authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-19 01:05:12-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-19 01:05:12-04:00
log0048bcbd71b9139203d7acee120d524d38e22a0e
tree6f4139367553fea653662d1fb65bd23421bad77a
parent86209e1a9259dca40803e56d612beacf5a35855c
parent380c8ec2c95fa8d732c141c705d9940629eb2012
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'merge-shawnl-simd5'

This is the commit from Shawn's SIMD patchset regarding `@byteSwap`, plus my fixups.

6 files changed, 160 insertions(+), 54 deletions(-)

doc/langref.html.in+10-1
...@@ -6542,12 +6542,21 @@ async fn func(y: *i32) void {...@@ -6542,12 +6542,21 @@ async fn func(y: *i32) void {
6542 {#header_close#}6542 {#header_close#}
65436543
6544 {#header_open|@byteSwap#}6544 {#header_open|@byteSwap#}
6545 <pre>{#syntax#}@byteSwap(comptime T: type, integer: T) T{#endsyntax#}</pre>6545 <pre>{#syntax#}@byteSwap(comptime T: type, operand: T) T{#endsyntax#}</pre>
6546 <p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p>6546 <p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p>
6547 <p>{#syntax#}operand{#endsyntax#} may be an {#link|integer|Integers#} or {#link|vector|Vectors#}.</p>
6547 <p>6548 <p>
6548 Swaps the byte order of the integer. This converts a big endian integer to a little endian integer,6549 Swaps the byte order of the integer. This converts a big endian integer to a little endian integer,
6549 and converts a little endian integer to a big endian integer.6550 and converts a little endian integer to a big endian integer.
6550 </p>6551 </p>
6552 <p>
6553 Note that for the purposes of memory layout with respect to endianness, the integer type should be
6554 related to the number of bytes reported by {#link|@sizeOf#} bytes. This is demonstrated with
6555 {#syntax#}u24{#endsyntax#}. {#syntax#}@sizeOf(u24) == 4{#endsyntax#}, which means that a
6556 {#syntax#}u24{#endsyntax#} stored in memory takes 4 bytes, and those 4 bytes are what are swapped on
6557 a little vs big endian system. On the other hand, if {#syntax#}T{#endsyntax#} is specified to
6558 be {#syntax#}u24{#endsyntax#}, then only 3 bytes are reversed.
6559 </p>
6551 {#header_close#}6560 {#header_close#}
65526561
6553 {#header_open|@bitReverse#}6562 {#header_open|@bitReverse#}
src/all_types.hpp+1
...@@ -1771,6 +1771,7 @@ struct ZigLLVMFnKey {...@@ -1771,6 +1771,7 @@ struct ZigLLVMFnKey {
1771 } overflow_arithmetic;1771 } overflow_arithmetic;
1772 struct {1772 struct {
1773 uint32_t bit_count;1773 uint32_t bit_count;
1774 uint32_t vector_len; // 0 means not a vector
1774 } bswap;1775 } bswap;
1775 struct {1776 struct {
1776 uint32_t bit_count;1777 uint32_t bit_count;
src/analyze.cpp+4-2
...@@ -6896,7 +6896,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {...@@ -6896,7 +6896,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
6896 return (uint32_t)(x.data.floating.bit_count) * ((uint32_t)x.id + 1025) +6896 return (uint32_t)(x.data.floating.bit_count) * ((uint32_t)x.id + 1025) +
6897 (uint32_t)(x.data.floating.vector_len) * (((uint32_t)x.id << 5) + 1025);6897 (uint32_t)(x.data.floating.vector_len) * (((uint32_t)x.id << 5) + 1025);
6898 case ZigLLVMFnIdBswap:6898 case ZigLLVMFnIdBswap:
6899 return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;6899 return (uint32_t)(x.data.bswap.bit_count) * ((uint32_t)3661994335) +
6900 (uint32_t)(x.data.bswap.vector_len) * (((uint32_t)x.id << 5) + 1025);
6900 case ZigLLVMFnIdBitReverse:6901 case ZigLLVMFnIdBitReverse:
6901 return (uint32_t)(x.data.bit_reverse.bit_count) * (uint32_t)2621398431;6902 return (uint32_t)(x.data.bit_reverse.bit_count) * (uint32_t)2621398431;
6902 case ZigLLVMFnIdOverflowArithmetic:6903 case ZigLLVMFnIdOverflowArithmetic:
...@@ -6919,7 +6920,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {...@@ -6919,7 +6920,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
6919 case ZigLLVMFnIdPopCount:6920 case ZigLLVMFnIdPopCount:
6920 return a.data.pop_count.bit_count == b.data.pop_count.bit_count;6921 return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
6921 case ZigLLVMFnIdBswap:6922 case ZigLLVMFnIdBswap:
6922 return a.data.bswap.bit_count == b.data.bswap.bit_count;6923 return a.data.bswap.bit_count == b.data.bswap.bit_count &&
6924 a.data.bswap.vector_len == b.data.bswap.vector_len;
6923 case ZigLLVMFnIdBitReverse:6925 case ZigLLVMFnIdBitReverse:
6924 return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;6926 return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;
6925 case ZigLLVMFnIdFloatOp:6927 case ZigLLVMFnIdFloatOp:
src/codegen.cpp+31-12
...@@ -4505,7 +4505,11 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec...@@ -4505,7 +4505,11 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec
4505 }4505 }
4506}4506}
45074507
4508static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnId fn_id) {4508static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFnId fn_id) {
4509 bool is_vector = expr_type->id == ZigTypeIdVector;
4510 ZigType *int_type = is_vector ? expr_type->data.vector.elem_type : expr_type;
4511 assert(int_type->id == ZigTypeIdInt);
4512 uint32_t vector_len = is_vector ? expr_type->data.vector.len : 0;
4509 ZigLLVMFnKey key = {};4513 ZigLLVMFnKey key = {};
4510 const char *fn_name;4514 const char *fn_name;
4511 uint32_t n_args;4515 uint32_t n_args;
...@@ -4529,6 +4533,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI...@@ -4529,6 +4533,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
4529 n_args = 1;4533 n_args = 1;
4530 key.id = ZigLLVMFnIdBswap;4534 key.id = ZigLLVMFnIdBswap;
4531 key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;4535 key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;
4536 key.data.bswap.vector_len = vector_len;
4532 } else if (fn_id == BuiltinFnIdBitReverse) {4537 } else if (fn_id == BuiltinFnIdBitReverse) {
4533 fn_name = "bitreverse";4538 fn_name = "bitreverse";
4534 n_args = 1;4539 n_args = 1;
...@@ -4543,12 +4548,15 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI...@@ -4543,12 +4548,15 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
4543 return existing_entry->value;4548 return existing_entry->value;
45444549
4545 char llvm_name[64];4550 char llvm_name[64];
4546 sprintf(llvm_name, "llvm.%s.i%" PRIu32, fn_name, int_type->data.integral.bit_count);4551 if (is_vector)
4552 sprintf(llvm_name, "llvm.%s.v%" PRIu32 "i%" PRIu32, fn_name, vector_len, int_type->data.integral.bit_count);
4553 else
4554 sprintf(llvm_name, "llvm.%s.i%" PRIu32, fn_name, int_type->data.integral.bit_count);
4547 LLVMTypeRef param_types[] = {4555 LLVMTypeRef param_types[] = {
4548 get_llvm_type(g, int_type),4556 get_llvm_type(g, expr_type),
4549 LLVMInt1Type(),4557 LLVMInt1Type(),
4550 };4558 };
4551 LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, int_type), param_types, n_args, false);4559 LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, expr_type), param_types, n_args, false);
4552 LLVMValueRef fn_val = LLVMAddFunction(g->module, llvm_name, fn_type);4560 LLVMValueRef fn_val = LLVMAddFunction(g->module, llvm_name, fn_type);
4553 assert(LLVMGetIntrinsicID(fn_val));4561 assert(LLVMGetIntrinsicID(fn_val));
45544562
...@@ -5542,25 +5550,36 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrIn...@@ -5542,25 +5550,36 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrIn
55425550
5543static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {5551static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {
5544 LLVMValueRef op = ir_llvm_value(g, instruction->op);5552 LLVMValueRef op = ir_llvm_value(g, instruction->op);
5545 ZigType *int_type = instruction->base.value.type;5553 ZigType *expr_type = instruction->base.value.type;
5554 bool is_vector = expr_type->id == ZigTypeIdVector;
5555 ZigType *int_type = is_vector ? expr_type->data.vector.elem_type : expr_type;
5546 assert(int_type->id == ZigTypeIdInt);5556 assert(int_type->id == ZigTypeIdInt);
5547 if (int_type->data.integral.bit_count % 16 == 0) {5557 if (int_type->data.integral.bit_count % 16 == 0) {
5548 LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBswap);5558 LLVMValueRef fn_val = get_int_builtin_fn(g, expr_type, BuiltinFnIdBswap);
5549 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");5559 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5550 }5560 }
5551 // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate5561 // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate
5552 ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,5562 ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,
5553 int_type->data.integral.bit_count + 8);5563 int_type->data.integral.bit_count + 8);
5564 LLVMValueRef shift_amt = LLVMConstInt(get_llvm_type(g, extended_type), 8, false);
5565 if (is_vector) {
5566 extended_type = get_vector_type(g, expr_type->data.vector.len, extended_type);
5567 LLVMValueRef *values = allocate_nonzero<LLVMValueRef>(expr_type->data.vector.len);
5568 for (uint32_t i = 0; i < expr_type->data.vector.len; i += 1) {
5569 values[i] = shift_amt;
5570 }
5571 shift_amt = LLVMConstVector(values, expr_type->data.vector.len);
5572 free(values);
5573 }
5554 // aabbcc5574 // aabbcc
5555 LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), "");5575 LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), "");
5556 // 00aabbcc5576 // 00aabbcc
5557 LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);5577 LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);
5558 LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, "");5578 LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, "");
5559 // ccbbaa005579 // ccbbaa00
5560 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped,5580 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, shift_amt, "");
5561 LLVMConstInt(get_llvm_type(g, extended_type), 8, false), "");
5562 // 00ccbbaa5581 // 00ccbbaa
5563 return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, int_type), "");5582 return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, expr_type), "");
5564}5583}
55655584
5566static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) {5585static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) {
...@@ -5581,7 +5600,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab...@@ -5581,7 +5600,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab
5581 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);5600 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
55825601
5583 ZigType *elem_type = array_type->data.array.child_type;5602 ZigType *elem_type = array_type->data.array.child_type;
5584 bool bitcast_ok = (elem_type->size_in_bits * 8) == elem_type->abi_size;5603 bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8;
5585 if (bitcast_ok) {5604 if (bitcast_ok) {
5586 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,5605 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
5587 LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");5606 LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");
...@@ -5615,7 +5634,7 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab...@@ -5615,7 +5634,7 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab
5615 LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type);5634 LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type);
56165635
5617 ZigType *elem_type = vector_type->data.vector.elem_type;5636 ZigType *elem_type = vector_type->data.vector.elem_type;
5618 bool bitcast_ok = (elem_type->size_in_bits * 8) == elem_type->abi_size;5637 bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8;
5619 if (bitcast_ok) {5638 if (bitcast_ok) {
5620 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,5639 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
5621 LLVMPointerType(vector_type_ref, 0), "");5640 LLVMPointerType(vector_type_ref, 0), "");
...@@ -8888,7 +8907,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa...@@ -8888,7 +8907,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
8888 args.append(g->framework_dirs.at(i));8907 args.append(g->framework_dirs.at(i));
8889 }8908 }
88908909
8891 //note(dimenus): appending libc headers before c_headers breaks intrinsics 8910 //note(dimenus): appending libc headers before c_headers breaks intrinsics
8892 //and other compiler specific items8911 //and other compiler specific items
8893 // According to Rich Felker libc headers are supposed to go before C language headers.8912 // According to Rich Felker libc headers are supposed to go before C language headers.
8894 args.append("-isystem");8913 args.append("-isystem");
src/ir.cpp+59-14
...@@ -11068,8 +11068,15 @@ static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) {...@@ -11068,8 +11068,15 @@ static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) {
11068 return ira->codegen->builtin_types.entry_invalid;11068 return ira->codegen->builtin_types.entry_invalid;
1106911069
11070 if (ty->id != ZigTypeIdInt) {11070 if (ty->id != ZigTypeIdInt) {
11071 ir_add_error(ira, type_value,11071 ErrorMsg *msg = ir_add_error(ira, type_value,
11072 buf_sprintf("expected integer type, found '%s'", buf_ptr(&ty->name)));11072 buf_sprintf("expected integer type, found '%s'", buf_ptr(&ty->name)));
11073 if (ty->id == ZigTypeIdVector &&
11074 ty->data.vector.elem_type->id == ZigTypeIdInt)
11075 {
11076 add_error_note(ira->codegen, msg, type_value->source_node,
11077 buf_sprintf("represent vectors with their element types, i.e. '%s'",
11078 buf_ptr(&ty->data.vector.elem_type->name)));
11079 }
11073 return ira->codegen->builtin_types.entry_invalid;11080 return ira->codegen->builtin_types.entry_invalid;
11074 }11081 }
1107511082
...@@ -25253,21 +25260,35 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct...@@ -25253,21 +25260,35 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct
25253}25260}
2525425261
25255static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {25262static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
25263 Error err;
25264
25256 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);25265 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
25257 if (type_is_invalid(int_type))25266 if (type_is_invalid(int_type))
25258 return ira->codegen->invalid_instruction;25267 return ira->codegen->invalid_instruction;
2525925268
25260 IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type);25269 IrInstruction *uncasted_op = instruction->op->child;
25261 if (type_is_invalid(op->value.type))25270 if (type_is_invalid(uncasted_op->value.type))
25262 return ira->codegen->invalid_instruction;25271 return ira->codegen->invalid_instruction;
2526325272
25264 if (int_type->data.integral.bit_count == 0) {25273 uint32_t vector_len; // UINT32_MAX means not a vector
25265 IrInstruction *result = ir_const(ira, &instruction->base, int_type);25274 if (uncasted_op->value.type->id == ZigTypeIdArray &&
25266 bigint_init_unsigned(&result->value.data.x_bigint, 0);25275 is_valid_vector_elem_type(uncasted_op->value.type->data.array.child_type))
25267 return result;25276 {
25277 vector_len = uncasted_op->value.type->data.array.len;
25278 } else if (uncasted_op->value.type->id == ZigTypeIdVector) {
25279 vector_len = uncasted_op->value.type->data.vector.len;
25280 } else {
25281 vector_len = UINT32_MAX;
25268 }25282 }
2526925283
25270 if (int_type->data.integral.bit_count == 8)25284 bool is_vector = (vector_len != UINT32_MAX);
25285 ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
25286
25287 IrInstruction *op = ir_implicit_cast(ira, uncasted_op, op_type);
25288 if (type_is_invalid(op->value.type))
25289 return ira->codegen->invalid_instruction;
25290
25291 if (int_type->data.integral.bit_count == 8 || int_type->data.integral.bit_count == 0)
25271 return op;25292 return op;
2527225293
25273 if (int_type->data.integral.bit_count % 8 != 0) {25294 if (int_type->data.integral.bit_count % 8 != 0) {
...@@ -25282,20 +25303,44 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction...@@ -25282,20 +25303,44 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction
25282 if (val == nullptr)25303 if (val == nullptr)
25283 return ira->codegen->invalid_instruction;25304 return ira->codegen->invalid_instruction;
25284 if (val->special == ConstValSpecialUndef)25305 if (val->special == ConstValSpecialUndef)
25285 return ir_const_undef(ira, &instruction->base, int_type);25306 return ir_const_undef(ira, &instruction->base, op_type);
2528625307
25287 IrInstruction *result = ir_const(ira, &instruction->base, int_type);25308 IrInstruction *result = ir_const(ira, &instruction->base, op_type);
25288 size_t buf_size = int_type->data.integral.bit_count / 8;25309 size_t buf_size = int_type->data.integral.bit_count / 8;
25289 uint8_t *buf = allocate_nonzero<uint8_t>(buf_size);25310 uint8_t *buf = allocate_nonzero<uint8_t>(buf_size);
25290 bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true);25311 if (is_vector) {
25291 bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,25312 expand_undef_array(ira->codegen, val);
25292 int_type->data.integral.is_signed);25313 result->value.data.x_array.data.s_none.elements = create_const_vals(op_type->data.vector.len);
25314 for (unsigned i = 0; i < op_type->data.vector.len; i += 1) {
25315 ConstExprValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
25316 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
25317 op_elem_val, UndefOk)))
25318 {
25319 return ira->codegen->invalid_instruction;
25320 }
25321 ConstExprValue *result_elem_val = &result->value.data.x_array.data.s_none.elements[i];
25322 result_elem_val->type = int_type;
25323 result_elem_val->special = op_elem_val->special;
25324 if (op_elem_val->special == ConstValSpecialUndef)
25325 continue;
25326
25327 bigint_write_twos_complement(&op_elem_val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
25328 bigint_read_twos_complement(&result->value.data.x_array.data.s_none.elements[i].data.x_bigint,
25329 buf, int_type->data.integral.bit_count, false,
25330 int_type->data.integral.is_signed);
25331 }
25332 } else {
25333 bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
25334 bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,
25335 int_type->data.integral.is_signed);
25336 }
25337 free(buf);
25293 return result;25338 return result;
25294 }25339 }
2529525340
25296 IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,25341 IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,
25297 instruction->base.source_node, nullptr, op);25342 instruction->base.source_node, nullptr, op);
25298 result->value.type = int_type;25343 result->value.type = op_type;
25299 return result;25344 return result;
25300}25345}
2530125346
test/stage1/behavior/byteswap.zig+55-25
...@@ -1,32 +1,62 @@...@@ -1,32 +1,62 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
33
4test "@byteSwap" {4test "@byteSwap integers" {
5 comptime testByteSwap();5 const ByteSwapIntTest = struct {
6 testByteSwap();6 fn run() void {
7 t(u0, 0, 0);
8 t(u8, 0x12, 0x12);
9 t(u16, 0x1234, 0x3412);
10 t(u24, 0x123456, 0x563412);
11 t(u32, 0x12345678, 0x78563412);
12 t(u40, 0x123456789a, 0x9a78563412);
13 t(i48, 0x123456789abc, @bitCast(i48, u48(0xbc9a78563412)));
14 t(u56, 0x123456789abcde, 0xdebc9a78563412);
15 t(u64, 0x123456789abcdef1, 0xf1debc9a78563412);
16 t(u128, 0x123456789abcdef11121314151617181, 0x8171615141312111f1debc9a78563412);
17
18 t(u0, u0(0), 0);
19 t(i8, i8(-50), -50);
20 t(i16, @bitCast(i16, u16(0x1234)), @bitCast(i16, u16(0x3412)));
21 t(i24, @bitCast(i24, u24(0x123456)), @bitCast(i24, u24(0x563412)));
22 t(i32, @bitCast(i32, u32(0x12345678)), @bitCast(i32, u32(0x78563412)));
23 t(u40, @bitCast(i40, u40(0x123456789a)), u40(0x9a78563412));
24 t(i48, @bitCast(i48, u48(0x123456789abc)), @bitCast(i48, u48(0xbc9a78563412)));
25 t(i56, @bitCast(i56, u56(0x123456789abcde)), @bitCast(i56, u56(0xdebc9a78563412)));
26 t(i64, @bitCast(i64, u64(0x123456789abcdef1)), @bitCast(i64, u64(0xf1debc9a78563412)));
27 t(
28 i128,
29 @bitCast(i128, u128(0x123456789abcdef11121314151617181)),
30 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)),
31 );
32 }
33 fn t(comptime I: type, input: I, expected_output: I) void {
34 std.testing.expectEqual(expected_output, @byteSwap(I, input));
35 }
36 };
37 comptime ByteSwapIntTest.run();
38 ByteSwapIntTest.run();
7}39}
840
9fn testByteSwap() void {41test "@byteSwap vectors" {
10 expect(@byteSwap(u0, 0) == 0);42 const ByteSwapVectorTest = struct {
11 expect(@byteSwap(u8, 0x12) == 0x12);43 fn run() void {
12 expect(@byteSwap(u16, 0x1234) == 0x3412);44 t(u8, 2, [_]u8{ 0x12, 0x13 }, [_]u8{ 0x12, 0x13 });
13 expect(@byteSwap(u24, 0x123456) == 0x563412);45 t(u16, 2, [_]u16{ 0x1234, 0x2345 }, [_]u16{ 0x3412, 0x4523 });
14 expect(@byteSwap(u32, 0x12345678) == 0x78563412);46 t(u24, 2, [_]u24{ 0x123456, 0x234567 }, [_]u24{ 0x563412, 0x674523 });
15 expect(@byteSwap(u40, 0x123456789a) == 0x9a78563412);47 }
16 expect(@byteSwap(i48, 0x123456789abc) == @bitCast(i48, u48(0xbc9a78563412)));
17 expect(@byteSwap(u56, 0x123456789abcde) == 0xdebc9a78563412);
18 expect(@byteSwap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
19 expect(@byteSwap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
2048
21 expect(@byteSwap(u0, u0(0)) == 0);49 fn t(
22 expect(@byteSwap(i8, i8(-50)) == -50);50 comptime I: type,
23 expect(@byteSwap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));51 comptime n: comptime_int,
24 expect(@byteSwap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));52 input: @Vector(n, I),
25 expect(@byteSwap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));53 expected_vector: @Vector(n, I),
26 expect(@byteSwap(u40, @bitCast(i40, u40(0x123456789a))) == u40(0x9a78563412));54 ) void {
27 expect(@byteSwap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));55 const actual_output: [n]I = @byteSwap(I, input);
28 expect(@byteSwap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));56 const expected_output: [n]I = expected_vector;
29 expect(@byteSwap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));57 std.testing.expectEqual(expected_output, actual_output);
30 expect(@byteSwap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==58 }
31 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));59 };
60 comptime ByteSwapVectorTest.run();
61 ByteSwapVectorTest.run();
32}62}