From 76f53960778e84ab49730edb77b85490b07fbea2 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Sun, 14 Jul 2019 09:22:37 -0500 Subject: @byteSwap on vectors --- src/ir.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 10 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index cbc00f0cfe..e8ef45a116 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -25253,16 +25253,42 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct } static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { - ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); - if (type_is_invalid(int_type)) + IrInstruction *op = instruction->op->child; + ZigType *type_expr = ir_resolve_type(ira, instruction->type->child); + if (type_is_invalid(type_expr)) return ira->codegen->invalid_instruction; - IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + if (type_expr->id != ZigTypeIdInt) { + ir_add_error(ira, instruction->type, + buf_sprintf("expected integer type, found '%s'", buf_ptr(&type_expr->name))); + if (type_expr->id == ZigTypeIdVector && + type_expr->data.vector.elem_type->id == ZigTypeIdInt) + ir_add_error(ira, instruction->type, + buf_sprintf("represent vectors with their scalar types, i.e. '%s'", + buf_ptr(&type_expr->data.vector.elem_type->name))); + return ira->codegen->invalid_instruction; + } + ZigType *int_type = type_expr; + + ZigType *expr_type = op->value.type; + bool is_vector = expr_type->id == ZigTypeIdVector; + ZigType *ret_type = int_type; + if (is_vector) + ret_type = get_vector_type(ira->codegen, expr_type->data.vector.len, int_type); + + op = ir_implicit_cast(ira, instruction->op->child, ret_type); if (type_is_invalid(op->value.type)) return ira->codegen->invalid_instruction; if (int_type->data.integral.bit_count == 0) { - IrInstruction *result = ir_const(ira, &instruction->base, int_type); + IrInstruction *result = ir_const(ira, &instruction->base, ret_type); + if (is_vector) { + expand_undef_array(ira->codegen, &result->value); + result->value.data.x_array.data.s_none.elements = + allocate(expr_type->data.vector.len); + for (unsigned i = 0; i < expr_type->data.vector.len; i++) + bigint_init_unsigned(&result->value.data.x_array.data.s_none.elements[i].data.x_bigint, 0); + } bigint_init_unsigned(&result->value.data.x_bigint, 0); return result; } @@ -25282,20 +25308,36 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction if (val == nullptr) return ira->codegen->invalid_instruction; if (val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, int_type); + return ir_const_undef(ira, &instruction->base, ret_type); - IrInstruction *result = ir_const(ira, &instruction->base, int_type); + IrInstruction *result = ir_const(ira, &instruction->base, ret_type); size_t buf_size = int_type->data.integral.bit_count / 8; uint8_t *buf = allocate_nonzero(buf_size); - bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true); - bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false, - int_type->data.integral.is_signed); + if (is_vector) { + expand_undef_array(ira->codegen, &result->value); + result->value.data.x_array.data.s_none.elements = + allocate(expr_type->data.vector.len); + for (unsigned i = 0; i < expr_type->data.vector.len; i++) { + ConstExprValue *cur = &val->data.x_array.data.s_none.elements[i]; + result->value.data.x_array.data.s_none.elements[i].special = cur->special; + if (cur->special == ConstValSpecialUndef) + continue; + bigint_write_twos_complement(&cur->data.x_bigint, buf, int_type->data.integral.bit_count, true); + bigint_read_twos_complement(&result->value.data.x_array.data.s_none.elements[i].data.x_bigint, + buf, int_type->data.integral.bit_count, false, + int_type->data.integral.is_signed); + } + } else { + bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true); + bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false, + int_type->data.integral.is_signed); + } return result; } IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope, instruction->base.source_node, nullptr, op); - result->value.type = int_type; + result->value.type = ret_type; return result; } -- cgit v1.2.3 From 380c8ec2c95fa8d732c141c705d9940629eb2012 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 19 Sep 2019 00:59:04 -0400 Subject: implement runtime `@byteSwap` and other fixups * update docs for `@byteSwap`. * fix hash & eql functions for ZigLLVMFnIdBswap not updated to include vector len. this was causing incorrect bswap function being called in unrelated code * fix `@byteSwap` behavior tests only testing comptime and not runtime operations * implement runtime `@byteSwap` * fix incorrect logic in ir_render_vector_to_array and ir_render_array_to_vector with regards to whether or not to bitcast * `@byteSwap` accepts an array operand which it will cast to vector * simplify `@byteSwap` semantic analysis code and various fixes --- doc/langref.html.in | 11 ++++- src/analyze.cpp | 6 ++- src/codegen.cpp | 23 ++++++---- src/ir.cpp | 91 ++++++++++++++++++++------------------- test/stage1/behavior/byteswap.zig | 89 +++++++++++++++++++++++--------------- 5 files changed, 129 insertions(+), 91 deletions(-) (limited to 'src/ir.cpp') diff --git a/doc/langref.html.in b/doc/langref.html.in index 8a303640e6..61fc06fd02 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6542,12 +6542,21 @@ async fn func(y: *i32) void { {#header_close#} {#header_open|@byteSwap#} -
{#syntax#}@byteSwap(comptime T: type, integer: T) T{#endsyntax#}
+
{#syntax#}@byteSwap(comptime T: type, operand: T) T{#endsyntax#}

{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.

+

{#syntax#}operand{#endsyntax#} may be an {#link|integer|Integers#} or {#link|vector|Vectors#}.

Swaps the byte order of the integer. This converts a big endian integer to a little endian integer, and converts a little endian integer to a big endian integer.

+

+ Note that for the purposes of memory layout with respect to endianness, the integer type should be + related to the number of bytes reported by {#link|@sizeOf#} bytes. This is demonstrated with + {#syntax#}u24{#endsyntax#}. {#syntax#}@sizeOf(u24) == 4{#endsyntax#}, which means that a + {#syntax#}u24{#endsyntax#} stored in memory takes 4 bytes, and those 4 bytes are what are swapped on + a little vs big endian system. On the other hand, if {#syntax#}T{#endsyntax#} is specified to + be {#syntax#}u24{#endsyntax#}, then only 3 bytes are reversed. +

{#header_close#} {#header_open|@bitReverse#} diff --git a/src/analyze.cpp b/src/analyze.cpp index ac70d5646f..66b72b935d 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -6896,7 +6896,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) { return (uint32_t)(x.data.floating.bit_count) * ((uint32_t)x.id + 1025) + (uint32_t)(x.data.floating.vector_len) * (((uint32_t)x.id << 5) + 1025); case ZigLLVMFnIdBswap: - return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335; + return (uint32_t)(x.data.bswap.bit_count) * ((uint32_t)3661994335) + + (uint32_t)(x.data.bswap.vector_len) * (((uint32_t)x.id << 5) + 1025); case ZigLLVMFnIdBitReverse: return (uint32_t)(x.data.bit_reverse.bit_count) * (uint32_t)2621398431; case ZigLLVMFnIdOverflowArithmetic: @@ -6919,7 +6920,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { case ZigLLVMFnIdPopCount: return a.data.pop_count.bit_count == b.data.pop_count.bit_count; case ZigLLVMFnIdBswap: - return a.data.bswap.bit_count == b.data.bswap.bit_count; + return a.data.bswap.bit_count == b.data.bswap.bit_count && + a.data.bswap.vector_len == b.data.bswap.vector_len; case ZigLLVMFnIdBitReverse: return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count; case ZigLLVMFnIdFloatOp: diff --git a/src/codegen.cpp b/src/codegen.cpp index 6a575d32a2..54c02b288a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4509,9 +4509,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFn bool is_vector = expr_type->id == ZigTypeIdVector; ZigType *int_type = is_vector ? expr_type->data.vector.elem_type : expr_type; assert(int_type->id == ZigTypeIdInt); - uint32_t vector_len = 0; - if (is_vector) - vector_len = expr_type->data.vector.len; + uint32_t vector_len = is_vector ? expr_type->data.vector.len : 0; ZigLLVMFnKey key = {}; const char *fn_name; uint32_t n_args; @@ -5563,16 +5561,23 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInst // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed, int_type->data.integral.bit_count + 8); - if (is_vector) + LLVMValueRef shift_amt = LLVMConstInt(get_llvm_type(g, extended_type), 8, false); + if (is_vector) { extended_type = get_vector_type(g, expr_type->data.vector.len, extended_type); + LLVMValueRef *values = allocate_nonzero(expr_type->data.vector.len); + for (uint32_t i = 0; i < expr_type->data.vector.len; i += 1) { + values[i] = shift_amt; + } + shift_amt = LLVMConstVector(values, expr_type->data.vector.len); + free(values); + } // aabbcc LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), ""); // 00aabbcc LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap); LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, ""); // ccbbaa00 - LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, - LLVMConstInt(get_llvm_type(g, extended_type), 8, false), ""); + LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, shift_amt, ""); // 00ccbbaa return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, expr_type), ""); } @@ -5595,7 +5600,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab LLVMValueRef vector = ir_llvm_value(g, instruction->vector); ZigType *elem_type = array_type->data.array.child_type; - bool bitcast_ok = (elem_type->size_in_bits * 8) == elem_type->abi_size; + bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8; if (bitcast_ok) { LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc, LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), ""); @@ -5629,7 +5634,7 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type); ZigType *elem_type = vector_type->data.vector.elem_type; - bool bitcast_ok = (elem_type->size_in_bits * 8) == elem_type->abi_size; + bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8; if (bitcast_ok) { LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, LLVMPointerType(vector_type_ref, 0), ""); @@ -8902,7 +8907,7 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append(g->framework_dirs.at(i)); } - //note(dimenus): appending libc headers before c_headers breaks intrinsics + //note(dimenus): appending libc headers before c_headers breaks intrinsics //and other compiler specific items // According to Rich Felker libc headers are supposed to go before C language headers. args.append("-isystem"); diff --git a/src/ir.cpp b/src/ir.cpp index e8ef45a116..1eba53ef45 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11068,8 +11068,15 @@ static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) { return ira->codegen->builtin_types.entry_invalid; if (ty->id != ZigTypeIdInt) { - ir_add_error(ira, type_value, + ErrorMsg *msg = ir_add_error(ira, type_value, buf_sprintf("expected integer type, found '%s'", buf_ptr(&ty->name))); + if (ty->id == ZigTypeIdVector && + ty->data.vector.elem_type->id == ZigTypeIdInt) + { + add_error_note(ira->codegen, msg, type_value->source_node, + buf_sprintf("represent vectors with their element types, i.e. '%s'", + buf_ptr(&ty->data.vector.elem_type->name))); + } return ira->codegen->builtin_types.entry_invalid; } @@ -25253,47 +25260,35 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct } static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { - IrInstruction *op = instruction->op->child; - ZigType *type_expr = ir_resolve_type(ira, instruction->type->child); - if (type_is_invalid(type_expr)) + Error err; + + ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); + if (type_is_invalid(int_type)) return ira->codegen->invalid_instruction; - if (type_expr->id != ZigTypeIdInt) { - ir_add_error(ira, instruction->type, - buf_sprintf("expected integer type, found '%s'", buf_ptr(&type_expr->name))); - if (type_expr->id == ZigTypeIdVector && - type_expr->data.vector.elem_type->id == ZigTypeIdInt) - ir_add_error(ira, instruction->type, - buf_sprintf("represent vectors with their scalar types, i.e. '%s'", - buf_ptr(&type_expr->data.vector.elem_type->name))); + IrInstruction *uncasted_op = instruction->op->child; + if (type_is_invalid(uncasted_op->value.type)) return ira->codegen->invalid_instruction; + + uint32_t vector_len; // UINT32_MAX means not a vector + if (uncasted_op->value.type->id == ZigTypeIdArray && + is_valid_vector_elem_type(uncasted_op->value.type->data.array.child_type)) + { + vector_len = uncasted_op->value.type->data.array.len; + } else if (uncasted_op->value.type->id == ZigTypeIdVector) { + vector_len = uncasted_op->value.type->data.vector.len; + } else { + vector_len = UINT32_MAX; } - ZigType *int_type = type_expr; - ZigType *expr_type = op->value.type; - bool is_vector = expr_type->id == ZigTypeIdVector; - ZigType *ret_type = int_type; - if (is_vector) - ret_type = get_vector_type(ira->codegen, expr_type->data.vector.len, int_type); + bool is_vector = (vector_len != UINT32_MAX); + ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type; - op = ir_implicit_cast(ira, instruction->op->child, ret_type); + IrInstruction *op = ir_implicit_cast(ira, uncasted_op, op_type); if (type_is_invalid(op->value.type)) return ira->codegen->invalid_instruction; - if (int_type->data.integral.bit_count == 0) { - IrInstruction *result = ir_const(ira, &instruction->base, ret_type); - if (is_vector) { - expand_undef_array(ira->codegen, &result->value); - result->value.data.x_array.data.s_none.elements = - allocate(expr_type->data.vector.len); - for (unsigned i = 0; i < expr_type->data.vector.len; i++) - bigint_init_unsigned(&result->value.data.x_array.data.s_none.elements[i].data.x_bigint, 0); - } - bigint_init_unsigned(&result->value.data.x_bigint, 0); - return result; - } - - if (int_type->data.integral.bit_count == 8) + if (int_type->data.integral.bit_count == 8 || int_type->data.integral.bit_count == 0) return op; if (int_type->data.integral.bit_count % 8 != 0) { @@ -25308,21 +25303,28 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction if (val == nullptr) return ira->codegen->invalid_instruction; if (val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, ret_type); + return ir_const_undef(ira, &instruction->base, op_type); - IrInstruction *result = ir_const(ira, &instruction->base, ret_type); + IrInstruction *result = ir_const(ira, &instruction->base, op_type); size_t buf_size = int_type->data.integral.bit_count / 8; uint8_t *buf = allocate_nonzero(buf_size); if (is_vector) { - expand_undef_array(ira->codegen, &result->value); - result->value.data.x_array.data.s_none.elements = - allocate(expr_type->data.vector.len); - for (unsigned i = 0; i < expr_type->data.vector.len; i++) { - ConstExprValue *cur = &val->data.x_array.data.s_none.elements[i]; - result->value.data.x_array.data.s_none.elements[i].special = cur->special; - if (cur->special == ConstValSpecialUndef) + expand_undef_array(ira->codegen, val); + result->value.data.x_array.data.s_none.elements = create_const_vals(op_type->data.vector.len); + for (unsigned i = 0; i < op_type->data.vector.len; i += 1) { + ConstExprValue *op_elem_val = &val->data.x_array.data.s_none.elements[i]; + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node, + op_elem_val, UndefOk))) + { + return ira->codegen->invalid_instruction; + } + ConstExprValue *result_elem_val = &result->value.data.x_array.data.s_none.elements[i]; + result_elem_val->type = int_type; + result_elem_val->special = op_elem_val->special; + if (op_elem_val->special == ConstValSpecialUndef) continue; - bigint_write_twos_complement(&cur->data.x_bigint, buf, int_type->data.integral.bit_count, true); + + bigint_write_twos_complement(&op_elem_val->data.x_bigint, buf, int_type->data.integral.bit_count, true); bigint_read_twos_complement(&result->value.data.x_array.data.s_none.elements[i].data.x_bigint, buf, int_type->data.integral.bit_count, false, int_type->data.integral.is_signed); @@ -25332,12 +25334,13 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false, int_type->data.integral.is_signed); } + free(buf); return result; } IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope, instruction->base.source_node, nullptr, op); - result->value.type = ret_type; + result->value.type = op_type; return result; } diff --git a/test/stage1/behavior/byteswap.zig b/test/stage1/behavior/byteswap.zig index 249db155b7..d8fc554808 100644 --- a/test/stage1/behavior/byteswap.zig +++ b/test/stage1/behavior/byteswap.zig @@ -1,43 +1,62 @@ const std = @import("std"); const expect = std.testing.expect; -test "@byteSwap" { - comptime testByteSwap(); - testByteSwap(); -} +test "@byteSwap integers" { + const ByteSwapIntTest = struct { + fn run() void { + t(u0, 0, 0); + t(u8, 0x12, 0x12); + t(u16, 0x1234, 0x3412); + t(u24, 0x123456, 0x563412); + t(u32, 0x12345678, 0x78563412); + t(u40, 0x123456789a, 0x9a78563412); + t(i48, 0x123456789abc, @bitCast(i48, u48(0xbc9a78563412))); + t(u56, 0x123456789abcde, 0xdebc9a78563412); + t(u64, 0x123456789abcdef1, 0xf1debc9a78563412); + t(u128, 0x123456789abcdef11121314151617181, 0x8171615141312111f1debc9a78563412); -test "@byteSwap on vectors" { - comptime testVectorByteSwap(); - testVectorByteSwap(); + t(u0, u0(0), 0); + t(i8, i8(-50), -50); + t(i16, @bitCast(i16, u16(0x1234)), @bitCast(i16, u16(0x3412))); + t(i24, @bitCast(i24, u24(0x123456)), @bitCast(i24, u24(0x563412))); + t(i32, @bitCast(i32, u32(0x12345678)), @bitCast(i32, u32(0x78563412))); + t(u40, @bitCast(i40, u40(0x123456789a)), u40(0x9a78563412)); + t(i48, @bitCast(i48, u48(0x123456789abc)), @bitCast(i48, u48(0xbc9a78563412))); + t(i56, @bitCast(i56, u56(0x123456789abcde)), @bitCast(i56, u56(0xdebc9a78563412))); + t(i64, @bitCast(i64, u64(0x123456789abcdef1)), @bitCast(i64, u64(0xf1debc9a78563412))); + t( + i128, + @bitCast(i128, u128(0x123456789abcdef11121314151617181)), + @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)), + ); + } + fn t(comptime I: type, input: I, expected_output: I) void { + std.testing.expectEqual(expected_output, @byteSwap(I, input)); + } + }; + comptime ByteSwapIntTest.run(); + ByteSwapIntTest.run(); } -fn testByteSwap() void { - expect(@byteSwap(u0, 0) == 0); - expect(@byteSwap(u8, 0x12) == 0x12); - expect(@byteSwap(u16, 0x1234) == 0x3412); - expect(@byteSwap(u24, 0x123456) == 0x563412); - expect(@byteSwap(u32, 0x12345678) == 0x78563412); - expect(@byteSwap(u40, 0x123456789a) == 0x9a78563412); - expect(@byteSwap(i48, 0x123456789abc) == @bitCast(i48, u48(0xbc9a78563412))); - expect(@byteSwap(u56, 0x123456789abcde) == 0xdebc9a78563412); - expect(@byteSwap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412); - expect(@byteSwap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412); - - expect(@byteSwap(u0, u0(0)) == 0); - expect(@byteSwap(i8, i8(-50)) == -50); - expect(@byteSwap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412))); - expect(@byteSwap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412))); - expect(@byteSwap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412))); - expect(@byteSwap(u40, @bitCast(i40, u40(0x123456789a))) == u40(0x9a78563412)); - expect(@byteSwap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412))); - expect(@byteSwap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412))); - expect(@byteSwap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412))); - expect(@byteSwap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == - @bitCast(i128, u128(0x8171615141312111f1debc9a78563412))); -} +test "@byteSwap vectors" { + const ByteSwapVectorTest = struct { + fn run() void { + t(u8, 2, [_]u8{ 0x12, 0x13 }, [_]u8{ 0x12, 0x13 }); + t(u16, 2, [_]u16{ 0x1234, 0x2345 }, [_]u16{ 0x3412, 0x4523 }); + t(u24, 2, [_]u24{ 0x123456, 0x234567 }, [_]u24{ 0x563412, 0x674523 }); + } -fn testVectorByteSwap() void { - expect((@byteSwap(u8, @Vector(2, u8)([2]u8{0x12, 0x13})) == @Vector(2, u8)([2]u8{0x12, 0x13})).all); - expect((@byteSwap(u16, @Vector(2, u16)([2]u16{0x1234, 0x2345})) == @Vector(2, u16)([2]u16{0x3412, 0x4523})).all); - expect((@byteSwap(u24, @Vector(2, u24)([2]u24{0x123456, 0x234567})) == @Vector(2, u24)([2]u24{0x563412, 0x674523})).all); + fn t( + comptime I: type, + comptime n: comptime_int, + input: @Vector(n, I), + expected_vector: @Vector(n, I), + ) void { + const actual_output: [n]I = @byteSwap(I, input); + const expected_output: [n]I = expected_vector; + std.testing.expectEqual(expected_output, actual_output); + } + }; + comptime ByteSwapVectorTest.run(); + ByteSwapVectorTest.run(); } -- cgit v1.2.3