authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-19 17:02:32-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-19 17:02:32-04:00
log8a30edcde82dfcd36c3eec2fb7bcd5af549325cf
tree9d45053a816d85e72daee5c168a20259be585871
parent5e34fb35972b8ff2ec0a420779b689229d05c659
parent925ffbce7f424548be9eb42eb3914d5035066003
signaturelock-open Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into llvm9


23 files changed, 1200 insertions(+), 180 deletions(-)

doc/langref.html.in+79-9
......@@ -5864,7 +5864,7 @@ volatile (
58645864 : [number] "{rax}" (number),
58655865 [arg1] "{rdi}" (arg1)
58665866// Next is the list of clobbers. These declare a set of registers whose
5867// values will not be preserved by the execution of this assembly code.
5867// values will not be preserved by the execution of this assembly code.
58685868// These do not include output or input registers. The special clobber
58695869// value of "memory" means that the assembly writes to arbitrary undeclared
58705870// memory locations - not only the memory pointed to by a declared indirect
......@@ -5885,7 +5885,7 @@ volatile (
58855885 </p>
58865886 {#header_open|Output Constraints#}
58875887 <p>
5888 Output constraints are still considered to be unstable in Zig, and
5888 Output constraints are still considered to be unstable in Zig, and
58895889 so
58905890 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>
58915891 and
......@@ -5900,7 +5900,7 @@ volatile (
59005900
59015901 {#header_open|Input Constraints#}
59025902 <p>
5903 Input constraints are still considered to be unstable in Zig, and
5903 Input constraints are still considered to be unstable in Zig, and
59045904 so
59055905 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>
59065906 and
......@@ -5919,7 +5919,7 @@ volatile (
59195919 the assembly code. These do not include output or input registers. The special clobber
59205920 value of {#syntax#}"memory"{#endsyntax#} means that the assembly causes writes to
59215921 arbitrary undeclared memory locations - not only the memory pointed to by a declared
5922 indirect output.
5922 indirect output.
59235923 </p>
59245924 <p>
59255925 Failure to declare the full set of clobbers for a given inline assembly
......@@ -6542,12 +6542,21 @@ async fn func(y: *i32) void {
65426542 {#header_close#}
65436543
65446544 {#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>
65466546 <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>
65476548 <p>
65486549 Swaps the byte order of the integer. This converts a big endian integer to a little endian integer,
65496550 and converts a little endian integer to a big endian integer.
65506551 </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>
65516560 {#header_close#}
65526561
65536562 {#header_open|@bitReverse#}
......@@ -6641,7 +6650,7 @@ async fn func(y: *i32) void {
66416650 {#header_open|@clz#}
66426651 <pre>{#syntax#}@clz(comptime T: type, integer: T){#endsyntax#}</pre>
66436652 <p>
6644 This function counts the number of leading zeroes in {#syntax#}integer{#endsyntax#}.
6653 This function counts the number of most-significant (leading in a big-Endian sense) zeroes in {#syntax#}integer{#endsyntax#}.
66456654 </p>
66466655 <p>
66476656 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#},
......@@ -6783,7 +6792,7 @@ test "main" {
67836792 {#header_open|@ctz#}
67846793 <pre>{#syntax#}@ctz(comptime T: type, integer: T){#endsyntax#}</pre>
67856794 <p>
6786 This function counts the number of trailing zeroes in {#syntax#}integer{#endsyntax#}.
6795 This function counts the number of least-significant (trailing in a big-Endian sense) zeroes in {#syntax#}integer{#endsyntax#}.
67876796 </p>
67886797 <p>
67896798 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#},
......@@ -7673,6 +7682,43 @@ test "@setRuntimeSafety" {
76737682 {#see_also|@shlExact|@shlWithOverflow#}
76747683 {#header_close#}
76757684
7685 {#header_open|@shuffle#}
7686 <pre>{#syntax#}@shuffle(comptime E: type, a: @Vector(a_len, E), b: @Vector(b_len, E), comptime mask: @Vector(mask_len, i32)) @Vector(mask_len, E){#endsyntax#}</pre>
7687 <p>
7688 Constructs a new {#link|vector|Vectors#} by selecting elements from {#syntax#}a{#endsyntax#} and
7689 {#syntax#}b{#endsyntax#} based on {#syntax#}mask{#endsyntax#}.
7690 </p>
7691 <p>
7692 Each element in {#syntax#}mask{#endsyntax#} selects an element from either {#syntax#}a{#endsyntax#} or
7693 {#syntax#}b{#endsyntax#}. Positive numbers select from {#syntax#}a{#endsyntax#} starting at 0.
7694 Negative values select from {#syntax#}b{#endsyntax#}, starting at {#syntax#}-1{#endsyntax#} and going down.
7695 It is recommended to use the {#syntax#}~{#endsyntax#} operator from indexes from {#syntax#}b{#endsyntax#}
7696 so that both indexes can start from {#syntax#}0{#endsyntax#} (i.e. {#syntax#}~i32(0){#endsyntax#} is
7697 {#syntax#}-1{#endsyntax#}).
7698 </p>
7699 <p>
7700 For each element of {#syntax#}mask{#endsyntax#}, if it or the selected value from
7701 {#syntax#}a{#endsyntax#} or {#syntax#}b{#endsyntax#} is {#syntax#}undefined{#endsyntax#},
7702 then the resulting element is {#syntax#}undefined{#endsyntax#}.
7703 </p>
7704 <p>
7705 {#syntax#}a_len{#endsyntax#} and {#syntax#}b_len{#endsyntax#} may differ in length. Out-of-bounds element
7706 indexes in {#syntax#}mask{#endsyntax#} result in compile errors.
7707 </p>
7708 <p>
7709 If {#syntax#}a{#endsyntax#} or {#syntax#}b{#endsyntax#} is {#syntax#}undefined{#endsyntax#}, it
7710 is equivalent to a vector of all {#syntax#}undefined{#endsyntax#} with the same length as the other vector.
7711 If both vectors are {#syntax#}undefined{#endsyntax#}, {#syntax#}@shuffle{#endsyntax#} returns
7712 a vector with all elements {#syntax#}undefined{#endsyntax#}.
7713 </p>
7714 <p>
7715 {#syntax#}E{#endsyntax#} must be an {#link|integer|Integers#}, {#link|float|Floats#},
7716 {#link|pointer|Pointers#}, or {#syntax#}bool{#endsyntax#}. The mask may be any vector length, and its
7717 length determines the result length.
7718 </p>
7719 {#see_also|SIMD#}
7720 {#header_close#}
7721
76767722 {#header_open|@sizeOf#}
76777723 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>
76787724 <p>
......@@ -7700,6 +7746,30 @@ test "@setRuntimeSafety" {
77007746 </p>
77017747 {#header_close#}
77027748
7749 {#header_open|@splat#}
7750 <pre>{#syntax#}@splat(comptime len: u32, scalar: var) @Vector(len, @typeOf(scalar)){#endsyntax#}</pre>
7751 <p>
7752 Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value
7753 {#syntax#}scalar{#endsyntax#}:
7754 </p>
7755 {#code_begin|test#}
7756const std = @import("std");
7757const assert = std.debug.assert;
7758
7759test "vector @splat" {
7760 const scalar: u32 = 5;
7761 const result = @splat(4, scalar);
7762 comptime assert(@typeOf(result) == @Vector(4, u32));
7763 assert(std.mem.eql(u32, ([4]u32)(result), [_]u32{ 5, 5, 5, 5 }));
7764}
7765 {#code_end#}
7766 <p>
7767 {#syntax#}scalar{#endsyntax#} must be an {#link|integer|Integers#}, {#link|bool|Primitive Types#},
7768 {#link|float|Floats#}, or {#link|pointer|Pointers#}.
7769 </p>
7770 {#see_also|Vectors|@shuffle#}
7771 {#header_close#}
7772
77037773 {#header_open|@sqrt#}
77047774 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>
77057775 <p>
......@@ -9411,8 +9481,8 @@ const c = @cImport({
94119481 <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
94129482 please!</li>
94139483 </ul>
9414 <p>When a C pointer is pointing to a single struct (not an array), deference the C pointer to
9415 access to the struct's fields or member data. That syntax looks like
9484 <p>When a C pointer is pointing to a single struct (not an array), deference the C pointer to
9485 access to the struct's fields or member data. That syntax looks like
94169486 this: </p>
94179487 <p>{#syntax#}ptr_to_struct.*.struct_member{#endsyntax#}</p>
94189488 <p>This is comparable to doing {#syntax#}->{#endsyntax#} in C.</p>
src/all_types.hpp+29-1
......@@ -1351,7 +1351,7 @@ struct ZigTypeBoundFn {
13511351};
13521352
13531353struct ZigTypeVector {
1354 // The type must be a pointer, integer, or float
1354 // The type must be a pointer, integer, bool, or float
13551355 ZigType *elem_type;
13561356 uint32_t len;
13571357};
......@@ -1611,6 +1611,8 @@ enum BuiltinFnId {
16111611 BuiltinFnIdIntToEnum,
16121612 BuiltinFnIdIntType,
16131613 BuiltinFnIdVectorType,
1614 BuiltinFnIdShuffle,
1615 BuiltinFnIdSplat,
16141616 BuiltinFnIdSetCold,
16151617 BuiltinFnIdSetRuntimeSafety,
16161618 BuiltinFnIdSetFloatMode,
......@@ -1770,6 +1772,7 @@ struct ZigLLVMFnKey {
17701772 } overflow_arithmetic;
17711773 struct {
17721774 uint32_t bit_count;
1775 uint32_t vector_len; // 0 means not a vector
17731776 } bswap;
17741777 struct {
17751778 uint32_t bit_count;
......@@ -2428,6 +2431,9 @@ enum IrInstructionId {
24282431 IrInstructionIdBoolToInt,
24292432 IrInstructionIdIntType,
24302433 IrInstructionIdVectorType,
2434 IrInstructionIdShuffleVector,
2435 IrInstructionIdSplatSrc,
2436 IrInstructionIdSplatGen,
24312437 IrInstructionIdBoolNot,
24322438 IrInstructionIdMemset,
24332439 IrInstructionIdMemcpy,
......@@ -3669,6 +3675,28 @@ struct IrInstructionVectorToArray {
36693675 IrInstruction *result_loc;
36703676};
36713677
3678struct IrInstructionShuffleVector {
3679 IrInstruction base;
3680
3681 IrInstruction *scalar_type;
3682 IrInstruction *a;
3683 IrInstruction *b;
3684 IrInstruction *mask; // This is in zig-format, not llvm format
3685};
3686
3687struct IrInstructionSplatSrc {
3688 IrInstruction base;
3689
3690 IrInstruction *len;
3691 IrInstruction *scalar;
3692};
3693
3694struct IrInstructionSplatGen {
3695 IrInstruction base;
3696
3697 IrInstruction *scalar;
3698};
3699
36723700struct IrInstructionAssertZero {
36733701 IrInstruction base;
36743702
src/analyze.cpp+6-3
......@@ -4708,6 +4708,7 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
47084708bool is_valid_vector_elem_type(ZigType *elem_type) {
47094709 return elem_type->id == ZigTypeIdInt ||
47104710 elem_type->id == ZigTypeIdFloat ||
4711 elem_type->id == ZigTypeIdBool ||
47114712 get_codegen_ptr_type(elem_type) != nullptr;
47124713}
47134714
......@@ -4727,7 +4728,7 @@ ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
47274728
47284729 ZigType *entry = new_type_table_entry(ZigTypeIdVector);
47294730 if ((len != 0) && type_has_bits(elem_type)) {
4730 // Vectors can only be ints, floats, or pointers. ints and floats have trivially resolvable
4731 // Vectors can only be ints, floats, bools, or pointers. ints (inc. bools) and floats have trivially resolvable
47314732 // llvm type refs. pointers we will use usize instead.
47324733 LLVMTypeRef example_vector_llvm_type;
47334734 if (elem_type->id == ZigTypeIdPointer) {
......@@ -6895,7 +6896,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
68956896 return (uint32_t)(x.data.floating.bit_count) * ((uint32_t)x.id + 1025) +
68966897 (uint32_t)(x.data.floating.vector_len) * (((uint32_t)x.id << 5) + 1025);
68976898 case ZigLLVMFnIdBswap:
6898 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);
68996901 case ZigLLVMFnIdBitReverse:
69006902 return (uint32_t)(x.data.bit_reverse.bit_count) * (uint32_t)2621398431;
69016903 case ZigLLVMFnIdOverflowArithmetic:
......@@ -6918,7 +6920,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
69186920 case ZigLLVMFnIdPopCount:
69196921 return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
69206922 case ZigLLVMFnIdBswap:
6921 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;
69226925 case ZigLLVMFnIdBitReverse:
69236926 return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;
69246927 case ZigLLVMFnIdFloatOp:
src/codegen.cpp+131-20
......@@ -4505,7 +4505,11 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec
45054505 }
45064506}
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;
45094513 ZigLLVMFnKey key = {};
45104514 const char *fn_name;
45114515 uint32_t n_args;
......@@ -4529,6 +4533,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
45294533 n_args = 1;
45304534 key.id = ZigLLVMFnIdBswap;
45314535 key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;
4536 key.data.bswap.vector_len = vector_len;
45324537 } else if (fn_id == BuiltinFnIdBitReverse) {
45334538 fn_name = "bitreverse";
45344539 n_args = 1;
......@@ -4543,12 +4548,15 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
45434548 return existing_entry->value;
45444549
45454550 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);
45474555 LLVMTypeRef param_types[] = {
4548 get_llvm_type(g, int_type),
4556 get_llvm_type(g, expr_type),
45494557 LLVMInt1Type(),
45504558 };
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);
45524560 LLVMValueRef fn_val = LLVMAddFunction(g->module, llvm_name, fn_type);
45534561 assert(LLVMGetIntrinsicID(fn_val));
45544562
......@@ -4581,6 +4589,48 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru
45814589 return gen_widen_or_shorten(g, false, int_type, instruction->base.value.type, wrong_size_int);
45824590}
45834591
4592static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executable, IrInstructionShuffleVector *instruction) {
4593 uint64_t len_a = instruction->a->value.type->data.vector.len;
4594 uint64_t len_mask = instruction->mask->value.type->data.vector.len;
4595
4596 // LLVM uses integers larger than the length of the first array to
4597 // index into the second array. This was deemed unnecessarily fragile
4598 // when changing code, so Zig uses negative numbers to index the
4599 // second vector. These start at -1 and go down, and are easiest to use
4600 // with the ~ operator. Here we convert between the two formats.
4601 IrInstruction *mask = instruction->mask;
4602 LLVMValueRef *values = allocate<LLVMValueRef>(len_mask);
4603 for (uint64_t i = 0; i < len_mask; i++) {
4604 if (mask->value.data.x_array.data.s_none.elements[i].special == ConstValSpecialUndef) {
4605 values[i] = LLVMGetUndef(LLVMInt32Type());
4606 } else {
4607 int32_t v = bigint_as_signed(&mask->value.data.x_array.data.s_none.elements[i].data.x_bigint);
4608 uint32_t index_val = (v >= 0) ? (uint32_t)v : (uint32_t)~v + (uint32_t)len_a;
4609 values[i] = LLVMConstInt(LLVMInt32Type(), index_val, false);
4610 }
4611 }
4612
4613 LLVMValueRef llvm_mask_value = LLVMConstVector(values, len_mask);
4614 free(values);
4615
4616 return LLVMBuildShuffleVector(g->builder,
4617 ir_llvm_value(g, instruction->a),
4618 ir_llvm_value(g, instruction->b),
4619 llvm_mask_value, "");
4620}
4621
4622static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInstructionSplatGen *instruction) {
4623 ZigType *result_type = instruction->base.value.type;
4624 src_assert(result_type->id == ZigTypeIdVector, instruction->base.source_node);
4625 uint32_t len = result_type->data.vector.len;
4626 LLVMTypeRef op_llvm_type = LLVMVectorType(get_llvm_type(g, instruction->scalar->value.type), 1);
4627 LLVMTypeRef mask_llvm_type = LLVMVectorType(LLVMInt32Type(), len);
4628 LLVMValueRef undef_vector = LLVMGetUndef(op_llvm_type);
4629 LLVMValueRef op_vector = LLVMBuildInsertElement(g->builder, undef_vector,
4630 ir_llvm_value(g, instruction->scalar), LLVMConstInt(LLVMInt32Type(), 0, false), "");
4631 return LLVMBuildShuffleVector(g->builder, op_vector, undef_vector, LLVMConstNull(mask_llvm_type), "");
4632}
4633
45844634static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {
45854635 ZigType *int_type = instruction->op->value.type;
45864636 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);
......@@ -5512,25 +5562,36 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrIn
55125562
55135563static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {
55145564 LLVMValueRef op = ir_llvm_value(g, instruction->op);
5515 ZigType *int_type = instruction->base.value.type;
5565 ZigType *expr_type = instruction->base.value.type;
5566 bool is_vector = expr_type->id == ZigTypeIdVector;
5567 ZigType *int_type = is_vector ? expr_type->data.vector.elem_type : expr_type;
55165568 assert(int_type->id == ZigTypeIdInt);
55175569 if (int_type->data.integral.bit_count % 16 == 0) {
5518 LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBswap);
5570 LLVMValueRef fn_val = get_int_builtin_fn(g, expr_type, BuiltinFnIdBswap);
55195571 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
55205572 }
55215573 // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate
55225574 ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,
55235575 int_type->data.integral.bit_count + 8);
5576 LLVMValueRef shift_amt = LLVMConstInt(get_llvm_type(g, extended_type), 8, false);
5577 if (is_vector) {
5578 extended_type = get_vector_type(g, expr_type->data.vector.len, extended_type);
5579 LLVMValueRef *values = allocate_nonzero<LLVMValueRef>(expr_type->data.vector.len);
5580 for (uint32_t i = 0; i < expr_type->data.vector.len; i += 1) {
5581 values[i] = shift_amt;
5582 }
5583 shift_amt = LLVMConstVector(values, expr_type->data.vector.len);
5584 free(values);
5585 }
55245586 // aabbcc
55255587 LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), "");
55265588 // 00aabbcc
55275589 LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);
55285590 LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, "");
55295591 // ccbbaa00
5530 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped,
5531 LLVMConstInt(get_llvm_type(g, extended_type), 8, false), "");
5592 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, shift_amt, "");
55325593 // 00ccbbaa
5533 return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, int_type), "");
5594 return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, expr_type), "");
55345595}
55355596
55365597static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) {
......@@ -5549,10 +5610,29 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab
55495610 assert(handle_is_ptr(array_type));
55505611 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
55515612 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
5552 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
5553 LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");
5554 uint32_t alignment = get_ptr_align(g, instruction->result_loc->value.type);
5555 gen_store_untyped(g, vector, casted_ptr, alignment, false);
5613
5614 ZigType *elem_type = array_type->data.array.child_type;
5615 bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8;
5616 if (bitcast_ok) {
5617 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
5618 LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");
5619 uint32_t alignment = get_ptr_align(g, instruction->result_loc->value.type);
5620 gen_store_untyped(g, vector, casted_ptr, alignment, false);
5621 } else {
5622 // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast
5623 // will not work, and we fall back to extractelement.
5624 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5625 LLVMTypeRef u32_type_ref = LLVMInt32Type();
5626 LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false);
5627 for (uintptr_t i = 0; i < instruction->vector->value.type->data.vector.len; i++) {
5628 LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false);
5629 LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false);
5630 LLVMValueRef indexes[] = { zero, index_usize };
5631 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, result_loc, indexes, 2, "");
5632 LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector, index_u32, "");
5633 LLVMBuildStore(g->builder, elem, elem_ptr);
5634 }
5635 }
55565636 return result_loc;
55575637}
55585638
......@@ -5563,12 +5643,34 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab
55635643 assert(vector_type->id == ZigTypeIdVector);
55645644 assert(!handle_is_ptr(vector_type));
55655645 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
5566 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
5567 LLVMPointerType(get_llvm_type(g, vector_type), 0), "");
5568 ZigType *array_type = instruction->array->value.type;
5569 assert(array_type->id == ZigTypeIdArray);
5570 uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type);
5571 return gen_load_untyped(g, casted_ptr, alignment, false, "");
5646 LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type);
5647
5648 ZigType *elem_type = vector_type->data.vector.elem_type;
5649 bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8;
5650 if (bitcast_ok) {
5651 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
5652 LLVMPointerType(vector_type_ref, 0), "");
5653 ZigType *array_type = instruction->array->value.type;
5654 assert(array_type->id == ZigTypeIdArray);
5655 uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type);
5656 return gen_load_untyped(g, casted_ptr, alignment, false, "");
5657 } else {
5658 // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast
5659 // will not work, and we fall back to insertelement.
5660 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5661 LLVMTypeRef u32_type_ref = LLVMInt32Type();
5662 LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false);
5663 LLVMValueRef vector = LLVMGetUndef(vector_type_ref);
5664 for (uintptr_t i = 0; i < instruction->base.value.type->data.vector.len; i++) {
5665 LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false);
5666 LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false);
5667 LLVMValueRef indexes[] = { zero, index_usize };
5668 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indexes, 2, "");
5669 LLVMValueRef elem = LLVMBuildLoad(g->builder, elem_ptr, "");
5670 vector = LLVMBuildInsertElement(g->builder, vector, elem, index_u32, "");
5671 }
5672 return vector;
5673 }
55725674}
55735675
55745676static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,
......@@ -5896,6 +5998,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
58965998 case IrInstructionIdFrameSizeSrc:
58975999 case IrInstructionIdAllocaGen:
58986000 case IrInstructionIdAwaitSrc:
6001 case IrInstructionIdSplatSrc:
58996002 zig_unreachable();
59006003
59016004 case IrInstructionIdDeclVarGen:
......@@ -6054,6 +6157,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
60546157 return ir_render_spill_begin(g, executable, (IrInstructionSpillBegin *)instruction);
60556158 case IrInstructionIdSpillEnd:
60566159 return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction);
6160 case IrInstructionIdShuffleVector:
6161 return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);
6162 case IrInstructionIdSplatGen:
6163 return ir_render_splat(g, executable, (IrInstructionSplatGen *) instruction);
60576164 }
60586165 zig_unreachable();
60596166}
......@@ -7419,7 +7526,9 @@ static void do_code_gen(CodeGen *g) {
74197526 }
74207527
74217528 char *error = nullptr;
7422 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
7529 if (LLVMVerifyModule(g->module, LLVMReturnStatusAction, &error)) {
7530 zig_panic("broken LLVM module found: %s", error);
7531 }
74237532}
74247533
74257534static void zig_llvm_emit_output(CodeGen *g) {
......@@ -7744,6 +7853,8 @@ static void define_builtin_fns(CodeGen *g) {
77447853 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
77457854 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
77467855 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
7856 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
7857 create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
77477858 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
77487859 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
77497860 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
src/ir.cpp+499-67
......@@ -717,6 +717,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) {
717717 return IrInstructionIdVectorType;
718718}
719719
720static constexpr IrInstructionId ir_instruction_id(IrInstructionShuffleVector *) {
721 return IrInstructionIdShuffleVector;
722}
723
724static constexpr IrInstructionId ir_instruction_id(IrInstructionSplatSrc *) {
725 return IrInstructionIdSplatSrc;
726}
727
728static constexpr IrInstructionId ir_instruction_id(IrInstructionSplatGen *) {
729 return IrInstructionIdSplatGen;
730}
731
720732static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
721733 return IrInstructionIdBoolNot;
722734}
......@@ -2277,6 +2289,38 @@ static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode
22772289 return &instruction->base;
22782290}
22792291
2292static IrInstruction *ir_build_shuffle_vector(IrBuilder *irb, Scope *scope, AstNode *source_node,
2293 IrInstruction *scalar_type, IrInstruction *a, IrInstruction *b, IrInstruction *mask)
2294{
2295 IrInstructionShuffleVector *instruction = ir_build_instruction<IrInstructionShuffleVector>(irb, scope, source_node);
2296 instruction->scalar_type = scalar_type;
2297 instruction->a = a;
2298 instruction->b = b;
2299 instruction->mask = mask;
2300
2301 if (scalar_type != nullptr) {
2302 ir_ref_instruction(scalar_type, irb->current_basic_block);
2303 }
2304 ir_ref_instruction(a, irb->current_basic_block);
2305 ir_ref_instruction(b, irb->current_basic_block);
2306 ir_ref_instruction(mask, irb->current_basic_block);
2307
2308 return &instruction->base;
2309}
2310
2311static IrInstruction *ir_build_splat_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2312 IrInstruction *len, IrInstruction *scalar)
2313{
2314 IrInstructionSplatSrc *instruction = ir_build_instruction<IrInstructionSplatSrc>(irb, scope, source_node);
2315 instruction->len = len;
2316 instruction->scalar = scalar;
2317
2318 ir_ref_instruction(len, irb->current_basic_block);
2319 ir_ref_instruction(scalar, irb->current_basic_block);
2320
2321 return &instruction->base;
2322}
2323
22802324static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
22812325 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
22822326 instruction->value = value;
......@@ -2333,6 +2377,19 @@ static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *
23332377 return &instruction->base;
23342378}
23352379
2380static IrInstruction *ir_build_splat_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type,
2381 IrInstruction *scalar)
2382{
2383 IrInstructionSplatGen *instruction = ir_build_instruction<IrInstructionSplatGen>(
2384 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2385 instruction->base.value.type = result_type;
2386 instruction->scalar = scalar;
2387
2388 ir_ref_instruction(scalar, ira->new_irb.current_basic_block);
2389
2390 return &instruction->base;
2391}
2392
23362393static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type,
23372394 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc)
23382395{
......@@ -4936,6 +4993,48 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
49364993 IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);
49374994 return ir_lval_wrap(irb, scope, vector_type, lval, result_loc);
49384995 }
4996 case BuiltinFnIdShuffle:
4997 {
4998 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4999 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
5000 if (arg0_value == irb->codegen->invalid_instruction)
5001 return arg0_value;
5002
5003 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5004 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
5005 if (arg1_value == irb->codegen->invalid_instruction)
5006 return arg1_value;
5007
5008 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
5009 IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
5010 if (arg2_value == irb->codegen->invalid_instruction)
5011 return arg2_value;
5012
5013 AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
5014 IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope);
5015 if (arg3_value == irb->codegen->invalid_instruction)
5016 return arg3_value;
5017
5018 IrInstruction *shuffle_vector = ir_build_shuffle_vector(irb, scope, node,
5019 arg0_value, arg1_value, arg2_value, arg3_value);
5020 return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc);
5021 }
5022 case BuiltinFnIdSplat:
5023 {
5024 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5025 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
5026 if (arg0_value == irb->codegen->invalid_instruction)
5027 return arg0_value;
5028
5029 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5030 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
5031 if (arg1_value == irb->codegen->invalid_instruction)
5032 return arg1_value;
5033
5034 IrInstruction *splat = ir_build_splat_src(irb, scope, node,
5035 arg0_value, arg1_value);
5036 return ir_lval_wrap(irb, scope, splat, lval, result_loc);
5037 }
49395038 case BuiltinFnIdMemcpy:
49405039 {
49415040 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
......@@ -11000,14 +11099,41 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
1100011099 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val);
1100111100}
1100211101
11102static Error ir_validate_vector_elem_type(IrAnalyze *ira, IrInstruction *source_instr, ZigType *elem_type) {
11103 if (!is_valid_vector_elem_type(elem_type)) {
11104 ir_add_error(ira, source_instr,
11105 buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid",
11106 buf_ptr(&elem_type->name)));
11107 return ErrorSemanticAnalyzeFail;
11108 }
11109 return ErrorNone;
11110}
11111
11112static ZigType *ir_resolve_vector_elem_type(IrAnalyze *ira, IrInstruction *elem_type_value) {
11113 Error err;
11114 ZigType *elem_type = ir_resolve_type(ira, elem_type_value);
11115 if (type_is_invalid(elem_type))
11116 return ira->codegen->builtin_types.entry_invalid;
11117 if ((err = ir_validate_vector_elem_type(ira, elem_type_value, elem_type)))
11118 return ira->codegen->builtin_types.entry_invalid;
11119 return elem_type;
11120}
11121
1100311122static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) {
1100411123 ZigType *ty = ir_resolve_type(ira, type_value);
1100511124 if (type_is_invalid(ty))
1100611125 return ira->codegen->builtin_types.entry_invalid;
1100711126
1100811127 if (ty->id != ZigTypeIdInt) {
11009 ir_add_error(ira, type_value,
11128 ErrorMsg *msg = ir_add_error(ira, type_value,
1101011129 buf_sprintf("expected integer type, found '%s'", buf_ptr(&ty->name)));
11130 if (ty->id == ZigTypeIdVector &&
11131 ty->data.vector.elem_type->id == ZigTypeIdInt)
11132 {
11133 add_error_note(ira->codegen, msg, type_value->source_node,
11134 buf_sprintf("represent vectors with their element types, i.e. '%s'",
11135 buf_ptr(&ty->data.vector.elem_type->name)));
11136 }
1101111137 return ira->codegen->builtin_types.entry_invalid;
1101211138 }
1101311139
......@@ -13092,6 +13218,59 @@ static bool optional_value_is_null(ConstExprValue *val) {
1309213218 }
1309313219}
1309413220
13221static IrInstruction *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type,
13222 ConstExprValue *op1_val, ConstExprValue *op2_val, IrInstructionBinOp *bin_op_instruction, IrBinOp op_id,
13223 bool one_possible_value) {
13224 if (op1_val->special == ConstValSpecialUndef ||
13225 op2_val->special == ConstValSpecialUndef)
13226 return ir_const_undef(ira, &bin_op_instruction->base, resolved_type);
13227 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
13228 if (float_is_nan(op1_val) || float_is_nan(op2_val)) {
13229 return ir_const_bool(ira, &bin_op_instruction->base, op_id == IrBinOpCmpNotEq);
13230 }
13231 Cmp cmp_result = float_cmp(op1_val, op2_val);
13232 bool answer = resolve_cmp_op_id(op_id, cmp_result);
13233 return ir_const_bool(ira, &bin_op_instruction->base, answer);
13234 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
13235 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
13236 bool answer = resolve_cmp_op_id(op_id, cmp_result);
13237 return ir_const_bool(ira, &bin_op_instruction->base, answer);
13238 } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) {
13239 if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
13240 op1_val->data.x_ptr.special == ConstPtrSpecialNull) &&
13241 (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
13242 op2_val->data.x_ptr.special == ConstPtrSpecialNull))
13243 {
13244 uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ?
13245 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
13246 uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ?
13247 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr;
13248 Cmp cmp_result;
13249 if (op1_addr > op2_addr) {
13250 cmp_result = CmpGT;
13251 } else if (op1_addr < op2_addr) {
13252 cmp_result = CmpLT;
13253 } else {
13254 cmp_result = CmpEQ;
13255 }
13256 bool answer = resolve_cmp_op_id(op_id, cmp_result);
13257 return ir_const_bool(ira, &bin_op_instruction->base, answer);
13258 }
13259 } else {
13260 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
13261 bool answer;
13262 if (op_id == IrBinOpCmpEq) {
13263 answer = are_equal;
13264 } else if (op_id == IrBinOpCmpNotEq) {
13265 answer = !are_equal;
13266 } else {
13267 zig_unreachable();
13268 }
13269 return ir_const_bool(ira, &bin_op_instruction->base, answer);
13270 }
13271 zig_unreachable();
13272}
13273
1309513274// Returns ErrorNotLazy when the value cannot be determined
1309613275static Error lazy_cmp_zero(AstNode *source_node, ConstExprValue *val, Cmp *result) {
1309713276 Error err;
......@@ -13477,51 +13656,22 @@ never_mind_just_calculate_it_normally:
1347713656 ConstExprValue *op2_val = one_possible_value ? &casted_op2->value : ir_resolve_const(ira, casted_op2, UndefBad);
1347813657 if (op2_val == nullptr)
1347913658 return ira->codegen->invalid_instruction;
13480
13481 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
13482 if (float_is_nan(op1_val) || float_is_nan(op2_val)) {
13483 return ir_const_bool(ira, &bin_op_instruction->base, op_id == IrBinOpCmpNotEq);
13484 }
13485 Cmp cmp_result = float_cmp(op1_val, op2_val);
13486 bool answer = resolve_cmp_op_id(op_id, cmp_result);
13487 return ir_const_bool(ira, &bin_op_instruction->base, answer);
13488 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
13489 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
13490 bool answer = resolve_cmp_op_id(op_id, cmp_result);
13491 return ir_const_bool(ira, &bin_op_instruction->base, answer);
13492 } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) {
13493 if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
13494 op1_val->data.x_ptr.special == ConstPtrSpecialNull) &&
13495 (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
13496 op2_val->data.x_ptr.special == ConstPtrSpecialNull))
13497 {
13498 uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ?
13499 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
13500 uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ?
13501 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr;
13502 Cmp cmp_result;
13503 if (op1_addr > op2_addr) {
13504 cmp_result = CmpGT;
13505 } else if (op1_addr < op2_addr) {
13506 cmp_result = CmpLT;
13507 } else {
13508 cmp_result = CmpEQ;
13509 }
13510 bool answer = resolve_cmp_op_id(op_id, cmp_result);
13511 return ir_const_bool(ira, &bin_op_instruction->base, answer);
13512 }
13513 } else {
13514 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
13515 bool answer;
13516 if (op_id == IrBinOpCmpEq) {
13517 answer = are_equal;
13518 } else if (op_id == IrBinOpCmpNotEq) {
13519 answer = !are_equal;
13520 } else {
13521 zig_unreachable();
13522 }
13523 return ir_const_bool(ira, &bin_op_instruction->base, answer);
13659 if (resolved_type->id != ZigTypeIdVector)
13660 return ir_evaluate_bin_op_cmp(ira, resolved_type, op1_val, op2_val, bin_op_instruction, op_id, one_possible_value);
13661 IrInstruction *result = ir_const(ira, &bin_op_instruction->base,
13662 get_vector_type(ira->codegen, resolved_type->data.vector.len, ira->codegen->builtin_types.entry_bool));
13663 result->value.data.x_array.data.s_none.elements =
13664 create_const_vals(resolved_type->data.vector.len);
13665
13666 expand_undef_array(ira->codegen, &result->value);
13667 for (size_t i = 0;i < resolved_type->data.vector.len;i++) {
13668 IrInstruction *cur_res = ir_evaluate_bin_op_cmp(ira, resolved_type->data.vector.elem_type,
13669 &op1_val->data.x_array.data.s_none.elements[i],
13670 &op2_val->data.x_array.data.s_none.elements[i],
13671 bin_op_instruction, op_id, one_possible_value);
13672 copy_const_val(&result->value.data.x_array.data.s_none.elements[i], &cur_res->value, false);
1352413673 }
13674 return result;
1352513675 }
1352613676
1352713677 // some comparisons with unsigned numbers can be evaluated
......@@ -13564,7 +13714,12 @@ never_mind_just_calculate_it_normally:
1356413714 IrInstruction *result = ir_build_bin_op(&ira->new_irb,
1356513715 bin_op_instruction->base.scope, bin_op_instruction->base.source_node,
1356613716 op_id, casted_op1, casted_op2, bin_op_instruction->safety_check_on);
13567 result->value.type = ira->codegen->builtin_types.entry_bool;
13717 if (resolved_type->id == ZigTypeIdVector) {
13718 result->value.type = get_vector_type(ira->codegen, resolved_type->data.vector.len,
13719 ira->codegen->builtin_types.entry_bool);
13720 } else {
13721 result->value.type = ira->codegen->builtin_types.entry_bool;
13722 }
1356813723 return result;
1356913724}
1357013725
......@@ -15198,7 +15353,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1519815353 }
1519915354 peer_parent->skipped = true;
1520015355 return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
15201 value_type, value, force_runtime, true, true);
15356 value_type, value, force_runtime || !is_comptime, true, true);
1520215357 }
1520315358
1520415359 if (peer_parent->resolved_type == nullptr) {
......@@ -22018,20 +22173,251 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr
2201822173 if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len))
2201922174 return ira->codegen->invalid_instruction;
2202022175
22021 ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child);
22176 ZigType *elem_type = ir_resolve_vector_elem_type(ira, instruction->elem_type->child);
2202222177 if (type_is_invalid(elem_type))
2202322178 return ira->codegen->invalid_instruction;
2202422179
22025 if (!is_valid_vector_elem_type(elem_type)) {
22026 ir_add_error(ira, instruction->elem_type,
22027 buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid",
22028 buf_ptr(&elem_type->name)));
22180 ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type);
22181
22182 return ir_const_type(ira, &instruction->base, vector_type);
22183}
22184
22185static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *source_instr,
22186 ZigType *scalar_type, IrInstruction *a, IrInstruction *b, IrInstruction *mask)
22187{
22188 ir_assert(source_instr && scalar_type && a && b && mask, source_instr);
22189 ir_assert(is_valid_vector_elem_type(scalar_type), source_instr);
22190
22191 uint32_t len_mask;
22192 if (mask->value.type->id == ZigTypeIdVector) {
22193 len_mask = mask->value.type->data.vector.len;
22194 } else if (mask->value.type->id == ZigTypeIdArray) {
22195 len_mask = mask->value.type->data.array.len;
22196 } else {
22197 ir_add_error(ira, mask,
22198 buf_sprintf("expected vector or array, found '%s'",
22199 buf_ptr(&mask->value.type->name)));
2202922200 return ira->codegen->invalid_instruction;
2203022201 }
22202 mask = ir_implicit_cast(ira, mask, get_vector_type(ira->codegen, len_mask,
22203 ira->codegen->builtin_types.entry_i32));
22204 if (type_is_invalid(mask->value.type))
22205 return ira->codegen->invalid_instruction;
2203122206
22032 ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type);
22207 uint32_t len_a;
22208 if (a->value.type->id == ZigTypeIdVector) {
22209 len_a = a->value.type->data.vector.len;
22210 } else if (a->value.type->id == ZigTypeIdArray) {
22211 len_a = a->value.type->data.array.len;
22212 } else if (a->value.type->id == ZigTypeIdUndefined) {
22213 len_a = UINT32_MAX;
22214 } else {
22215 ir_add_error(ira, a,
22216 buf_sprintf("expected vector or array with element type '%s', found '%s'",
22217 buf_ptr(&scalar_type->name),
22218 buf_ptr(&a->value.type->name)));
22219 return ira->codegen->invalid_instruction;
22220 }
2203322221
22034 return ir_const_type(ira, &instruction->base, vector_type);
22222 uint32_t len_b;
22223 if (b->value.type->id == ZigTypeIdVector) {
22224 len_b = b->value.type->data.vector.len;
22225 } else if (b->value.type->id == ZigTypeIdArray) {
22226 len_b = b->value.type->data.array.len;
22227 } else if (b->value.type->id == ZigTypeIdUndefined) {
22228 len_b = UINT32_MAX;
22229 } else {
22230 ir_add_error(ira, b,
22231 buf_sprintf("expected vector or array with element type '%s', found '%s'",
22232 buf_ptr(&scalar_type->name),
22233 buf_ptr(&b->value.type->name)));
22234 return ira->codegen->invalid_instruction;
22235 }
22236
22237 if (len_a == UINT32_MAX && len_b == UINT32_MAX) {
22238 return ir_const_undef(ira, a, get_vector_type(ira->codegen, len_mask, scalar_type));
22239 }
22240
22241 if (len_a == UINT32_MAX) {
22242 len_a = len_b;
22243 a = ir_const_undef(ira, a, get_vector_type(ira->codegen, len_a, scalar_type));
22244 } else {
22245 a = ir_implicit_cast(ira, a, get_vector_type(ira->codegen, len_a, scalar_type));
22246 if (type_is_invalid(a->value.type))
22247 return ira->codegen->invalid_instruction;
22248 }
22249
22250 if (len_b == UINT32_MAX) {
22251 len_b = len_a;
22252 b = ir_const_undef(ira, b, get_vector_type(ira->codegen, len_b, scalar_type));
22253 } else {
22254 b = ir_implicit_cast(ira, b, get_vector_type(ira->codegen, len_b, scalar_type));
22255 if (type_is_invalid(b->value.type))
22256 return ira->codegen->invalid_instruction;
22257 }
22258
22259 ConstExprValue *mask_val = ir_resolve_const(ira, mask, UndefOk);
22260 if (mask_val == nullptr)
22261 return ira->codegen->invalid_instruction;
22262
22263 expand_undef_array(ira->codegen, mask_val);
22264
22265 for (uint32_t i = 0; i < len_mask; i += 1) {
22266 ConstExprValue *mask_elem_val = &mask_val->data.x_array.data.s_none.elements[i];
22267 if (mask_elem_val->special == ConstValSpecialUndef)
22268 continue;
22269 int32_t v_i32 = bigint_as_signed(&mask_elem_val->data.x_bigint);
22270 uint32_t v;
22271 IrInstruction *chosen_operand;
22272 if (v_i32 >= 0) {
22273 v = (uint32_t)v_i32;
22274 chosen_operand = a;
22275 } else {
22276 v = (uint32_t)~v_i32;
22277 chosen_operand = b;
22278 }
22279 if (v >= chosen_operand->value.type->data.vector.len) {
22280 ErrorMsg *msg = ir_add_error(ira, mask,
22281 buf_sprintf("mask index '%u' has out-of-bounds selection", i));
22282 add_error_note(ira->codegen, msg, chosen_operand->source_node,
22283 buf_sprintf("selected index '%u' out of bounds of %s", v,
22284 buf_ptr(&chosen_operand->value.type->name)));
22285 if (chosen_operand == a && v < len_a + len_b) {
22286 add_error_note(ira->codegen, msg, b->source_node,
22287 buf_create_from_str("selections from the second vector are specified with negative numbers"));
22288 }
22289 return ira->codegen->invalid_instruction;
22290 }
22291 }
22292
22293 ZigType *result_type = get_vector_type(ira->codegen, len_mask, scalar_type);
22294 if (instr_is_comptime(a) && instr_is_comptime(b)) {
22295 ConstExprValue *a_val = ir_resolve_const(ira, a, UndefOk);
22296 if (a_val == nullptr)
22297 return ira->codegen->invalid_instruction;
22298
22299 ConstExprValue *b_val = ir_resolve_const(ira, b, UndefOk);
22300 if (b_val == nullptr)
22301 return ira->codegen->invalid_instruction;
22302
22303 expand_undef_array(ira->codegen, a_val);
22304 expand_undef_array(ira->codegen, b_val);
22305
22306 IrInstruction *result = ir_const(ira, source_instr, result_type);
22307 result->value.data.x_array.data.s_none.elements = create_const_vals(len_mask);
22308 for (uint32_t i = 0; i < mask_val->type->data.vector.len; i += 1) {
22309 ConstExprValue *mask_elem_val = &mask_val->data.x_array.data.s_none.elements[i];
22310 ConstExprValue *result_elem_val = &result->value.data.x_array.data.s_none.elements[i];
22311 if (mask_elem_val->special == ConstValSpecialUndef) {
22312 result_elem_val->special = ConstValSpecialUndef;
22313 continue;
22314 }
22315 int32_t v = bigint_as_signed(&mask_elem_val->data.x_bigint);
22316 // We've already checked for and emitted compile errors for index out of bounds here.
22317 ConstExprValue *src_elem_val = (v >= 0) ?
22318 &a->value.data.x_array.data.s_none.elements[v] :
22319 &b->value.data.x_array.data.s_none.elements[~v];
22320 copy_const_val(result_elem_val, src_elem_val, false);
22321
22322 ir_assert(result_elem_val->special == ConstValSpecialStatic, source_instr);
22323 }
22324 result->value.special = ConstValSpecialStatic;
22325 return result;
22326 }
22327
22328 // All static analysis passed, and not comptime.
22329 // For runtime codegen, vectors a and b must be the same length. Here we
22330 // recursively @shuffle the smaller vector to append undefined elements
22331 // to it up to the length of the longer vector. This recursion terminates
22332 // in 1 call because these calls to ir_analyze_shuffle_vector guarantee
22333 // len_a == len_b.
22334 if (len_a != len_b) {
22335 uint32_t len_min = min(len_a, len_b);
22336 uint32_t len_max = max(len_a, len_b);
22337
22338 IrInstruction *expand_mask = ir_const(ira, mask,
22339 get_vector_type(ira->codegen, len_max, ira->codegen->builtin_types.entry_i32));
22340 expand_mask->value.data.x_array.data.s_none.elements = create_const_vals(len_max);
22341 uint32_t i = 0;
22342 for (; i < len_min; i += 1)
22343 bigint_init_unsigned(&expand_mask->value.data.x_array.data.s_none.elements[i].data.x_bigint, i);
22344 for (; i < len_max; i += 1)
22345 bigint_init_signed(&expand_mask->value.data.x_array.data.s_none.elements[i].data.x_bigint, -1);
22346
22347 IrInstruction *undef = ir_const_undef(ira, source_instr,
22348 get_vector_type(ira->codegen, len_min, scalar_type));
22349
22350 if (len_b < len_a) {
22351 b = ir_analyze_shuffle_vector(ira, source_instr, scalar_type, b, undef, expand_mask);
22352 } else {
22353 a = ir_analyze_shuffle_vector(ira, source_instr, scalar_type, a, undef, expand_mask);
22354 }
22355 }
22356
22357 IrInstruction *result = ir_build_shuffle_vector(&ira->new_irb,
22358 source_instr->scope, source_instr->source_node,
22359 nullptr, a, b, mask);
22360 result->value.type = result_type;
22361 return result;
22362}
22363
22364static IrInstruction *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrInstructionShuffleVector *instruction) {
22365 ZigType *scalar_type = ir_resolve_vector_elem_type(ira, instruction->scalar_type);
22366 if (type_is_invalid(scalar_type))
22367 return ira->codegen->invalid_instruction;
22368
22369 IrInstruction *a = instruction->a->child;
22370 if (type_is_invalid(a->value.type))
22371 return ira->codegen->invalid_instruction;
22372
22373 IrInstruction *b = instruction->b->child;
22374 if (type_is_invalid(b->value.type))
22375 return ira->codegen->invalid_instruction;
22376
22377 IrInstruction *mask = instruction->mask->child;
22378 if (type_is_invalid(mask->value.type))
22379 return ira->codegen->invalid_instruction;
22380
22381 return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, a, b, mask);
22382}
22383
22384static IrInstruction *ir_analyze_instruction_splat(IrAnalyze *ira, IrInstructionSplatSrc *instruction) {
22385 Error err;
22386
22387 IrInstruction *len = instruction->len->child;
22388 if (type_is_invalid(len->value.type))
22389 return ira->codegen->invalid_instruction;
22390
22391 IrInstruction *scalar = instruction->scalar->child;
22392 if (type_is_invalid(scalar->value.type))
22393 return ira->codegen->invalid_instruction;
22394
22395 uint64_t len_u64;
22396 if (!ir_resolve_unsigned(ira, len, ira->codegen->builtin_types.entry_u32, &len_u64))
22397 return ira->codegen->invalid_instruction;
22398 uint32_t len_int = len_u64;
22399
22400 if ((err = ir_validate_vector_elem_type(ira, scalar, scalar->value.type)))
22401 return ira->codegen->invalid_instruction;
22402
22403 ZigType *return_type = get_vector_type(ira->codegen, len_int, scalar->value.type);
22404
22405 if (instr_is_comptime(scalar)) {
22406 ConstExprValue *scalar_val = ir_resolve_const(ira, scalar, UndefOk);
22407 if (scalar_val == nullptr)
22408 return ira->codegen->invalid_instruction;
22409 if (scalar_val->special == ConstValSpecialUndef)
22410 return ir_const_undef(ira, &instruction->base, return_type);
22411
22412 IrInstruction *result = ir_const(ira, &instruction->base, return_type);
22413 result->value.data.x_array.data.s_none.elements = create_const_vals(len_int);
22414 for (uint32_t i = 0; i < len_int; i += 1) {
22415 copy_const_val(&result->value.data.x_array.data.s_none.elements[i], scalar_val, false);
22416 }
22417 return result;
22418 }
22419
22420 return ir_build_splat_gen(ira, &instruction->base, return_type, scalar);
2203522421}
2203622422
2203722423static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
......@@ -24970,21 +25356,35 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct
2497025356}
2497125357
2497225358static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
25359 Error err;
25360
2497325361 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
2497425362 if (type_is_invalid(int_type))
2497525363 return ira->codegen->invalid_instruction;
2497625364
24977 IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type);
24978 if (type_is_invalid(op->value.type))
25365 IrInstruction *uncasted_op = instruction->op->child;
25366 if (type_is_invalid(uncasted_op->value.type))
2497925367 return ira->codegen->invalid_instruction;
2498025368
24981 if (int_type->data.integral.bit_count == 0) {
24982 IrInstruction *result = ir_const(ira, &instruction->base, int_type);
24983 bigint_init_unsigned(&result->value.data.x_bigint, 0);
24984 return result;
25369 uint32_t vector_len; // UINT32_MAX means not a vector
25370 if (uncasted_op->value.type->id == ZigTypeIdArray &&
25371 is_valid_vector_elem_type(uncasted_op->value.type->data.array.child_type))
25372 {
25373 vector_len = uncasted_op->value.type->data.array.len;
25374 } else if (uncasted_op->value.type->id == ZigTypeIdVector) {
25375 vector_len = uncasted_op->value.type->data.vector.len;
25376 } else {
25377 vector_len = UINT32_MAX;
2498525378 }
2498625379
24987 if (int_type->data.integral.bit_count == 8)
25380 bool is_vector = (vector_len != UINT32_MAX);
25381 ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
25382
25383 IrInstruction *op = ir_implicit_cast(ira, uncasted_op, op_type);
25384 if (type_is_invalid(op->value.type))
25385 return ira->codegen->invalid_instruction;
25386
25387 if (int_type->data.integral.bit_count == 8 || int_type->data.integral.bit_count == 0)
2498825388 return op;
2498925389
2499025390 if (int_type->data.integral.bit_count % 8 != 0) {
......@@ -24999,20 +25399,44 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction
2499925399 if (val == nullptr)
2500025400 return ira->codegen->invalid_instruction;
2500125401 if (val->special == ConstValSpecialUndef)
25002 return ir_const_undef(ira, &instruction->base, int_type);
25402 return ir_const_undef(ira, &instruction->base, op_type);
2500325403
25004 IrInstruction *result = ir_const(ira, &instruction->base, int_type);
25404 IrInstruction *result = ir_const(ira, &instruction->base, op_type);
2500525405 size_t buf_size = int_type->data.integral.bit_count / 8;
2500625406 uint8_t *buf = allocate_nonzero<uint8_t>(buf_size);
25007 bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
25008 bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,
25009 int_type->data.integral.is_signed);
25407 if (is_vector) {
25408 expand_undef_array(ira->codegen, val);
25409 result->value.data.x_array.data.s_none.elements = create_const_vals(op_type->data.vector.len);
25410 for (unsigned i = 0; i < op_type->data.vector.len; i += 1) {
25411 ConstExprValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
25412 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
25413 op_elem_val, UndefOk)))
25414 {
25415 return ira->codegen->invalid_instruction;
25416 }
25417 ConstExprValue *result_elem_val = &result->value.data.x_array.data.s_none.elements[i];
25418 result_elem_val->type = int_type;
25419 result_elem_val->special = op_elem_val->special;
25420 if (op_elem_val->special == ConstValSpecialUndef)
25421 continue;
25422
25423 bigint_write_twos_complement(&op_elem_val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
25424 bigint_read_twos_complement(&result->value.data.x_array.data.s_none.elements[i].data.x_bigint,
25425 buf, int_type->data.integral.bit_count, false,
25426 int_type->data.integral.is_signed);
25427 }
25428 } else {
25429 bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
25430 bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,
25431 int_type->data.integral.is_signed);
25432 }
25433 free(buf);
2501025434 return result;
2501125435 }
2501225436
2501325437 IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,
2501425438 instruction->base.source_node, nullptr, op);
25015 result->value.type = int_type;
25439 result->value.type = op_type;
2501625440 return result;
2501725441}
2501825442
......@@ -25450,6 +25874,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2545025874 case IrInstructionIdTestErrGen:
2545125875 case IrInstructionIdFrameSizeGen:
2545225876 case IrInstructionIdAwaitGen:
25877 case IrInstructionIdSplatGen:
2545325878 zig_unreachable();
2545425879
2545525880 case IrInstructionIdReturn:
......@@ -25578,6 +26003,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2557826003 return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
2557926004 case IrInstructionIdVectorType:
2558026005 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
26006 case IrInstructionIdShuffleVector:
26007 return ir_analyze_instruction_shuffle_vector(ira, (IrInstructionShuffleVector *)instruction);
26008 case IrInstructionIdSplatSrc:
26009 return ir_analyze_instruction_splat(ira, (IrInstructionSplatSrc *)instruction);
2558126010 case IrInstructionIdBoolNot:
2558226011 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
2558326012 case IrInstructionIdMemset:
......@@ -25913,6 +26342,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2591326342 case IrInstructionIdTruncate:
2591426343 case IrInstructionIdIntType:
2591526344 case IrInstructionIdVectorType:
26345 case IrInstructionIdShuffleVector:
26346 case IrInstructionIdSplatSrc:
26347 case IrInstructionIdSplatGen:
2591626348 case IrInstructionIdBoolNot:
2591726349 case IrInstructionIdSliceSrc:
2591826350 case IrInstructionIdMemberCount:
src/ir_print.cpp+41
......@@ -42,6 +42,12 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {
4242 switch (instruction->id) {
4343 case IrInstructionIdInvalid:
4444 return "Invalid";
45 case IrInstructionIdShuffleVector:
46 return "Shuffle";
47 case IrInstructionIdSplatSrc:
48 return "SplatSrc";
49 case IrInstructionIdSplatGen:
50 return "SplatGen";
4551 case IrInstructionIdDeclVarSrc:
4652 return "DeclVarSrc";
4753 case IrInstructionIdDeclVarGen:
......@@ -1208,6 +1214,32 @@ static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruct
12081214 fprintf(irp->f, ")");
12091215}
12101216
1217static void ir_print_shuffle_vector(IrPrint *irp, IrInstructionShuffleVector *instruction) {
1218 fprintf(irp->f, "@shuffle(");
1219 ir_print_other_instruction(irp, instruction->scalar_type);
1220 fprintf(irp->f, ", ");
1221 ir_print_other_instruction(irp, instruction->a);
1222 fprintf(irp->f, ", ");
1223 ir_print_other_instruction(irp, instruction->b);
1224 fprintf(irp->f, ", ");
1225 ir_print_other_instruction(irp, instruction->mask);
1226 fprintf(irp->f, ")");
1227}
1228
1229static void ir_print_splat_src(IrPrint *irp, IrInstructionSplatSrc *instruction) {
1230 fprintf(irp->f, "@splat(");
1231 ir_print_other_instruction(irp, instruction->len);
1232 fprintf(irp->f, ", ");
1233 ir_print_other_instruction(irp, instruction->scalar);
1234 fprintf(irp->f, ")");
1235}
1236
1237static void ir_print_splat_gen(IrPrint *irp, IrInstructionSplatGen *instruction) {
1238 fprintf(irp->f, "@splat(");
1239 ir_print_other_instruction(irp, instruction->scalar);
1240 fprintf(irp->f, ")");
1241}
1242
12111243static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
12121244 fprintf(irp->f, "! ");
12131245 ir_print_other_instruction(irp, instruction->value);
......@@ -2143,6 +2175,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
21432175 case IrInstructionIdVectorType:
21442176 ir_print_vector_type(irp, (IrInstructionVectorType *)instruction);
21452177 break;
2178 case IrInstructionIdShuffleVector:
2179 ir_print_shuffle_vector(irp, (IrInstructionShuffleVector *)instruction);
2180 break;
2181 case IrInstructionIdSplatSrc:
2182 ir_print_splat_src(irp, (IrInstructionSplatSrc *)instruction);
2183 break;
2184 case IrInstructionIdSplatGen:
2185 ir_print_splat_gen(irp, (IrInstructionSplatGen *)instruction);
2186 break;
21462187 case IrInstructionIdBoolNot:
21472188 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
21482189 break;
src/list.hpp+1-1
......@@ -15,7 +15,7 @@ struct ZigList {
1515 void deinit() {
1616 free(items);
1717 }
18 void append(T item) {
18 void append(const T& item) {
1919 ensure_capacity(length + 1);
2020 items[length++] = item;
2121 }
src/main.cpp+1-1
......@@ -90,7 +90,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
9090 " -mllvm [arg] (unsupported) forward an arg to LLVM's option processing\n"
9191 " --override-std-dir [arg] override path to Zig standard library\n"
9292 " --override-lib-dir [arg] override path to Zig lib library\n"
93 " -ffunction-sections places each function in a seperate section\n"
93 " -ffunction-sections places each function in a separate section\n"
9494 "\n"
9595 "Link Options:\n"
9696 " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n"
std/event/channel.zig+2
......@@ -306,6 +306,8 @@ pub fn Channel(comptime T: type) type {
306306test "std.event.Channel" {
307307 // https://github.com/ziglang/zig/issues/1908
308308 if (builtin.single_threaded) return error.SkipZigTest;
309 // https://github.com/ziglang/zig/issues/3251
310 if (std.os.freebsd.is_the_target) return error.SkipZigTest;
309311
310312 var loop: Loop = undefined;
311313 // TODO make a multi threaded test
std/event/future.zig+2
......@@ -85,6 +85,8 @@ pub fn Future(comptime T: type) type {
8585test "std.event.Future" {
8686 // https://github.com/ziglang/zig/issues/1908
8787 if (builtin.single_threaded) return error.SkipZigTest;
88 // https://github.com/ziglang/zig/issues/3251
89 if (std.os.freebsd.is_the_target) return error.SkipZigTest;
8890
8991 const allocator = std.heap.direct_allocator;
9092
std/event/lock.zig+2
......@@ -118,6 +118,8 @@ pub const Lock = struct {
118118test "std.event.Lock" {
119119 // TODO https://github.com/ziglang/zig/issues/1908
120120 if (builtin.single_threaded) return error.SkipZigTest;
121 // TODO https://github.com/ziglang/zig/issues/3251
122 if (std.os.freebsd.is_the_target) return error.SkipZigTest;
121123
122124 const allocator = std.heap.direct_allocator;
123125
std/hash/auto_hash.zig+6-3
......@@ -116,7 +116,7 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {
116116 // Otherwise, hash every element.
117117 // TODO remove the copy to an array once field access is done.
118118 const array: [info.len]info.child = key;
119 comptime var i: u32 = 0;
119 comptime var i = 0;
120120 inline while (i < info.len) : (i += 1) {
121121 hash(hasher, array[i], strat);
122122 }
......@@ -357,10 +357,13 @@ test "testHash union" {
357357test "testHash vector" {
358358 const a: @Vector(4, u32) = [_]u32{ 1, 2, 3, 4 };
359359 const b: @Vector(4, u32) = [_]u32{ 1, 2, 3, 5 };
360 const c: @Vector(4, u31) = [_]u31{ 1, 2, 3, 4 };
361360 testing.expect(testHash(a) == testHash(a));
362361 testing.expect(testHash(a) != testHash(b));
363 testing.expect(testHash(a) != testHash(c));
362
363 const c: @Vector(4, u31) = [_]u31{ 1, 2, 3, 4 };
364 const d: @Vector(4, u31) = [_]u31{ 1, 2, 3, 5 };
365 testing.expect(testHash(c) == testHash(c));
366 testing.expect(testHash(c) != testHash(d));
364367}
365368
366369test "testHash error union" {
std/http/headers.zig+1-1
......@@ -299,7 +299,7 @@ pub const Headers = struct {
299299 return buf;
300300 }
301301
302 /// Returns all headers with the given name as a comma seperated string.
302 /// Returns all headers with the given name as a comma separated string.
303303 ///
304304 /// Useful for HTTP headers that follow RFC-7230 section 3.2.2:
305305 /// A recipient MAY combine multiple header fields with the same field
std/special/c.zig+2-7
......@@ -269,16 +269,11 @@ nakedcc fn clone() void {
269269 \\ bx lr
270270 \\
271271 \\1: mov r0,r6
272 \\ tst r5,#1
273 \\ bne 1f
274 \\ mov lr,pc
275 \\ mov pc,r5
272 \\ bl 3f
276273 \\2: mov r7,#1
277274 \\ svc 0
278 \\
279 \\1: mov lr,pc
280 \\ bx r5
281275 \\ b 2b
276 \\3: bx r5
282277 );
283278 } else {
284279 @compileError("Implement clone() for this arch.");
std/special/start.zig+1-1
......@@ -23,7 +23,7 @@ comptime {
2323 } else if (builtin.os == .uefi) {
2424 @export("EfiMain", EfiMain, .Strong);
2525 } else {
26 @export("_start", _start, .Strong);
26 if (!@hasDecl(root, "_start")) @export("_start", _start, .Strong);
2727 }
2828}
2929
std/zig/ast.zig+40-40
......@@ -255,39 +255,39 @@ pub const Error = union(enum) {
255255 }
256256 }
257257
258 pub const InvalidToken = SingleTokenError("Invalid token {}");
259 pub const ExpectedContainerMembers = SingleTokenError("Expected test, comptime, var decl, or container field, found {}");
260 pub const ExpectedStringLiteral = SingleTokenError("Expected string literal, found {}");
261 pub const ExpectedIntegerLiteral = SingleTokenError("Expected integer literal, found {}");
262 pub const ExpectedIdentifier = SingleTokenError("Expected identifier, found {}");
263 pub const ExpectedStatement = SingleTokenError("Expected statement, found {}");
264 pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}");
265 pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found {}");
266 pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found {}");
267 pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");
268 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");
269 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");
270 pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found {}");
271 pub const ExpectedLBrace = SingleTokenError("Expected '{{', found {}");
272 pub const ExpectedLabelOrLBrace = SingleTokenError("Expected label or '{{', found {}");
273 pub const ExpectedColonOrRParen = SingleTokenError("Expected ':' or ')', found {}");
274 pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found {}");
275 pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found {}");
276 pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ @tagName(Token.Id.Identifier) ++ ", found {}");
277 pub const ExpectedSliceOrRBracket = SingleTokenError("Expected ']' or '..', found {}");
278 pub const ExpectedTypeExpr = SingleTokenError("Expected type expression, found {}");
279 pub const ExpectedPrimaryTypeExpr = SingleTokenError("Expected primary type expression, found {}");
280 pub const ExpectedExpr = SingleTokenError("Expected expression, found {}");
281 pub const ExpectedPrimaryExpr = SingleTokenError("Expected primary expression, found {}");
282 pub const ExpectedParamList = SingleTokenError("Expected parameter list, found {}");
283 pub const ExpectedPayload = SingleTokenError("Expected loop payload, found {}");
284 pub const ExpectedBlockOrAssignment = SingleTokenError("Expected block or assignment, found {}");
285 pub const ExpectedBlockOrExpression = SingleTokenError("Expected block or expression, found {}");
286 pub const ExpectedExprOrAssignment = SingleTokenError("Expected expression or assignment, found {}");
287 pub const ExpectedPrefixExpr = SingleTokenError("Expected prefix expression, found {}");
288 pub const ExpectedLoopExpr = SingleTokenError("Expected loop expression, found {}");
289 pub const ExpectedDerefOrUnwrap = SingleTokenError("Expected pointer dereference or optional unwrap, found {}");
290 pub const ExpectedSuffixOp = SingleTokenError("Expected pointer dereference, optional unwrap, or field access, found {}");
258 pub const InvalidToken = SingleTokenError("Invalid token '{}'");
259 pub const ExpectedContainerMembers = SingleTokenError("Expected test, comptime, var decl, or container field, found '{}'");
260 pub const ExpectedStringLiteral = SingleTokenError("Expected string literal, found '{}'");
261 pub const ExpectedIntegerLiteral = SingleTokenError("Expected integer literal, found '{}'");
262 pub const ExpectedIdentifier = SingleTokenError("Expected identifier, found '{}'");
263 pub const ExpectedStatement = SingleTokenError("Expected statement, found '{}'");
264 pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found '{}'");
265 pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{}'");
266 pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found '{}'");
267 pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', or '" ++ Token.Id.Keyword_enum.symbol() ++ "', found '{}'");
268 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{}'");
269 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found '{}'");
270 pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found '{}'");
271 pub const ExpectedLBrace = SingleTokenError("Expected '{{', found '{}'");
272 pub const ExpectedLabelOrLBrace = SingleTokenError("Expected label or '{{', found '{}'");
273 pub const ExpectedColonOrRParen = SingleTokenError("Expected ':' or ')', found '{}'");
274 pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found '{}'");
275 pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found '{}'");
276 pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or '" ++ Token.Id.Identifier.symbol() ++ "', found '{}'");
277 pub const ExpectedSliceOrRBracket = SingleTokenError("Expected ']' or '..', found '{}'");
278 pub const ExpectedTypeExpr = SingleTokenError("Expected type expression, found '{}'");
279 pub const ExpectedPrimaryTypeExpr = SingleTokenError("Expected primary type expression, found '{}'");
280 pub const ExpectedExpr = SingleTokenError("Expected expression, found '{}'");
281 pub const ExpectedPrimaryExpr = SingleTokenError("Expected primary expression, found '{}'");
282 pub const ExpectedParamList = SingleTokenError("Expected parameter list, found '{}'");
283 pub const ExpectedPayload = SingleTokenError("Expected loop payload, found '{}'");
284 pub const ExpectedBlockOrAssignment = SingleTokenError("Expected block or assignment, found '{}'");
285 pub const ExpectedBlockOrExpression = SingleTokenError("Expected block or expression, found '{}'");
286 pub const ExpectedExprOrAssignment = SingleTokenError("Expected expression or assignment, found '{}'");
287 pub const ExpectedPrefixExpr = SingleTokenError("Expected prefix expression, found '{}'");
288 pub const ExpectedLoopExpr = SingleTokenError("Expected loop expression, found '{}'");
289 pub const ExpectedDerefOrUnwrap = SingleTokenError("Expected pointer dereference or optional unwrap, found '{}'");
290 pub const ExpectedSuffixOp = SingleTokenError("Expected pointer dereference, optional unwrap, or field access, found '{}'");
291291
292292 pub const ExpectedParamType = SimpleError("Expected parameter type");
293293 pub const ExpectedPubItem = SimpleError("Pub must be followed by fn decl, var decl, or container member");
......@@ -324,11 +324,11 @@ pub const Error = union(enum) {
324324 return stream.print("`&&` is invalid. Note that `and` is boolean AND.");
325325 },
326326 .Invalid => {
327 return stream.print("expected {}, found invalid bytes", @tagName(self.expected_id));
327 return stream.print("expected '{}', found invalid bytes", self.expected_id.symbol());
328328 },
329329 else => {
330 const token_name = @tagName(found_token.id);
331 return stream.print("expected {}, found {}", @tagName(self.expected_id), token_name);
330 const token_name = found_token.id.symbol();
331 return stream.print("expected '{}', found '{}'", self.expected_id.symbol(), token_name);
332332 },
333333 }
334334 }
......@@ -339,8 +339,8 @@ pub const Error = union(enum) {
339339 end_id: Token.Id,
340340
341341 pub fn render(self: *const ExpectedCommaOrEnd, tokens: *Tree.TokenList, stream: var) !void {
342 const token_name = @tagName(tokens.at(self.token).id);
343 return stream.print("expected ',' or {}, found {}", @tagName(self.end_id), token_name);
342 const actual_token = tokens.at(self.token);
343 return stream.print("expected ',' or '{}', found '{}'", self.end_id.symbol(), actual_token.id.symbol());
344344 }
345345 };
346346
......@@ -351,8 +351,8 @@ pub const Error = union(enum) {
351351 token: TokenIndex,
352352
353353 pub fn render(self: *const ThisError, tokens: *Tree.TokenList, stream: var) !void {
354 const token_name = @tagName(tokens.at(self.token).id);
355 return stream.print(msg, token_name);
354 const actual_token = tokens.at(self.token);
355 return stream.print(msg, actual_token.id.symbol());
356356 }
357357 };
358358 }
std/zig/tokenizer.zig+125
......@@ -196,6 +196,131 @@ pub const Token = struct {
196196 Keyword_var,
197197 Keyword_volatile,
198198 Keyword_while,
199
200 pub fn symbol(id: Id) []const u8 {
201 return switch (id) {
202 .Invalid => "Invalid",
203 .Invalid_ampersands => "&&",
204 .Identifier => "Identifier",
205 .StringLiteral => "StringLiteral",
206 .MultilineStringLiteralLine => "MultilineStringLiteralLine",
207 .CharLiteral => "CharLiteral",
208 .Eof => "Eof",
209 .Builtin => "Builtin",
210 .IntegerLiteral => "IntegerLiteral",
211 .FloatLiteral => "FloatLiteral",
212 .LineComment => "LineComment",
213 .DocComment => "DocComment",
214 .ShebangLine => "ShebangLine",
215
216 .Bang => "!",
217 .Pipe => "|",
218 .PipePipe => "||",
219 .PipeEqual => "|=",
220 .Equal => "=",
221 .EqualEqual => "==",
222 .EqualAngleBracketRight => "=>",
223 .BangEqual => "!=",
224 .LParen => "(",
225 .RParen => ")",
226 .Semicolon => ";",
227 .Percent => "%",
228 .PercentEqual => "%=",
229 .LBrace => "{",
230 .RBrace => "}",
231 .LBracket => "[",
232 .RBracket => "]",
233 .Period => ".",
234 .Ellipsis2 => "..",
235 .Ellipsis3 => "...",
236 .Caret => "^",
237 .CaretEqual => "^=",
238 .Plus => "+",
239 .PlusPlus => "++",
240 .PlusEqual => "+=",
241 .PlusPercent => "+%",
242 .PlusPercentEqual => "+%=",
243 .Minus => "-",
244 .MinusEqual => "-=",
245 .MinusPercent => "-%",
246 .MinusPercentEqual => "-%=",
247 .Asterisk => "*",
248 .AsteriskEqual => "*=",
249 .AsteriskAsterisk => "**",
250 .AsteriskPercent => "*%",
251 .AsteriskPercentEqual => "*%=",
252 .Arrow => "->",
253 .Colon => ":",
254 .Slash => "/",
255 .SlashEqual => "/=",
256 .Comma => ",",
257 .Ampersand => "&",
258 .AmpersandEqual => "&=",
259 .QuestionMark => "?",
260 .AngleBracketLeft => "<",
261 .AngleBracketLeftEqual => "<=",
262 .AngleBracketAngleBracketLeft => "<<",
263 .AngleBracketAngleBracketLeftEqual => "<<=",
264 .AngleBracketRight => ">",
265 .AngleBracketRightEqual => ">=",
266 .AngleBracketAngleBracketRight => ">>",
267 .AngleBracketAngleBracketRightEqual => ">>=",
268 .Tilde => "~",
269 .BracketStarBracket => "[*]",
270 .BracketStarCBracket => "[*c]",
271 .Keyword_align => "align",
272 .Keyword_allowzero => "allowzero",
273 .Keyword_and => "and",
274 .Keyword_anyframe => "anyframe",
275 .Keyword_asm => "asm",
276 .Keyword_async => "async",
277 .Keyword_await => "await",
278 .Keyword_break => "break",
279 .Keyword_catch => "catch",
280 .Keyword_comptime => "comptime",
281 .Keyword_const => "const",
282 .Keyword_continue => "continue",
283 .Keyword_defer => "defer",
284 .Keyword_else => "else",
285 .Keyword_enum => "enum",
286 .Keyword_errdefer => "errdefer",
287 .Keyword_error => "error",
288 .Keyword_export => "export",
289 .Keyword_extern => "extern",
290 .Keyword_false => "false",
291 .Keyword_fn => "fn",
292 .Keyword_for => "for",
293 .Keyword_if => "if",
294 .Keyword_inline => "inline",
295 .Keyword_nakedcc => "nakedcc",
296 .Keyword_noalias => "noalias",
297 .Keyword_noasync => "noasync",
298 .Keyword_noinline => "noinline",
299 .Keyword_null => "null",
300 .Keyword_or => "or",
301 .Keyword_orelse => "orelse",
302 .Keyword_packed => "packed",
303 .Keyword_pub => "pub",
304 .Keyword_resume => "resume",
305 .Keyword_return => "return",
306 .Keyword_linksection => "linksection",
307 .Keyword_stdcallcc => "stdcallcc",
308 .Keyword_struct => "struct",
309 .Keyword_suspend => "suspend",
310 .Keyword_switch => "switch",
311 .Keyword_test => "test",
312 .Keyword_threadlocal => "threadlocal",
313 .Keyword_true => "true",
314 .Keyword_try => "try",
315 .Keyword_undefined => "undefined",
316 .Keyword_union => "union",
317 .Keyword_unreachable => "unreachable",
318 .Keyword_usingnamespace => "usingnamespace",
319 .Keyword_var => "var",
320 .Keyword_volatile => "volatile",
321 .Keyword_while => "while",
322 };
323 }
199324 };
200325};
201326
test/compile_errors.zig+24-1
......@@ -6484,6 +6484,19 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
64846484 "tmp.zig:7:23: error: unable to evaluate constant expression",
64856485 );
64866486
6487 cases.addTest(
6488 "@shuffle with selected index past first vector length",
6489 \\export fn entry() void {
6490 \\ const v: @Vector(4, u32) = [4]u32{ 10, 11, 12, 13 };
6491 \\ const x: @Vector(4, u32) = [4]u32{ 14, 15, 16, 17 };
6492 \\ var z = @shuffle(u32, v, x, [8]i32{ 0, 1, 2, 3, 7, 6, 5, 4 });
6493 \\}
6494 ,
6495 "tmp.zig:4:39: error: mask index '4' has out-of-bounds selection",
6496 "tmp.zig:4:27: note: selected index '7' out of bounds of @Vector(4, u32)",
6497 "tmp.zig:4:30: note: selections from the second vector are specified with negative numbers",
6498 );
6499
64876500 cases.addTest(
64886501 "nested vectors",
64896502 \\export fn entry() void {
......@@ -6491,7 +6504,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
64916504 \\ var v: V = undefined;
64926505 \\}
64936506 ,
6494 "tmp.zig:2:26: error: vector element type must be integer, float, or pointer; '@Vector(4, u8)' is invalid",
6507 "tmp.zig:2:26: error: vector element type must be integer, float, bool, or pointer; '@Vector(4, u8)' is invalid",
6508 );
6509
6510 cases.addTest(
6511 "bad @splat type",
6512 \\export fn entry() void {
6513 \\ const c = 4;
6514 \\ var v = @splat(4, c);
6515 \\}
6516 ,
6517 "tmp.zig:3:23: error: vector element type must be integer, float, bool, or pointer; 'comptime_int' is invalid",
64956518 );
64966519
64976520 cases.add("compileLog of tagged enum doesn't crash the compiler",
test/stage1/behavior.zig+1
......@@ -80,6 +80,7 @@ comptime {
8080 _ = @import("behavior/pub_enum.zig");
8181 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
8282 _ = @import("behavior/reflection.zig");
83 _ = @import("behavior/shuffle.zig");
8384 _ = @import("behavior/sizeof_and_typeof.zig");
8485 _ = @import("behavior/slice.zig");
8586 _ = @import("behavior/slicetobytes.zig");
test/stage1/behavior/byteswap.zig+55-25
......@@ -1,32 +1,62 @@
11const std = @import("std");
22const expect = std.testing.expect;
33
4test "@byteSwap" {
5 comptime testByteSwap();
6 testByteSwap();
4test "@byteSwap integers" {
5 const ByteSwapIntTest = struct {
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();
739}
840
9fn testByteSwap() void {
10 expect(@byteSwap(u0, 0) == 0);
11 expect(@byteSwap(u8, 0x12) == 0x12);
12 expect(@byteSwap(u16, 0x1234) == 0x3412);
13 expect(@byteSwap(u24, 0x123456) == 0x563412);
14 expect(@byteSwap(u32, 0x12345678) == 0x78563412);
15 expect(@byteSwap(u40, 0x123456789a) == 0x9a78563412);
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);
41test "@byteSwap vectors" {
42 const ByteSwapVectorTest = struct {
43 fn run() void {
44 t(u8, 2, [_]u8{ 0x12, 0x13 }, [_]u8{ 0x12, 0x13 });
45 t(u16, 2, [_]u16{ 0x1234, 0x2345 }, [_]u16{ 0x3412, 0x4523 });
46 t(u24, 2, [_]u24{ 0x123456, 0x234567 }, [_]u24{ 0x563412, 0x674523 });
47 }
2048
21 expect(@byteSwap(u0, u0(0)) == 0);
22 expect(@byteSwap(i8, i8(-50)) == -50);
23 expect(@byteSwap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
24 expect(@byteSwap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
25 expect(@byteSwap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
26 expect(@byteSwap(u40, @bitCast(i40, u40(0x123456789a))) == u40(0x9a78563412));
27 expect(@byteSwap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
28 expect(@byteSwap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
29 expect(@byteSwap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
30 expect(@byteSwap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
31 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
49 fn t(
50 comptime I: type,
51 comptime n: comptime_int,
52 input: @Vector(n, I),
53 expected_vector: @Vector(n, I),
54 ) void {
55 const actual_output: [n]I = @byteSwap(I, input);
56 const expected_output: [n]I = expected_vector;
57 std.testing.expectEqual(expected_output, actual_output);
58 }
59 };
60 comptime ByteSwapVectorTest.run();
61 ByteSwapVectorTest.run();
3262}
test/stage1/behavior/misc.zig+20
......@@ -721,3 +721,23 @@ test "global variable assignment with optional unwrapping with var initialized t
721721 };
722722 expect(global_foo.* == 1234);
723723}
724
725test "peer result location with typed parent, runtime condition, comptime prongs" {
726 const S = struct {
727 fn doTheTest(arg: i32) i32 {
728 const st = Structy{
729 .bleh = if (arg == 1) 1 else 1,
730 };
731
732 if (st.bleh == 1)
733 return 1234;
734 return 0;
735 }
736
737 const Structy = struct {
738 bleh: i32,
739 };
740 };
741 expect(S.doTheTest(0) == 1234);
742 expect(S.doTheTest(1) == 1234);
743}
test/stage1/behavior/shuffle.zig created+57
......@@ -0,0 +1,57 @@
1const std = @import("std");
2const mem = std.mem;
3const expect = std.testing.expect;
4
5test "@shuffle" {
6 const S = struct {
7 fn doTheTest() void {
8 var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
9 var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
10 const mask: @Vector(4, i32) = [4]i32{ 0, ~i32(2), 3, ~i32(3) };
11 var res = @shuffle(i32, v, x, mask);
12 expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 2147483647, 3, 40, 4 }));
13
14 // Implicit cast from array (of mask)
15 res = @shuffle(i32, v, x, [4]i32{ 0, ~i32(2), 3, ~i32(3) });
16 expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 2147483647, 3, 40, 4 }));
17
18 // Undefined
19 const mask2: @Vector(4, i32) = [4]i32{ 3, 1, 2, 0 };
20 res = @shuffle(i32, v, undefined, mask2);
21 expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 40, -2, 30, 2147483647 }));
22
23 // Upcasting of b
24 var v2: @Vector(2, i32) = [2]i32{ 2147483647, undefined };
25 const mask3: @Vector(4, i32) = [4]i32{ ~i32(0), 2, ~i32(0), 3 };
26 res = @shuffle(i32, x, v2, mask3);
27 expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 2147483647, 3, 2147483647, 4 }));
28
29 // Upcasting of a
30 var v3: @Vector(2, i32) = [2]i32{ 2147483647, -2 };
31 const mask4: @Vector(4, i32) = [4]i32{ 0, ~i32(2), 1, ~i32(3) };
32 res = @shuffle(i32, v3, x, mask4);
33 expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 2147483647, 3, -2, 4 }));
34
35 // bool
36 {
37 var x2: @Vector(4, bool) = [4]bool{ false, true, false, true };
38 var v4: @Vector(2, bool) = [2]bool{ true, false };
39 const mask5: @Vector(4, i32) = [4]i32{ 0, ~i32(1), 1, 2 };
40 var res2 = @shuffle(bool, x2, v4, mask5);
41 expect(mem.eql(bool, ([4]bool)(res2), [4]bool{ false, false, true, false }));
42 }
43
44 // TODO re-enable when LLVM codegen is fixed
45 // https://github.com/ziglang/zig/issues/3246
46 if (false) {
47 var x2: @Vector(3, bool) = [3]bool{ false, true, false };
48 var v4: @Vector(2, bool) = [2]bool{ true, false };
49 const mask5: @Vector(4, i32) = [4]i32{ 0, ~i32(1), 1, 2 };
50 var res2 = @shuffle(bool, x2, v4, mask5);
51 expect(mem.eql(bool, ([4]bool)(res2), [4]bool{ false, false, true, false }));
52 }
53 }
54 };
55 S.doTheTest();
56 comptime S.doTheTest();
57}
test/stage1/behavior/vector.zig+75
......@@ -2,6 +2,18 @@ const std = @import("std");
22const mem = std.mem;
33const expect = std.testing.expect;
44
5test "implicit cast vector to array - bool" {
6 const S = struct {
7 fn doTheTest() void {
8 const a: @Vector(4, bool) = [_]bool{ true, false, true, false };
9 const result_array: [4]bool = a;
10 expect(mem.eql(bool, result_array, [4]bool{ true, false, true, false }));
11 }
12 };
13 S.doTheTest();
14 comptime S.doTheTest();
15}
16
517test "vector wrap operators" {
618 const S = struct {
719 fn doTheTest() void {
......@@ -18,6 +30,23 @@ test "vector wrap operators" {
1830 comptime S.doTheTest();
1931}
2032
33test "vector bin compares with mem.eql" {
34 const S = struct {
35 fn doTheTest() void {
36 var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
37 var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 };
38 expect(mem.eql(bool, ([4]bool)(v == x), [4]bool{ false, false, true, false }));
39 expect(mem.eql(bool, ([4]bool)(v != x), [4]bool{ true, true, false, true }));
40 expect(mem.eql(bool, ([4]bool)(v < x), [4]bool{ false, true, false, false }));
41 expect(mem.eql(bool, ([4]bool)(v > x), [4]bool{ true, false, false, true }));
42 expect(mem.eql(bool, ([4]bool)(v <= x), [4]bool{ false, true, true, false }));
43 expect(mem.eql(bool, ([4]bool)(v >= x), [4]bool{ true, false, true, true }));
44 }
45 };
46 S.doTheTest();
47 comptime S.doTheTest();
48}
49
2150test "vector int operators" {
2251 const S = struct {
2352 fn doTheTest() void {
......@@ -80,3 +109,49 @@ test "array to vector" {
80109 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
81110 var vec: @Vector(4, f32) = arr;
82111}
112
113test "vector casts of sizes not divisable by 8" {
114 const S = struct {
115 fn doTheTest() void {
116 {
117 var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0 };
118 var x: [4]u3 = v;
119 expect(mem.eql(u3, x, ([4]u3)(v)));
120 }
121 {
122 var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0 };
123 var x: [4]u2 = v;
124 expect(mem.eql(u2, x, ([4]u2)(v)));
125 }
126 {
127 var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0 };
128 var x: [4]u1 = v;
129 expect(mem.eql(u1, x, ([4]u1)(v)));
130 }
131 {
132 var v: @Vector(4, bool) = [4]bool{ false, false, true, false };
133 var x: [4]bool = v;
134 expect(mem.eql(bool, x, ([4]bool)(v)));
135 }
136 }
137 };
138 S.doTheTest();
139 comptime S.doTheTest();
140}
141
142test "vector @splat" {
143 const S = struct {
144 fn doTheTest() void {
145 var v: u32 = 5;
146 var x = @splat(4, v);
147 expect(@typeOf(x) == @Vector(4, u32));
148 var array_x: [4]u32 = x;
149 expect(array_x[0] == 5);
150 expect(array_x[1] == 5);
151 expect(array_x[2] == 5);
152 expect(array_x[3] == 5);
153 }
154 };
155 S.doTheTest();
156 comptime S.doTheTest();
157}