mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
Merge pull request #11237 from wsengir/stage2-vectors
stage2: implement most vector operations in Sema and LLVM backend
This commit is contained in:
commit
7141356838
23
src/Air.zig
23
src/Air.zig
@ -308,6 +308,10 @@ pub const Inst = struct {
|
||||
/// `!=`. Result type is always bool.
|
||||
/// Uses the `bin_op` field.
|
||||
cmp_neq,
|
||||
/// Conditional between two vectors.
|
||||
/// Result type is always a vector of bools.
|
||||
/// Uses the `ty_pl` field, payload is `VectorCmp`.
|
||||
cmp_vector,
|
||||
|
||||
/// Conditional branch.
|
||||
/// Result type is always noreturn; no instructions in a block follow this one.
|
||||
@ -781,6 +785,20 @@ pub const Shuffle = struct {
|
||||
mask_len: u32,
|
||||
};
|
||||
|
||||
pub const VectorCmp = struct {
|
||||
lhs: Inst.Ref,
|
||||
rhs: Inst.Ref,
|
||||
op: u32,
|
||||
|
||||
pub fn compareOperator(self: VectorCmp) std.math.CompareOperator {
|
||||
return @intToEnum(std.math.CompareOperator, @truncate(u3, self.op));
|
||||
}
|
||||
|
||||
pub fn encodeOp(compare_operator: std.math.CompareOperator) u32 {
|
||||
return @enumToInt(compare_operator);
|
||||
}
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// 0. `Inst.Ref` for every outputs_len
|
||||
/// 1. `Inst.Ref` for every inputs_len
|
||||
@ -886,6 +904,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||
.shl_sat,
|
||||
.min,
|
||||
.max,
|
||||
.bool_and,
|
||||
.bool_or,
|
||||
=> return air.typeOf(datas[inst].bin_op.lhs),
|
||||
|
||||
.sqrt,
|
||||
@ -917,8 +937,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||
.is_non_err,
|
||||
.is_err_ptr,
|
||||
.is_non_err_ptr,
|
||||
.bool_and,
|
||||
.bool_or,
|
||||
=> return Type.initTag(.bool),
|
||||
|
||||
.const_ty => return Type.initTag(.type),
|
||||
@ -942,6 +960,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||
.aggregate_init,
|
||||
.union_init,
|
||||
.field_parent_ptr,
|
||||
.cmp_vector,
|
||||
=> return air.getRefType(datas[inst].ty_pl.ty),
|
||||
|
||||
.not,
|
||||
|
||||
@ -441,6 +441,10 @@ fn analyzeInst(
|
||||
const reduce = inst_datas[inst].reduce;
|
||||
return trackOperands(a, new_set, inst, main_tomb, .{ reduce.operand, .none, .none });
|
||||
},
|
||||
.cmp_vector => {
|
||||
const extra = a.air.extraData(Air.VectorCmp, inst_datas[inst].ty_pl.payload).data;
|
||||
return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });
|
||||
},
|
||||
.aggregate_init => {
|
||||
const ty_pl = inst_datas[inst].ty_pl;
|
||||
const aggregate_ty = a.air.getRefType(ty_pl.ty);
|
||||
|
||||
525
src/Sema.zig
525
src/Sema.zig
File diff suppressed because it is too large
Load Diff
@ -577,6 +577,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.cmp_gte => try self.airCmp(inst, .gte),
|
||||
.cmp_gt => try self.airCmp(inst, .gt),
|
||||
.cmp_neq => try self.airCmp(inst, .neq),
|
||||
.cmp_vector => try self.airCmpVector(inst),
|
||||
|
||||
.bool_and => try self.airBinOp(inst),
|
||||
.bool_or => try self.airBinOp(inst),
|
||||
@ -2713,6 +2714,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
|
||||
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = inst;
|
||||
return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
|
||||
}
|
||||
|
||||
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
|
||||
|
||||
|
||||
@ -567,6 +567,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.cmp_gte => try self.airCmp(inst, .gte),
|
||||
.cmp_gt => try self.airCmp(inst, .gt),
|
||||
.cmp_neq => try self.airCmp(inst, .neq),
|
||||
.cmp_vector => try self.airCmpVector(inst),
|
||||
|
||||
.bool_and => try self.airBinOp(inst),
|
||||
.bool_or => try self.airBinOp(inst),
|
||||
@ -2894,7 +2895,6 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
|
||||
const lhs_ty = self.air.typeOf(bin_op.lhs);
|
||||
|
||||
switch (lhs_ty.zigTypeTag()) {
|
||||
.Vector => return self.fail("TODO ARM cmp vectors", .{}),
|
||||
.Optional => return self.fail("TODO ARM cmp optionals", .{}),
|
||||
.Float => return self.fail("TODO ARM cmp floats", .{}),
|
||||
.Int, .Bool, .Pointer, .ErrorSet, .Enum => {
|
||||
@ -2929,6 +2929,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
|
||||
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = inst;
|
||||
return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
|
||||
}
|
||||
|
||||
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
|
||||
|
||||
|
||||
@ -537,6 +537,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.cmp_gte => try self.airCmp(inst, .gte),
|
||||
.cmp_gt => try self.airCmp(inst, .gt),
|
||||
.cmp_neq => try self.airCmp(inst, .neq),
|
||||
.cmp_vector => try self.airCmpVector(inst),
|
||||
|
||||
.bool_and => try self.airBoolOp(inst),
|
||||
.bool_or => try self.airBoolOp(inst),
|
||||
@ -1791,6 +1792,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
|
||||
// return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = inst;
|
||||
return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
|
||||
}
|
||||
|
||||
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
|
||||
|
||||
|
||||
@ -1309,6 +1309,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.cmp_lte => self.airCmp(inst, .lte),
|
||||
.cmp_lt => self.airCmp(inst, .lt),
|
||||
.cmp_neq => self.airCmp(inst, .neq),
|
||||
.cmp_vector => self.airCmpVector(inst),
|
||||
|
||||
.array_elem_val => self.airArrayElemVal(inst),
|
||||
.array_to_slice => self.airArrayToSlice(inst),
|
||||
@ -2222,6 +2223,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner
|
||||
return cmp_tmp;
|
||||
}
|
||||
|
||||
fn airCmpVector(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
_ = inst;
|
||||
return self.fail("TODO implement airCmpVector for wasm", .{});
|
||||
}
|
||||
|
||||
fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
const br = self.air.instructions.items(.data)[inst].br;
|
||||
const block = self.blocks.get(br.block_inst).?;
|
||||
|
||||
@ -658,6 +658,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.cmp_gte => try self.airCmp(inst, .gte),
|
||||
.cmp_gt => try self.airCmp(inst, .gt),
|
||||
.cmp_neq => try self.airCmp(inst, .neq),
|
||||
.cmp_vector => try self.airCmpVector(inst),
|
||||
|
||||
.bool_and => try self.airBoolOp(inst),
|
||||
.bool_or => try self.airBoolOp(inst),
|
||||
@ -3699,6 +3700,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
|
||||
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = inst;
|
||||
return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
|
||||
}
|
||||
|
||||
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
|
||||
const payload = try self.addExtra(Mir.DbgLineColumn{
|
||||
|
||||
@ -1715,6 +1715,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
|
||||
.cmp_eq => try airEquality(f, inst, "((", "=="),
|
||||
.cmp_neq => try airEquality(f, inst, "!((", "!="),
|
||||
|
||||
.cmp_vector => return f.fail("TODO: C backend: implement binary op for tag '{s}'", .{@tagName(Air.Inst.Tag.cmp_vector)}),
|
||||
|
||||
// bool_and and bool_or are non-short-circuit operations
|
||||
.bool_and => try airBinOp(f, inst, " & "),
|
||||
.bool_or => try airBinOp(f, inst, " | "),
|
||||
|
||||
@ -3375,6 +3375,7 @@ pub const FuncGen = struct {
|
||||
.cmp_lt => try self.airCmp(inst, .lt),
|
||||
.cmp_lte => try self.airCmp(inst, .lte),
|
||||
.cmp_neq => try self.airCmp(inst, .neq),
|
||||
.cmp_vector => try self.airCmpVector(inst),
|
||||
|
||||
.is_non_null => try self.airIsNonNull(inst, false, false, .NE),
|
||||
.is_non_null_ptr => try self.airIsNonNull(inst, true , false, .NE),
|
||||
@ -3640,6 +3641,20 @@ pub const FuncGen = struct {
|
||||
return self.cmp(lhs, rhs, operand_ty, op);
|
||||
}
|
||||
|
||||
fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
||||
if (self.liveness.isUnused(inst)) return null;
|
||||
|
||||
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
|
||||
const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
|
||||
|
||||
const lhs = try self.resolveInst(extra.lhs);
|
||||
const rhs = try self.resolveInst(extra.rhs);
|
||||
const vec_ty = self.air.typeOf(extra.lhs);
|
||||
const cmp_op = extra.compareOperator();
|
||||
|
||||
return self.cmp(lhs, rhs, vec_ty, cmp_op);
|
||||
}
|
||||
|
||||
fn cmp(
|
||||
self: *FuncGen,
|
||||
lhs: *const llvm.Value,
|
||||
@ -3650,9 +3665,10 @@ pub const FuncGen = struct {
|
||||
var int_buffer: Type.Payload.Bits = undefined;
|
||||
var opt_buffer: Type.Payload.ElemType = undefined;
|
||||
|
||||
const int_ty = switch (operand_ty.zigTypeTag()) {
|
||||
.Enum => operand_ty.intTagType(&int_buffer),
|
||||
.Int, .Bool, .Pointer, .ErrorSet => operand_ty,
|
||||
const scalar_ty = operand_ty.scalarType();
|
||||
const int_ty = switch (scalar_ty.zigTypeTag()) {
|
||||
.Enum => scalar_ty.intTagType(&int_buffer),
|
||||
.Int, .Bool, .Pointer, .ErrorSet => scalar_ty,
|
||||
.Optional => blk: {
|
||||
const payload_ty = operand_ty.optionalChild(&opt_buffer);
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime() or operand_ty.isPtrLikeOptional()) {
|
||||
@ -3944,10 +3960,11 @@ pub const FuncGen = struct {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
const operand_ty = self.air.typeOf(ty_op.operand);
|
||||
const operand_scalar_ty = operand_ty.scalarType();
|
||||
const dest_ty = self.air.typeOfIndex(inst);
|
||||
const dest_llvm_ty = try self.dg.llvmType(dest_ty);
|
||||
|
||||
if (operand_ty.isSignedInt()) {
|
||||
if (operand_scalar_ty.isSignedInt()) {
|
||||
return self.builder.buildSIToFP(operand, dest_llvm_ty, "");
|
||||
} else {
|
||||
return self.builder.buildUIToFP(operand, dest_llvm_ty, "");
|
||||
@ -3961,11 +3978,12 @@ pub const FuncGen = struct {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
const dest_ty = self.air.typeOfIndex(inst);
|
||||
const dest_scalar_ty = dest_ty.scalarType();
|
||||
const dest_llvm_ty = try self.dg.llvmType(dest_ty);
|
||||
|
||||
// TODO set fast math flag
|
||||
|
||||
if (dest_ty.isSignedInt()) {
|
||||
if (dest_scalar_ty.isSignedInt()) {
|
||||
return self.builder.buildFPToSI(operand, dest_llvm_ty, "");
|
||||
} else {
|
||||
return self.builder.buildFPToUI(operand, dest_llvm_ty, "");
|
||||
@ -4896,9 +4914,10 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isAnyFloat()) return self.builder.buildFAdd(lhs, rhs, "");
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildNSWAdd(lhs, rhs, "");
|
||||
if (scalar_ty.isAnyFloat()) return self.builder.buildFAdd(lhs, rhs, "");
|
||||
if (scalar_ty.isSignedInt()) return self.builder.buildNSWAdd(lhs, rhs, "");
|
||||
return self.builder.buildNUWAdd(lhs, rhs, "");
|
||||
}
|
||||
|
||||
@ -4919,9 +4938,10 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isAnyFloat()) return self.todo("saturating float add", .{});
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildSAddSat(lhs, rhs, "");
|
||||
if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});
|
||||
if (scalar_ty.isSignedInt()) return self.builder.buildSAddSat(lhs, rhs, "");
|
||||
|
||||
return self.builder.buildUAddSat(lhs, rhs, "");
|
||||
}
|
||||
@ -4933,9 +4953,10 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isAnyFloat()) return self.builder.buildFSub(lhs, rhs, "");
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildNSWSub(lhs, rhs, "");
|
||||
if (scalar_ty.isAnyFloat()) return self.builder.buildFSub(lhs, rhs, "");
|
||||
if (scalar_ty.isSignedInt()) return self.builder.buildNSWSub(lhs, rhs, "");
|
||||
return self.builder.buildNUWSub(lhs, rhs, "");
|
||||
}
|
||||
|
||||
@ -4956,9 +4977,10 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isAnyFloat()) return self.todo("saturating float sub", .{});
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildSSubSat(lhs, rhs, "");
|
||||
if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});
|
||||
if (scalar_ty.isSignedInt()) return self.builder.buildSSubSat(lhs, rhs, "");
|
||||
return self.builder.buildUSubSat(lhs, rhs, "");
|
||||
}
|
||||
|
||||
@ -4969,9 +4991,10 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isAnyFloat()) return self.builder.buildFMul(lhs, rhs, "");
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildNSWMul(lhs, rhs, "");
|
||||
if (scalar_ty.isAnyFloat()) return self.builder.buildFMul(lhs, rhs, "");
|
||||
if (scalar_ty.isSignedInt()) return self.builder.buildNSWMul(lhs, rhs, "");
|
||||
return self.builder.buildNUWMul(lhs, rhs, "");
|
||||
}
|
||||
|
||||
@ -4992,9 +5015,10 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isAnyFloat()) return self.todo("saturating float mul", .{});
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildSMulFixSat(lhs, rhs, "");
|
||||
if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});
|
||||
if (scalar_ty.isSignedInt()) return self.builder.buildSMulFixSat(lhs, rhs, "");
|
||||
return self.builder.buildUMulFixSat(lhs, rhs, "");
|
||||
}
|
||||
|
||||
@ -5015,12 +5039,13 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isRuntimeFloat()) {
|
||||
if (scalar_ty.isRuntimeFloat()) {
|
||||
const result = self.builder.buildFDiv(lhs, rhs, "");
|
||||
return self.callTrunc(result, inst_ty);
|
||||
}
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, "");
|
||||
if (scalar_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, "");
|
||||
return self.builder.buildUDiv(lhs, rhs, "");
|
||||
}
|
||||
|
||||
@ -5031,12 +5056,13 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isRuntimeFloat()) {
|
||||
if (scalar_ty.isRuntimeFloat()) {
|
||||
const result = self.builder.buildFDiv(lhs, rhs, "");
|
||||
return try self.callFloor(result, inst_ty);
|
||||
}
|
||||
if (inst_ty.isSignedInt()) {
|
||||
if (scalar_ty.isSignedInt()) {
|
||||
// const d = @divTrunc(a, b);
|
||||
// const r = @rem(a, b);
|
||||
// return if (r == 0) d else d - ((a < 0) ^ (b < 0));
|
||||
@ -5062,9 +5088,10 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isRuntimeFloat()) return self.builder.buildFDiv(lhs, rhs, "");
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildExactSDiv(lhs, rhs, "");
|
||||
if (scalar_ty.isRuntimeFloat()) return self.builder.buildFDiv(lhs, rhs, "");
|
||||
if (scalar_ty.isSignedInt()) return self.builder.buildExactSDiv(lhs, rhs, "");
|
||||
return self.builder.buildExactUDiv(lhs, rhs, "");
|
||||
}
|
||||
|
||||
@ -5075,9 +5102,10 @@ pub const FuncGen = struct {
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isRuntimeFloat()) return self.builder.buildFRem(lhs, rhs, "");
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildSRem(lhs, rhs, "");
|
||||
if (scalar_ty.isRuntimeFloat()) return self.builder.buildFRem(lhs, rhs, "");
|
||||
if (scalar_ty.isSignedInt()) return self.builder.buildSRem(lhs, rhs, "");
|
||||
return self.builder.buildURem(lhs, rhs, "");
|
||||
}
|
||||
|
||||
@ -5089,8 +5117,9 @@ pub const FuncGen = struct {
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const inst_llvm_ty = try self.dg.llvmType(inst_ty);
|
||||
const scalar_ty = inst_ty.scalarType();
|
||||
|
||||
if (inst_ty.isRuntimeFloat()) {
|
||||
if (scalar_ty.isRuntimeFloat()) {
|
||||
const a = self.builder.buildFRem(lhs, rhs, "");
|
||||
const b = self.builder.buildFAdd(a, rhs, "");
|
||||
const c = self.builder.buildFRem(b, rhs, "");
|
||||
@ -5098,7 +5127,7 @@ pub const FuncGen = struct {
|
||||
const ltz = self.builder.buildFCmp(.OLT, lhs, zero, "");
|
||||
return self.builder.buildSelect(ltz, c, a, "");
|
||||
}
|
||||
if (inst_ty.isSignedInt()) {
|
||||
if (scalar_ty.isSignedInt()) {
|
||||
const a = self.builder.buildSRem(lhs, rhs, "");
|
||||
const b = self.builder.buildNSWAdd(a, rhs, "");
|
||||
const c = self.builder.buildSRem(b, rhs, "");
|
||||
@ -5323,15 +5352,22 @@ pub const FuncGen = struct {
|
||||
if (self.liveness.isUnused(inst)) return null;
|
||||
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const lhs_type = self.air.typeOf(bin_op.lhs);
|
||||
|
||||
const lhs_ty = self.air.typeOf(bin_op.lhs);
|
||||
const rhs_ty = self.air.typeOf(bin_op.rhs);
|
||||
const lhs_scalar_ty = lhs_ty.scalarType();
|
||||
const rhs_scalar_ty = rhs_ty.scalarType();
|
||||
|
||||
const tg = self.dg.module.getTarget();
|
||||
const casted_rhs = if (self.air.typeOf(bin_op.rhs).bitSize(tg) < lhs_type.bitSize(tg))
|
||||
self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "")
|
||||
|
||||
const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
|
||||
self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_ty), "")
|
||||
else
|
||||
rhs;
|
||||
if (lhs_type.isSignedInt()) return self.builder.buildNSWShl(lhs, casted_rhs, "");
|
||||
if (lhs_scalar_ty.isSignedInt()) return self.builder.buildNSWShl(lhs, casted_rhs, "");
|
||||
return self.builder.buildNUWShl(lhs, casted_rhs, "");
|
||||
}
|
||||
|
||||
@ -5339,11 +5375,18 @@ pub const FuncGen = struct {
|
||||
if (self.liveness.isUnused(inst)) return null;
|
||||
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
|
||||
const lhs_type = self.air.typeOf(bin_op.lhs);
|
||||
const rhs_type = self.air.typeOf(bin_op.rhs);
|
||||
const lhs_scalar_ty = lhs_type.scalarType();
|
||||
const rhs_scalar_ty = rhs_type.scalarType();
|
||||
|
||||
const tg = self.dg.module.getTarget();
|
||||
const casted_rhs = if (self.air.typeOf(bin_op.rhs).bitSize(tg) < lhs_type.bitSize(tg))
|
||||
|
||||
const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
|
||||
self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "")
|
||||
else
|
||||
rhs;
|
||||
@ -5354,31 +5397,45 @@ pub const FuncGen = struct {
|
||||
if (self.liveness.isUnused(inst)) return null;
|
||||
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const lhs_type = self.air.typeOf(bin_op.lhs);
|
||||
|
||||
const lhs_ty = self.air.typeOf(bin_op.lhs);
|
||||
const rhs_ty = self.air.typeOf(bin_op.rhs);
|
||||
const lhs_scalar_ty = lhs_ty.scalarType();
|
||||
const rhs_scalar_ty = rhs_ty.scalarType();
|
||||
|
||||
const tg = self.dg.module.getTarget();
|
||||
const casted_rhs = if (self.air.typeOf(bin_op.rhs).bitSize(tg) < lhs_type.bitSize(tg))
|
||||
self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "")
|
||||
|
||||
const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
|
||||
self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_ty), "")
|
||||
else
|
||||
rhs;
|
||||
if (lhs_type.isSignedInt()) return self.builder.buildSShlSat(lhs, casted_rhs, "");
|
||||
if (lhs_scalar_ty.isSignedInt()) return self.builder.buildSShlSat(lhs, casted_rhs, "");
|
||||
return self.builder.buildUShlSat(lhs, casted_rhs, "");
|
||||
}
|
||||
|
||||
fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*const llvm.Value {
|
||||
if (self.liveness.isUnused(inst))
|
||||
return null;
|
||||
if (self.liveness.isUnused(inst)) return null;
|
||||
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
const lhs_type = self.air.typeOf(bin_op.lhs);
|
||||
|
||||
const lhs_ty = self.air.typeOf(bin_op.lhs);
|
||||
const rhs_ty = self.air.typeOf(bin_op.rhs);
|
||||
const lhs_scalar_ty = lhs_ty.scalarType();
|
||||
const rhs_scalar_ty = rhs_ty.scalarType();
|
||||
|
||||
const tg = self.dg.module.getTarget();
|
||||
const casted_rhs = if (self.air.typeOf(bin_op.rhs).bitSize(tg) < lhs_type.bitSize(tg))
|
||||
self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "")
|
||||
|
||||
const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
|
||||
self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_ty), "")
|
||||
else
|
||||
rhs;
|
||||
const is_signed_int = self.air.typeOfIndex(inst).isSignedInt();
|
||||
const is_signed_int = lhs_scalar_ty.isSignedInt();
|
||||
|
||||
if (is_exact) {
|
||||
if (is_signed_int) {
|
||||
@ -5506,7 +5563,8 @@ pub const FuncGen = struct {
|
||||
if (bitcast_ok) {
|
||||
const llvm_vector_ty = try self.dg.llvmType(operand_ty);
|
||||
const casted_ptr = self.builder.buildBitCast(array_ptr, llvm_vector_ty.pointerType(0), "");
|
||||
_ = self.builder.buildStore(operand, casted_ptr);
|
||||
const llvm_store = self.builder.buildStore(operand, casted_ptr);
|
||||
llvm_store.setAlignment(inst_ty.abiAlignment(target));
|
||||
} else {
|
||||
// If the ABI size of the element type is not evenly divisible by size in bits;
|
||||
// a simple bitcast will not work, and we fall back to extractelement.
|
||||
|
||||
@ -266,6 +266,7 @@ const Writer = struct {
|
||||
.mul_add => try w.writeMulAdd(s, inst),
|
||||
.shuffle => try w.writeShuffle(s, inst),
|
||||
.reduce => try w.writeReduce(s, inst),
|
||||
.cmp_vector => try w.writeCmpVector(s, inst),
|
||||
|
||||
.add_with_overflow,
|
||||
.sub_with_overflow,
|
||||
@ -402,6 +403,16 @@ const Writer = struct {
|
||||
try s.print(", {s}", .{@tagName(reduce.operation)});
|
||||
}
|
||||
|
||||
fn writeCmpVector(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
|
||||
const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data;
|
||||
|
||||
try s.print("{s}, ", .{@tagName(extra.compareOperator())});
|
||||
try w.writeOperand(s, inst, 0, extra.lhs);
|
||||
try s.writeAll(", ");
|
||||
try w.writeOperand(s, inst, 1, extra.rhs);
|
||||
}
|
||||
|
||||
fn writeFence(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const atomic_order = w.air.instructions.items(.data)[inst].fence;
|
||||
|
||||
@ -470,8 +481,8 @@ const Writer = struct {
|
||||
}
|
||||
|
||||
fn writeFieldParentPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const pl_op = w.air.instructions.items(.data)[inst].ty_pl;
|
||||
const extra = w.air.extraData(Air.FieldParentPtr, pl_op.payload).data;
|
||||
const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
|
||||
const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
|
||||
|
||||
try w.writeOperand(s, inst, 0, extra.field_ptr);
|
||||
try s.print(", {d}", .{extra.field_index});
|
||||
|
||||
769
src/value.zig
769
src/value.zig
File diff suppressed because it is too large
Load Diff
@ -3,15 +3,17 @@ const builtin = @import("builtin");
|
||||
const mem = std.mem;
|
||||
const math = std.math;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const expectApproxEqRel = std.testing.expectApproxEqRel;
|
||||
const Vector = std.meta.Vector;
|
||||
|
||||
test "implicit cast vector to array - bool" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
const a: Vector(4, bool) = [_]bool{ true, false, true, false };
|
||||
const a: @Vector(4, bool) = [_]bool{ true, false, true, false };
|
||||
const result_array: [4]bool = a;
|
||||
try expect(mem.eql(bool, &result_array, &[4]bool{ true, false, true, false }));
|
||||
}
|
||||
@ -21,15 +23,20 @@ test "implicit cast vector to array - bool" {
|
||||
}
|
||||
|
||||
test "vector wrap operators" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
|
||||
var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
|
||||
var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
|
||||
var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
|
||||
try expect(mem.eql(i32, &@as([4]i32, v +% x), &[4]i32{ -2147483648, 2147483645, 33, 44 }));
|
||||
try expect(mem.eql(i32, &@as([4]i32, v -% x), &[4]i32{ 2147483646, 2147483647, 27, 36 }));
|
||||
try expect(mem.eql(i32, &@as([4]i32, v *% x), &[4]i32{ 2147483647, 2, 90, 160 }));
|
||||
var z: Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 };
|
||||
var z: @Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 };
|
||||
try expect(mem.eql(i32, &@as([4]i32, -%z), &[4]i32{ -1, -2, -3, -2147483648 }));
|
||||
}
|
||||
};
|
||||
@ -38,11 +45,16 @@ test "vector wrap operators" {
|
||||
}
|
||||
|
||||
test "vector bin compares with mem.eql" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
|
||||
var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 };
|
||||
var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
|
||||
var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 };
|
||||
try expect(mem.eql(bool, &@as([4]bool, v == x), &[4]bool{ false, false, true, false }));
|
||||
try expect(mem.eql(bool, &@as([4]bool, v != x), &[4]bool{ true, true, false, true }));
|
||||
try expect(mem.eql(bool, &@as([4]bool, v < x), &[4]bool{ false, true, false, false }));
|
||||
@ -56,11 +68,16 @@ test "vector bin compares with mem.eql" {
|
||||
}
|
||||
|
||||
test "vector int operators" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };
|
||||
var x: Vector(4, i32) = [4]i32{ 1, 2, 3, 4 };
|
||||
var v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };
|
||||
var x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 };
|
||||
try expect(mem.eql(i32, &@as([4]i32, v + x), &[4]i32{ 11, 22, 33, 44 }));
|
||||
try expect(mem.eql(i32, &@as([4]i32, v - x), &[4]i32{ 9, 18, 27, 36 }));
|
||||
try expect(mem.eql(i32, &@as([4]i32, v * x), &[4]i32{ 10, 40, 90, 160 }));
|
||||
@ -72,11 +89,16 @@ test "vector int operators" {
|
||||
}
|
||||
|
||||
test "vector float operators" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: Vector(4, f32) = [4]f32{ 10, 20, 30, 40 };
|
||||
var x: Vector(4, f32) = [4]f32{ 1, 2, 3, 4 };
|
||||
var v: @Vector(4, f32) = [4]f32{ 10, 20, 30, 40 };
|
||||
var x: @Vector(4, f32) = [4]f32{ 1, 2, 3, 4 };
|
||||
try expect(mem.eql(f32, &@as([4]f32, v + x), &[4]f32{ 11, 22, 33, 44 }));
|
||||
try expect(mem.eql(f32, &@as([4]f32, v - x), &[4]f32{ 9, 18, 27, 36 }));
|
||||
try expect(mem.eql(f32, &@as([4]f32, v * x), &[4]f32{ 10, 40, 90, 160 }));
|
||||
@ -88,11 +110,16 @@ test "vector float operators" {
|
||||
}
|
||||
|
||||
test "vector bit operators" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
|
||||
var x: Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 };
|
||||
var v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
|
||||
var x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 };
|
||||
try expect(mem.eql(u8, &@as([4]u8, v ^ x), &[4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 }));
|
||||
try expect(mem.eql(u8, &@as([4]u8, v | x), &[4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 }));
|
||||
try expect(mem.eql(u8, &@as([4]u8, v & x), &[4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 }));
|
||||
@ -103,10 +130,15 @@ test "vector bit operators" {
|
||||
}
|
||||
|
||||
test "implicit cast vector to array" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var a: Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
|
||||
var a: @Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
|
||||
var result_array: [4]i32 = a;
|
||||
result_array = a;
|
||||
try expect(mem.eql(i32, &result_array, &[4]i32{ 1, 2, 3, 4 }));
|
||||
@ -117,34 +149,50 @@ test "implicit cast vector to array" {
|
||||
}
|
||||
|
||||
test "array to vector" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var foo: f32 = 3.14;
|
||||
var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
|
||||
var vec: Vector(4, f32) = arr;
|
||||
_ = vec;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var foo: f32 = 3.14;
|
||||
var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
|
||||
var vec: @Vector(4, f32) = arr;
|
||||
try expect(mem.eql(f32, &@as([4]f32, vec), &arr));
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "vector casts of sizes not divisible by 8" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
{
|
||||
var v: Vector(4, u3) = [4]u3{ 5, 2, 3, 0 };
|
||||
var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0 };
|
||||
var x: [4]u3 = v;
|
||||
try expect(mem.eql(u3, &x, &@as([4]u3, v)));
|
||||
}
|
||||
{
|
||||
var v: Vector(4, u2) = [4]u2{ 1, 2, 3, 0 };
|
||||
var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0 };
|
||||
var x: [4]u2 = v;
|
||||
try expect(mem.eql(u2, &x, &@as([4]u2, v)));
|
||||
}
|
||||
{
|
||||
var v: Vector(4, u1) = [4]u1{ 1, 0, 1, 0 };
|
||||
var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0 };
|
||||
var x: [4]u1 = v;
|
||||
try expect(mem.eql(u1, &x, &@as([4]u1, v)));
|
||||
}
|
||||
{
|
||||
var v: Vector(4, bool) = [4]bool{ false, false, true, false };
|
||||
var v: @Vector(4, bool) = [4]bool{ false, false, true, false };
|
||||
var x: [4]bool = v;
|
||||
try expect(mem.eql(bool, &x, &@as([4]bool, v)));
|
||||
}
|
||||
@ -155,14 +203,19 @@ test "vector casts of sizes not divisible by 8" {
|
||||
}
|
||||
|
||||
test "vector @splat" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn testForT(comptime N: comptime_int, v: anytype) !void {
|
||||
const T = @TypeOf(v);
|
||||
var vec = @splat(N, v);
|
||||
try expectEqual(Vector(N, T), @TypeOf(vec));
|
||||
try expect(@Vector(N, T) == @TypeOf(vec));
|
||||
var as_array = @as([N]T, vec);
|
||||
for (as_array) |elem| try expectEqual(v, elem);
|
||||
for (as_array) |elem| try expect(v == elem);
|
||||
}
|
||||
fn doTheTest() !void {
|
||||
// Splats with multiple-of-8 bit types that fill a 128bit vector.
|
||||
@ -191,10 +244,15 @@ test "vector @splat" {
|
||||
}
|
||||
|
||||
test "load vector elements via comptime index" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
|
||||
var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
|
||||
try expect(v[0] == 1);
|
||||
try expect(v[1] == 2);
|
||||
try expect(loadv(&v[2]) == 3);
|
||||
@ -209,10 +267,15 @@ test "load vector elements via comptime index" {
|
||||
}
|
||||
|
||||
test "store vector elements via comptime index" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
|
||||
var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
|
||||
|
||||
v[2] = 42;
|
||||
try expect(v[1] == 5);
|
||||
@ -233,10 +296,15 @@ test "store vector elements via comptime index" {
|
||||
}
|
||||
|
||||
test "load vector elements via runtime index" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
|
||||
var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
|
||||
var i: u32 = 0;
|
||||
try expect(v[i] == 1);
|
||||
i += 1;
|
||||
@ -251,10 +319,15 @@ test "load vector elements via runtime index" {
|
||||
}
|
||||
|
||||
test "store vector elements via runtime index" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
|
||||
var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
|
||||
var i: u32 = 2;
|
||||
v[i] = 1;
|
||||
try expect(v[1] == 5);
|
||||
@ -270,9 +343,14 @@ test "store vector elements via runtime index" {
|
||||
}
|
||||
|
||||
test "initialize vector which is a struct field" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const Vec4Obj = struct {
|
||||
data: Vector(4, f32),
|
||||
data: @Vector(4, f32),
|
||||
};
|
||||
|
||||
const S = struct {
|
||||
@ -288,33 +366,38 @@ test "initialize vector which is a struct field" {
|
||||
}
|
||||
|
||||
test "vector comparison operators" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
{
|
||||
const v1: Vector(4, bool) = [_]bool{ true, false, true, false };
|
||||
const v2: Vector(4, bool) = [_]bool{ false, true, false, true };
|
||||
try expectEqual(@splat(4, true), v1 == v1);
|
||||
try expectEqual(@splat(4, false), v1 == v2);
|
||||
try expectEqual(@splat(4, true), v1 != v2);
|
||||
try expectEqual(@splat(4, false), v2 != v2);
|
||||
var v1: @Vector(4, bool) = [_]bool{ true, false, true, false };
|
||||
var v2: @Vector(4, bool) = [_]bool{ false, true, false, true };
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 == v1)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v1 == v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 != v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v2 != v2)));
|
||||
}
|
||||
{
|
||||
const v1 = @splat(4, @as(u32, 0xc0ffeeee));
|
||||
const v2: Vector(4, c_uint) = v1;
|
||||
const v3 = @splat(4, @as(u32, 0xdeadbeef));
|
||||
try expectEqual(@splat(4, true), v1 == v2);
|
||||
try expectEqual(@splat(4, false), v1 == v3);
|
||||
try expectEqual(@splat(4, true), v1 != v3);
|
||||
try expectEqual(@splat(4, false), v1 != v2);
|
||||
var v1 = @splat(4, @as(u32, 0xc0ffeeee));
|
||||
var v2: @Vector(4, c_uint) = v1;
|
||||
var v3 = @splat(4, @as(u32, 0xdeadbeef));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 == v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v1 == v3)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 != v3)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v1 != v2)));
|
||||
}
|
||||
{
|
||||
// Comptime-known LHS/RHS
|
||||
var v1: @Vector(4, u32) = [_]u32{ 2, 1, 2, 1 };
|
||||
const v2 = @splat(4, @as(u32, 2));
|
||||
const v3: @Vector(4, bool) = [_]bool{ true, false, true, false };
|
||||
try expectEqual(v3, v1 == v2);
|
||||
try expectEqual(v3, v2 == v1);
|
||||
try expect(mem.eql(bool, &@as([4]bool, v3), &@as([4]bool, v1 == v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, v3), &@as([4]bool, v2 == v1)));
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -323,43 +406,48 @@ test "vector comparison operators" {
|
||||
}
|
||||
|
||||
test "vector division operators" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTestDiv(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void {
|
||||
fn doTheTestDiv(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void {
|
||||
if (!comptime std.meta.trait.isSignedInt(T)) {
|
||||
const d0 = x / y;
|
||||
for (@as([4]T, d0)) |v, i| {
|
||||
try expectEqual(x[i] / y[i], v);
|
||||
try expect(x[i] / y[i] == v);
|
||||
}
|
||||
}
|
||||
const d1 = @divExact(x, y);
|
||||
for (@as([4]T, d1)) |v, i| {
|
||||
try expectEqual(@divExact(x[i], y[i]), v);
|
||||
try expect(@divExact(x[i], y[i]) == v);
|
||||
}
|
||||
const d2 = @divFloor(x, y);
|
||||
for (@as([4]T, d2)) |v, i| {
|
||||
try expectEqual(@divFloor(x[i], y[i]), v);
|
||||
try expect(@divFloor(x[i], y[i]) == v);
|
||||
}
|
||||
const d3 = @divTrunc(x, y);
|
||||
for (@as([4]T, d3)) |v, i| {
|
||||
try expectEqual(@divTrunc(x[i], y[i]), v);
|
||||
try expect(@divTrunc(x[i], y[i]) == v);
|
||||
}
|
||||
}
|
||||
|
||||
fn doTheTestMod(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void {
|
||||
fn doTheTestMod(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void {
|
||||
if ((!comptime std.meta.trait.isSignedInt(T)) and @typeInfo(T) != .Float) {
|
||||
const r0 = x % y;
|
||||
for (@as([4]T, r0)) |v, i| {
|
||||
try expectEqual(x[i] % y[i], v);
|
||||
try expect(x[i] % y[i] == v);
|
||||
}
|
||||
}
|
||||
const r1 = @mod(x, y);
|
||||
for (@as([4]T, r1)) |v, i| {
|
||||
try expectEqual(@mod(x[i], y[i]), v);
|
||||
try expect(@mod(x[i], y[i]) == v);
|
||||
}
|
||||
const r2 = @rem(x, y);
|
||||
for (@as([4]T, r2)) |v, i| {
|
||||
try expectEqual(@rem(x[i], y[i]), v);
|
||||
try expect(@rem(x[i], y[i]) == v);
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,12 +494,17 @@ test "vector division operators" {
|
||||
}
|
||||
|
||||
test "vector bitwise not operator" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTestNot(comptime T: type, x: Vector(4, T)) !void {
|
||||
fn doTheTestNot(comptime T: type, x: @Vector(4, T)) !void {
|
||||
var y = ~x;
|
||||
for (@as([4]T, y)) |v, i| {
|
||||
try expectEqual(~x[i], v);
|
||||
try expect(~x[i] == v);
|
||||
}
|
||||
}
|
||||
fn doTheTest() !void {
|
||||
@ -432,23 +525,28 @@ test "vector bitwise not operator" {
|
||||
}
|
||||
|
||||
test "vector shift operators" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTestShift(x: anytype, y: anytype) !void {
|
||||
const N = @typeInfo(@TypeOf(x)).Array.len;
|
||||
const TX = @typeInfo(@TypeOf(x)).Array.child;
|
||||
const TY = @typeInfo(@TypeOf(y)).Array.child;
|
||||
|
||||
var xv = @as(Vector(N, TX), x);
|
||||
var yv = @as(Vector(N, TY), y);
|
||||
var xv = @as(@Vector(N, TX), x);
|
||||
var yv = @as(@Vector(N, TY), y);
|
||||
|
||||
var z0 = xv >> yv;
|
||||
for (@as([N]TX, z0)) |v, i| {
|
||||
try expectEqual(x[i] >> y[i], v);
|
||||
try expect(x[i] >> y[i] == v);
|
||||
}
|
||||
var z1 = xv << yv;
|
||||
for (@as([N]TX, z1)) |v, i| {
|
||||
try expectEqual(x[i] << y[i], v);
|
||||
try expect(x[i] << y[i] == v);
|
||||
}
|
||||
}
|
||||
fn doTheTestShiftExact(x: anytype, y: anytype, dir: enum { Left, Right }) !void {
|
||||
@ -456,13 +554,13 @@ test "vector shift operators" {
|
||||
const TX = @typeInfo(@TypeOf(x)).Array.child;
|
||||
const TY = @typeInfo(@TypeOf(y)).Array.child;
|
||||
|
||||
var xv = @as(Vector(N, TX), x);
|
||||
var yv = @as(Vector(N, TY), y);
|
||||
var xv = @as(@Vector(N, TX), x);
|
||||
var yv = @as(@Vector(N, TY), y);
|
||||
|
||||
var z = if (dir == .Left) @shlExact(xv, yv) else @shrExact(xv, yv);
|
||||
for (@as([N]TX, z)) |v, i| {
|
||||
const check = if (dir == .Left) x[i] << y[i] else x[i] >> y[i];
|
||||
try expectEqual(check, v);
|
||||
try expect(check == v);
|
||||
}
|
||||
}
|
||||
fn doTheTest() !void {
|
||||
@ -663,11 +761,16 @@ test "vector reduce operation" {
|
||||
}
|
||||
|
||||
test "mask parameter of @shuffle is comptime scope" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
const __v4hi = std.meta.Vector(4, i16);
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const __v4hi = @Vector(4, i16);
|
||||
var v4_a = __v4hi{ 0, 0, 0, 0 };
|
||||
var v4_b = __v4hi{ 0, 0, 0, 0 };
|
||||
var shuffled: __v4hi = @shuffle(i16, v4_a, v4_b, std.meta.Vector(4, i32){
|
||||
var shuffled: __v4hi = @shuffle(i16, v4_a, v4_b, @Vector(4, i32){
|
||||
std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len),
|
||||
std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len),
|
||||
std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len),
|
||||
@ -677,13 +780,30 @@ test "mask parameter of @shuffle is comptime scope" {
|
||||
}
|
||||
|
||||
test "saturating add" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
const u8x3 = std.meta.Vector(3, u8);
|
||||
try expectEqual(u8x3{ 255, 255, 255 }, (u8x3{ 255, 254, 1 } +| u8x3{ 1, 2, 255 }));
|
||||
const i8x3 = std.meta.Vector(3, i8);
|
||||
try expectEqual(i8x3{ 127, 127, 127 }, (i8x3{ 127, 126, 1 } +| i8x3{ 1, 2, 127 }));
|
||||
{ // Broken out to avoid https://github.com/ziglang/zig/issues/11251
|
||||
const u8x3 = @Vector(3, u8);
|
||||
var lhs = u8x3{ 255, 254, 1 };
|
||||
var rhs = u8x3{ 1, 2, 255 };
|
||||
var result = lhs +| rhs;
|
||||
const expected = u8x3{ 255, 255, 255 };
|
||||
try expect(mem.eql(u8, &@as([3]u8, expected), &@as([3]u8, result)));
|
||||
}
|
||||
{ // Broken out to avoid https://github.com/ziglang/zig/issues/11251
|
||||
const i8x3 = @Vector(3, i8);
|
||||
var lhs = i8x3{ 127, 126, 1 };
|
||||
var rhs = i8x3{ 1, 2, 127 };
|
||||
var result = lhs +| rhs;
|
||||
const expected = i8x3{ 127, 127, 127 };
|
||||
try expect(mem.eql(i8, &@as([3]i8, expected), &@as([3]i8, result)));
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
@ -691,11 +811,21 @@ test "saturating add" {
|
||||
}
|
||||
|
||||
test "saturating subtraction" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
const u8x3 = std.meta.Vector(3, u8);
|
||||
try expectEqual(u8x3{ 0, 0, 0 }, (u8x3{ 0, 0, 0 } -| u8x3{ 255, 255, 255 }));
|
||||
// Broken out to avoid https://github.com/ziglang/zig/issues/11251
|
||||
const u8x3 = @Vector(3, u8);
|
||||
var lhs = u8x3{ 0, 0, 0 };
|
||||
var rhs = u8x3{ 255, 255, 255 };
|
||||
var result = lhs -| rhs;
|
||||
const expected = u8x3{ 0, 0, 0 };
|
||||
try expect(mem.eql(u8, &@as([3]u8, expected), &@as([3]u8, result)));
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
@ -703,14 +833,24 @@ test "saturating subtraction" {
|
||||
}
|
||||
|
||||
test "saturating multiplication" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
// TODO: once #9660 has been solved, remove this line
|
||||
if (builtin.target.cpu.arch == .wasm32) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
const u8x3 = std.meta.Vector(3, u8);
|
||||
try expectEqual(u8x3{ 255, 255, 255 }, (u8x3{ 2, 2, 2 } *| u8x3{ 255, 255, 255 }));
|
||||
// Broken out to avoid https://github.com/ziglang/zig/issues/11251
|
||||
const u8x3 = @Vector(3, u8);
|
||||
var lhs = u8x3{ 2, 2, 2 };
|
||||
var rhs = u8x3{ 255, 255, 255 };
|
||||
var result = lhs *| rhs;
|
||||
const expected = u8x3{ 255, 255, 255 };
|
||||
try expect(mem.eql(u8, &@as([3]u8, expected), &@as([3]u8, result)));
|
||||
}
|
||||
};
|
||||
|
||||
@ -719,11 +859,21 @@ test "saturating multiplication" {
|
||||
}
|
||||
|
||||
test "saturating shift-left" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
const u8x3 = std.meta.Vector(3, u8);
|
||||
try expectEqual(u8x3{ 255, 255, 255 }, (u8x3{ 255, 255, 255 } <<| u8x3{ 1, 1, 1 }));
|
||||
// Broken out to avoid https://github.com/ziglang/zig/issues/11251
|
||||
const u8x3 = @Vector(3, u8);
|
||||
var lhs = u8x3{ 1, 1, 1 };
|
||||
var rhs = u8x3{ 255, 255, 255 };
|
||||
var result = lhs <<| rhs;
|
||||
const expected = u8x3{ 255, 255, 255 };
|
||||
try expect(mem.eql(u8, &@as([3]u8, expected), &@as([3]u8, result)));
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user