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 (...@@ -5864,7 +5864,7 @@ volatile (
5864 : [number] "{rax}" (number),5864 : [number] "{rax}" (number),
5865 [arg1] "{rdi}" (arg1)5865 [arg1] "{rdi}" (arg1)
5866// Next is the list of clobbers. These declare a set of registers whose5866// 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.
5868// These do not include output or input registers. The special clobber5868// These do not include output or input registers. The special clobber
5869// value of "memory" means that the assembly writes to arbitrary undeclared5869// value of "memory" means that the assembly writes to arbitrary undeclared
5870// memory locations - not only the memory pointed to by a declared indirect5870// memory locations - not only the memory pointed to by a declared indirect
...@@ -5885,7 +5885,7 @@ volatile (...@@ -5885,7 +5885,7 @@ volatile (
5885 </p>5885 </p>
5886 {#header_open|Output Constraints#}5886 {#header_open|Output Constraints#}
5887 <p>5887 <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
5889 so5889 so
5890 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>5890 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>
5891 and5891 and
...@@ -5900,7 +5900,7 @@ volatile (...@@ -5900,7 +5900,7 @@ volatile (
59005900
5901 {#header_open|Input Constraints#}5901 {#header_open|Input Constraints#}
5902 <p>5902 <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
5904 so5904 so
5905 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>5905 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>
5906 and5906 and
...@@ -5919,7 +5919,7 @@ volatile (...@@ -5919,7 +5919,7 @@ volatile (
5919 the assembly code. These do not include output or input registers. The special clobber5919 the assembly code. These do not include output or input registers. The special clobber
5920 value of {#syntax#}"memory"{#endsyntax#} means that the assembly causes writes to5920 value of {#syntax#}"memory"{#endsyntax#} means that the assembly causes writes to
5921 arbitrary undeclared memory locations - not only the memory pointed to by a declared5921 arbitrary undeclared memory locations - not only the memory pointed to by a declared
5922 indirect output. 5922 indirect output.
5923 </p>5923 </p>
5924 <p>5924 <p>
5925 Failure to declare the full set of clobbers for a given inline assembly5925 Failure to declare the full set of clobbers for a given inline assembly
...@@ -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#}
...@@ -6641,7 +6650,7 @@ async fn func(y: *i32) void {...@@ -6641,7 +6650,7 @@ async fn func(y: *i32) void {
6641 {#header_open|@clz#}6650 {#header_open|@clz#}
6642 <pre>{#syntax#}@clz(comptime T: type, integer: T){#endsyntax#}</pre>6651 <pre>{#syntax#}@clz(comptime T: type, integer: T){#endsyntax#}</pre>
6643 <p>6652 <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#}.
6645 </p>6654 </p>
6646 <p>6655 <p>
6647 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#},6656 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#},
...@@ -6783,7 +6792,7 @@ test "main" {...@@ -6783,7 +6792,7 @@ test "main" {
6783 {#header_open|@ctz#}6792 {#header_open|@ctz#}
6784 <pre>{#syntax#}@ctz(comptime T: type, integer: T){#endsyntax#}</pre>6793 <pre>{#syntax#}@ctz(comptime T: type, integer: T){#endsyntax#}</pre>
6785 <p>6794 <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#}.
6787 </p>6796 </p>
6788 <p>6797 <p>
6789 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#},6798 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#},
...@@ -7673,6 +7682,43 @@ test "@setRuntimeSafety" {...@@ -7673,6 +7682,43 @@ test "@setRuntimeSafety" {
7673 {#see_also|@shlExact|@shlWithOverflow#}7682 {#see_also|@shlExact|@shlWithOverflow#}
7674 {#header_close#}7683 {#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
7676 {#header_open|@sizeOf#}7722 {#header_open|@sizeOf#}
7677 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>7723 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>
7678 <p>7724 <p>
...@@ -7700,6 +7746,30 @@ test "@setRuntimeSafety" {...@@ -7700,6 +7746,30 @@ test "@setRuntimeSafety" {
7700 </p>7746 </p>
7701 {#header_close#}7747 {#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
7703 {#header_open|@sqrt#}7773 {#header_open|@sqrt#}
7704 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>7774 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>
7705 <p>7775 <p>
...@@ -9411,8 +9481,8 @@ const c = @cImport({...@@ -9411,8 +9481,8 @@ const c = @cImport({
9411 <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}9481 <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
9412 please!</li>9482 please!</li>
9413 </ul>9483 </ul>
9414 <p>When a C pointer is pointing to a single struct (not an array), deference the C pointer to 9484 <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 9485 access to the struct's fields or member data. That syntax looks like
9416 this: </p>9486 this: </p>
9417 <p>{#syntax#}ptr_to_struct.*.struct_member{#endsyntax#}</p>9487 <p>{#syntax#}ptr_to_struct.*.struct_member{#endsyntax#}</p>
9418 <p>This is comparable to doing {#syntax#}->{#endsyntax#} in C.</p>9488 <p>This is comparable to doing {#syntax#}->{#endsyntax#} in C.</p>
src/all_types.hpp+29-1
...@@ -1351,7 +1351,7 @@ struct ZigTypeBoundFn {...@@ -1351,7 +1351,7 @@ struct ZigTypeBoundFn {
1351};1351};
13521352
1353struct ZigTypeVector {1353struct ZigTypeVector {
1354 // The type must be a pointer, integer, or float1354 // The type must be a pointer, integer, bool, or float
1355 ZigType *elem_type;1355 ZigType *elem_type;
1356 uint32_t len;1356 uint32_t len;
1357};1357};
...@@ -1611,6 +1611,8 @@ enum BuiltinFnId {...@@ -1611,6 +1611,8 @@ enum BuiltinFnId {
1611 BuiltinFnIdIntToEnum,1611 BuiltinFnIdIntToEnum,
1612 BuiltinFnIdIntType,1612 BuiltinFnIdIntType,
1613 BuiltinFnIdVectorType,1613 BuiltinFnIdVectorType,
1614 BuiltinFnIdShuffle,
1615 BuiltinFnIdSplat,
1614 BuiltinFnIdSetCold,1616 BuiltinFnIdSetCold,
1615 BuiltinFnIdSetRuntimeSafety,1617 BuiltinFnIdSetRuntimeSafety,
1616 BuiltinFnIdSetFloatMode,1618 BuiltinFnIdSetFloatMode,
...@@ -1770,6 +1772,7 @@ struct ZigLLVMFnKey {...@@ -1770,6 +1772,7 @@ struct ZigLLVMFnKey {
1770 } overflow_arithmetic;1772 } overflow_arithmetic;
1771 struct {1773 struct {
1772 uint32_t bit_count;1774 uint32_t bit_count;
1775 uint32_t vector_len; // 0 means not a vector
1773 } bswap;1776 } bswap;
1774 struct {1777 struct {
1775 uint32_t bit_count;1778 uint32_t bit_count;
...@@ -2428,6 +2431,9 @@ enum IrInstructionId {...@@ -2428,6 +2431,9 @@ enum IrInstructionId {
2428 IrInstructionIdBoolToInt,2431 IrInstructionIdBoolToInt,
2429 IrInstructionIdIntType,2432 IrInstructionIdIntType,
2430 IrInstructionIdVectorType,2433 IrInstructionIdVectorType,
2434 IrInstructionIdShuffleVector,
2435 IrInstructionIdSplatSrc,
2436 IrInstructionIdSplatGen,
2431 IrInstructionIdBoolNot,2437 IrInstructionIdBoolNot,
2432 IrInstructionIdMemset,2438 IrInstructionIdMemset,
2433 IrInstructionIdMemcpy,2439 IrInstructionIdMemcpy,
...@@ -3669,6 +3675,28 @@ struct IrInstructionVectorToArray {...@@ -3669,6 +3675,28 @@ struct IrInstructionVectorToArray {
3669 IrInstruction *result_loc;3675 IrInstruction *result_loc;
3670};3676};
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
3672struct IrInstructionAssertZero {3700struct IrInstructionAssertZero {
3673 IrInstruction base;3701 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) {...@@ -4708,6 +4708,7 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
4708bool is_valid_vector_elem_type(ZigType *elem_type) {4708bool is_valid_vector_elem_type(ZigType *elem_type) {
4709 return elem_type->id == ZigTypeIdInt ||4709 return elem_type->id == ZigTypeIdInt ||
4710 elem_type->id == ZigTypeIdFloat ||4710 elem_type->id == ZigTypeIdFloat ||
4711 elem_type->id == ZigTypeIdBool ||
4711 get_codegen_ptr_type(elem_type) != nullptr;4712 get_codegen_ptr_type(elem_type) != nullptr;
4712}4713}
47134714
...@@ -4727,7 +4728,7 @@ ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {...@@ -4727,7 +4728,7 @@ ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
47274728
4728 ZigType *entry = new_type_table_entry(ZigTypeIdVector);4729 ZigType *entry = new_type_table_entry(ZigTypeIdVector);
4729 if ((len != 0) && type_has_bits(elem_type)) {4730 if ((len != 0) && type_has_bits(elem_type)) {
4730 // Vectors can only be ints, floats, or pointers. ints and floats have trivially resolvable4731 // Vectors can only be ints, floats, bools, or pointers. ints (inc. bools) and floats have trivially resolvable
4731 // llvm type refs. pointers we will use usize instead.4732 // llvm type refs. pointers we will use usize instead.
4732 LLVMTypeRef example_vector_llvm_type;4733 LLVMTypeRef example_vector_llvm_type;
4733 if (elem_type->id == ZigTypeIdPointer) {4734 if (elem_type->id == ZigTypeIdPointer) {
...@@ -6895,7 +6896,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {...@@ -6895,7 +6896,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
6895 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) +
6896 (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);
6897 case ZigLLVMFnIdBswap:6898 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);
6899 case ZigLLVMFnIdBitReverse:6901 case ZigLLVMFnIdBitReverse:
6900 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;
6901 case ZigLLVMFnIdOverflowArithmetic:6903 case ZigLLVMFnIdOverflowArithmetic:
...@@ -6918,7 +6920,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {...@@ -6918,7 +6920,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
6918 case ZigLLVMFnIdPopCount:6920 case ZigLLVMFnIdPopCount:
6919 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;
6920 case ZigLLVMFnIdBswap:6922 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;
6922 case ZigLLVMFnIdBitReverse:6925 case ZigLLVMFnIdBitReverse:
6923 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;
6924 case ZigLLVMFnIdFloatOp:6927 case ZigLLVMFnIdFloatOp:
src/codegen.cpp+131-20
...@@ -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
...@@ -4581,6 +4589,48 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru...@@ -4581,6 +4589,48 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru
4581 return gen_widen_or_shorten(g, false, int_type, instruction->base.value.type, wrong_size_int);4589 return gen_widen_or_shorten(g, false, int_type, instruction->base.value.type, wrong_size_int);
4582}4590}
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
4584static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {4634static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {
4585 ZigType *int_type = instruction->op->value.type;4635 ZigType *int_type = instruction->op->value.type;
4586 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);4636 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...@@ -5512,25 +5562,36 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrIn
55125562
5513static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {5563static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {
5514 LLVMValueRef op = ir_llvm_value(g, instruction->op);5564 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;
5516 assert(int_type->id == ZigTypeIdInt);5568 assert(int_type->id == ZigTypeIdInt);
5517 if (int_type->data.integral.bit_count % 16 == 0) {5569 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);
5519 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");5571 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5520 }5572 }
5521 // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate5573 // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate
5522 ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,5574 ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,
5523 int_type->data.integral.bit_count + 8);5575 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 }
5524 // aabbcc5586 // aabbcc
5525 LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), "");5587 LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), "");
5526 // 00aabbcc5588 // 00aabbcc
5527 LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);5589 LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);
5528 LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, "");5590 LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, "");
5529 // ccbbaa005591 // ccbbaa00
5530 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped,5592 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, shift_amt, "");
5531 LLVMConstInt(get_llvm_type(g, extended_type), 8, false), "");
5532 // 00ccbbaa5593 // 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), "");
5534}5595}
55355596
5536static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) {5597static 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...@@ -5549,10 +5610,29 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab
5549 assert(handle_is_ptr(array_type));5610 assert(handle_is_ptr(array_type));
5550 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);5611 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
5551 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);5612 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
5552 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,5613
5553 LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");5614 ZigType *elem_type = array_type->data.array.child_type;
5554 uint32_t alignment = get_ptr_align(g, instruction->result_loc->value.type);5615 bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8;
5555 gen_store_untyped(g, vector, casted_ptr, alignment, false);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 }
5556 return result_loc;5636 return result_loc;
5557}5637}
55585638
...@@ -5563,12 +5643,34 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab...@@ -5563,12 +5643,34 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab
5563 assert(vector_type->id == ZigTypeIdVector);5643 assert(vector_type->id == ZigTypeIdVector);
5564 assert(!handle_is_ptr(vector_type));5644 assert(!handle_is_ptr(vector_type));
5565 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);5645 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
5566 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,5646 LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type);
5567 LLVMPointerType(get_llvm_type(g, vector_type), 0), "");5647
5568 ZigType *array_type = instruction->array->value.type;5648 ZigType *elem_type = vector_type->data.vector.elem_type;
5569 assert(array_type->id == ZigTypeIdArray);5649 bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8;
5570 uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type);5650 if (bitcast_ok) {
5571 return gen_load_untyped(g, casted_ptr, alignment, false, "");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 }
5572}5674}
55735675
5574static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,5676static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,
...@@ -5896,6 +5998,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5896,6 +5998,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5896 case IrInstructionIdFrameSizeSrc:5998 case IrInstructionIdFrameSizeSrc:
5897 case IrInstructionIdAllocaGen:5999 case IrInstructionIdAllocaGen:
5898 case IrInstructionIdAwaitSrc:6000 case IrInstructionIdAwaitSrc:
6001 case IrInstructionIdSplatSrc:
5899 zig_unreachable();6002 zig_unreachable();
59006003
5901 case IrInstructionIdDeclVarGen:6004 case IrInstructionIdDeclVarGen:
...@@ -6054,6 +6157,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6054,6 +6157,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6054 return ir_render_spill_begin(g, executable, (IrInstructionSpillBegin *)instruction);6157 return ir_render_spill_begin(g, executable, (IrInstructionSpillBegin *)instruction);
6055 case IrInstructionIdSpillEnd:6158 case IrInstructionIdSpillEnd:
6056 return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction);6159 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);
6057 }6164 }
6058 zig_unreachable();6165 zig_unreachable();
6059}6166}
...@@ -7419,7 +7526,9 @@ static void do_code_gen(CodeGen *g) {...@@ -7419,7 +7526,9 @@ static void do_code_gen(CodeGen *g) {
7419 }7526 }
74207527
7421 char *error = nullptr;7528 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 }
7423}7532}
74247533
7425static void zig_llvm_emit_output(CodeGen *g) {7534static void zig_llvm_emit_output(CodeGen *g) {
...@@ -7744,6 +7853,8 @@ static void define_builtin_fns(CodeGen *g) {...@@ -7744,6 +7853,8 @@ static void define_builtin_fns(CodeGen *g) {
7744 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);7853 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
7745 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int7854 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
7746 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);7855 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
7856 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
7857 create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
7747 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);7858 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
7748 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);7859 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
7749 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);7860 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
src/ir.cpp+499-67
...@@ -717,6 +717,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) {...@@ -717,6 +717,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) {
717 return IrInstructionIdVectorType;717 return IrInstructionIdVectorType;
718}718}
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
720static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {732static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
721 return IrInstructionIdBoolNot;733 return IrInstructionIdBoolNot;
722}734}
...@@ -2277,6 +2289,38 @@ static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode...@@ -2277,6 +2289,38 @@ static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode
2277 return &instruction->base;2289 return &instruction->base;
2278}2290}
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
2280static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {2324static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
2281 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);2325 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
2282 instruction->value = value;2326 instruction->value = value;
...@@ -2333,6 +2377,19 @@ static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *...@@ -2333,6 +2377,19 @@ static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *
2333 return &instruction->base;2377 return &instruction->base;
2334}2378}
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
2336static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type,2393static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type,
2337 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc)2394 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc)
2338{2395{
...@@ -4936,6 +4993,48 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4936,6 +4993,48 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4936 IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);4993 IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);
4937 return ir_lval_wrap(irb, scope, vector_type, lval, result_loc);4994 return ir_lval_wrap(irb, scope, vector_type, lval, result_loc);
4938 }4995 }
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 }
4939 case BuiltinFnIdMemcpy:5038 case BuiltinFnIdMemcpy:
4940 {5039 {
4941 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);5040 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) {...@@ -11000,14 +11099,41 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
11000 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val);11099 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val);
11001}11100}
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
11003static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) {11122static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) {
11004 ZigType *ty = ir_resolve_type(ira, type_value);11123 ZigType *ty = ir_resolve_type(ira, type_value);
11005 if (type_is_invalid(ty))11124 if (type_is_invalid(ty))
11006 return ira->codegen->builtin_types.entry_invalid;11125 return ira->codegen->builtin_types.entry_invalid;
1100711126
11008 if (ty->id != ZigTypeIdInt) {11127 if (ty->id != ZigTypeIdInt) {
11009 ir_add_error(ira, type_value,11128 ErrorMsg *msg = ir_add_error(ira, type_value,
11010 buf_sprintf("expected integer type, found '%s'", buf_ptr(&ty->name)));11129 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 }
11011 return ira->codegen->builtin_types.entry_invalid;11137 return ira->codegen->builtin_types.entry_invalid;
11012 }11138 }
1101311139
...@@ -13092,6 +13218,59 @@ static bool optional_value_is_null(ConstExprValue *val) {...@@ -13092,6 +13218,59 @@ static bool optional_value_is_null(ConstExprValue *val) {
13092 }13218 }
13093}13219}
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
13095// Returns ErrorNotLazy when the value cannot be determined13274// Returns ErrorNotLazy when the value cannot be determined
13096static Error lazy_cmp_zero(AstNode *source_node, ConstExprValue *val, Cmp *result) {13275static Error lazy_cmp_zero(AstNode *source_node, ConstExprValue *val, Cmp *result) {
13097 Error err;13276 Error err;
...@@ -13477,51 +13656,22 @@ never_mind_just_calculate_it_normally:...@@ -13477,51 +13656,22 @@ never_mind_just_calculate_it_normally:
13477 ConstExprValue *op2_val = one_possible_value ? &casted_op2->value : ir_resolve_const(ira, casted_op2, UndefBad);13656 ConstExprValue *op2_val = one_possible_value ? &casted_op2->value : ir_resolve_const(ira, casted_op2, UndefBad);
13478 if (op2_val == nullptr)13657 if (op2_val == nullptr)
13479 return ira->codegen->invalid_instruction;13658 return ira->codegen->invalid_instruction;
1348013659 if (resolved_type->id != ZigTypeIdVector)
13481 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {13660 return ir_evaluate_bin_op_cmp(ira, resolved_type, op1_val, op2_val, bin_op_instruction, op_id, one_possible_value);
13482 if (float_is_nan(op1_val) || float_is_nan(op2_val)) {13661 IrInstruction *result = ir_const(ira, &bin_op_instruction->base,
13483 return ir_const_bool(ira, &bin_op_instruction->base, op_id == IrBinOpCmpNotEq);13662 get_vector_type(ira->codegen, resolved_type->data.vector.len, ira->codegen->builtin_types.entry_bool));
13484 }13663 result->value.data.x_array.data.s_none.elements =
13485 Cmp cmp_result = float_cmp(op1_val, op2_val);13664 create_const_vals(resolved_type->data.vector.len);
13486 bool answer = resolve_cmp_op_id(op_id, cmp_result);13665
13487 return ir_const_bool(ira, &bin_op_instruction->base, answer);13666 expand_undef_array(ira->codegen, &result->value);
13488 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {13667 for (size_t i = 0;i < resolved_type->data.vector.len;i++) {
13489 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);13668 IrInstruction *cur_res = ir_evaluate_bin_op_cmp(ira, resolved_type->data.vector.elem_type,
13490 bool answer = resolve_cmp_op_id(op_id, cmp_result);13669 &op1_val->data.x_array.data.s_none.elements[i],
13491 return ir_const_bool(ira, &bin_op_instruction->base, answer);13670 &op2_val->data.x_array.data.s_none.elements[i],
13492 } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) {13671 bin_op_instruction, op_id, one_possible_value);
13493 if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||13672 copy_const_val(&result->value.data.x_array.data.s_none.elements[i], &cur_res->value, false);
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);
13524 }13673 }
13674 return result;
13525 }13675 }
1352613676
13527 // some comparisons with unsigned numbers can be evaluated13677 // some comparisons with unsigned numbers can be evaluated
...@@ -13564,7 +13714,12 @@ never_mind_just_calculate_it_normally:...@@ -13564,7 +13714,12 @@ never_mind_just_calculate_it_normally:
13564 IrInstruction *result = ir_build_bin_op(&ira->new_irb,13714 IrInstruction *result = ir_build_bin_op(&ira->new_irb,
13565 bin_op_instruction->base.scope, bin_op_instruction->base.source_node,13715 bin_op_instruction->base.scope, bin_op_instruction->base.source_node,
13566 op_id, casted_op1, casted_op2, bin_op_instruction->safety_check_on);13716 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 }
13568 return result;13723 return result;
13569}13724}
1357013725
...@@ -15198,7 +15353,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -15198,7 +15353,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
15198 }15353 }
15199 peer_parent->skipped = true;15354 peer_parent->skipped = true;
15200 return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,15355 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);
15202 }15357 }
1520315358
15204 if (peer_parent->resolved_type == nullptr) {15359 if (peer_parent->resolved_type == nullptr) {
...@@ -22018,20 +22173,251 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr...@@ -22018,20 +22173,251 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr
22018 if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len))22173 if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len))
22019 return ira->codegen->invalid_instruction;22174 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);
22022 if (type_is_invalid(elem_type))22177 if (type_is_invalid(elem_type))
22023 return ira->codegen->invalid_instruction;22178 return ira->codegen->invalid_instruction;
2202422179
22025 if (!is_valid_vector_elem_type(elem_type)) {22180 ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type);
22026 ir_add_error(ira, instruction->elem_type,22181
22027 buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid",22182 return ir_const_type(ira, &instruction->base, vector_type);
22028 buf_ptr(&elem_type->name)));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)));
22029 return ira->codegen->invalid_instruction;22200 return ira->codegen->invalid_instruction;
22030 }22201 }
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);
22035}22421}
2203622422
22037static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {22423static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
...@@ -24970,21 +25356,35 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct...@@ -24970,21 +25356,35 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct
24970}25356}
2497125357
24972static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {25358static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
25359 Error err;
25360
24973 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);25361 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
24974 if (type_is_invalid(int_type))25362 if (type_is_invalid(int_type))
24975 return ira->codegen->invalid_instruction;25363 return ira->codegen->invalid_instruction;
2497625364
24977 IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type);25365 IrInstruction *uncasted_op = instruction->op->child;
24978 if (type_is_invalid(op->value.type))25366 if (type_is_invalid(uncasted_op->value.type))
24979 return ira->codegen->invalid_instruction;25367 return ira->codegen->invalid_instruction;
2498025368
24981 if (int_type->data.integral.bit_count == 0) {25369 uint32_t vector_len; // UINT32_MAX means not a vector
24982 IrInstruction *result = ir_const(ira, &instruction->base, int_type);25370 if (uncasted_op->value.type->id == ZigTypeIdArray &&
24983 bigint_init_unsigned(&result->value.data.x_bigint, 0);25371 is_valid_vector_elem_type(uncasted_op->value.type->data.array.child_type))
24984 return result;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;
24985 }25378 }
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)
24988 return op;25388 return op;
2498925389
24990 if (int_type->data.integral.bit_count % 8 != 0) {25390 if (int_type->data.integral.bit_count % 8 != 0) {
...@@ -24999,20 +25399,44 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction...@@ -24999,20 +25399,44 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction
24999 if (val == nullptr)25399 if (val == nullptr)
25000 return ira->codegen->invalid_instruction;25400 return ira->codegen->invalid_instruction;
25001 if (val->special == ConstValSpecialUndef)25401 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);
25005 size_t buf_size = int_type->data.integral.bit_count / 8;25405 size_t buf_size = int_type->data.integral.bit_count / 8;
25006 uint8_t *buf = allocate_nonzero<uint8_t>(buf_size);25406 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);25407 if (is_vector) {
25008 bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,25408 expand_undef_array(ira->codegen, val);
25009 int_type->data.integral.is_signed);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);
25010 return result;25434 return result;
25011 }25435 }
2501225436
25013 IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,25437 IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,
25014 instruction->base.source_node, nullptr, op);25438 instruction->base.source_node, nullptr, op);
25015 result->value.type = int_type;25439 result->value.type = op_type;
25016 return result;25440 return result;
25017}25441}
2501825442
...@@ -25450,6 +25874,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25450,6 +25874,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25450 case IrInstructionIdTestErrGen:25874 case IrInstructionIdTestErrGen:
25451 case IrInstructionIdFrameSizeGen:25875 case IrInstructionIdFrameSizeGen:
25452 case IrInstructionIdAwaitGen:25876 case IrInstructionIdAwaitGen:
25877 case IrInstructionIdSplatGen:
25453 zig_unreachable();25878 zig_unreachable();
2545425879
25455 case IrInstructionIdReturn:25880 case IrInstructionIdReturn:
...@@ -25578,6 +26003,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25578,6 +26003,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25578 return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);26003 return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
25579 case IrInstructionIdVectorType:26004 case IrInstructionIdVectorType:
25580 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);26005 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);
25581 case IrInstructionIdBoolNot:26010 case IrInstructionIdBoolNot:
25582 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);26011 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
25583 case IrInstructionIdMemset:26012 case IrInstructionIdMemset:
...@@ -25913,6 +26342,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -25913,6 +26342,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {
25913 case IrInstructionIdTruncate:26342 case IrInstructionIdTruncate:
25914 case IrInstructionIdIntType:26343 case IrInstructionIdIntType:
25915 case IrInstructionIdVectorType:26344 case IrInstructionIdVectorType:
26345 case IrInstructionIdShuffleVector:
26346 case IrInstructionIdSplatSrc:
26347 case IrInstructionIdSplatGen:
25916 case IrInstructionIdBoolNot:26348 case IrInstructionIdBoolNot:
25917 case IrInstructionIdSliceSrc:26349 case IrInstructionIdSliceSrc:
25918 case IrInstructionIdMemberCount:26350 case IrInstructionIdMemberCount:
src/ir_print.cpp+41
...@@ -42,6 +42,12 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {...@@ -42,6 +42,12 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {
42 switch (instruction->id) {42 switch (instruction->id) {
43 case IrInstructionIdInvalid:43 case IrInstructionIdInvalid:
44 return "Invalid";44 return "Invalid";
45 case IrInstructionIdShuffleVector:
46 return "Shuffle";
47 case IrInstructionIdSplatSrc:
48 return "SplatSrc";
49 case IrInstructionIdSplatGen:
50 return "SplatGen";
45 case IrInstructionIdDeclVarSrc:51 case IrInstructionIdDeclVarSrc:
46 return "DeclVarSrc";52 return "DeclVarSrc";
47 case IrInstructionIdDeclVarGen:53 case IrInstructionIdDeclVarGen:
...@@ -1208,6 +1214,32 @@ static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruct...@@ -1208,6 +1214,32 @@ static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruct
1208 fprintf(irp->f, ")");1214 fprintf(irp->f, ")");
1209}1215}
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
1211static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {1243static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
1212 fprintf(irp->f, "! ");1244 fprintf(irp->f, "! ");
1213 ir_print_other_instruction(irp, instruction->value);1245 ir_print_other_instruction(irp, instruction->value);
...@@ -2143,6 +2175,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2143,6 +2175,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2143 case IrInstructionIdVectorType:2175 case IrInstructionIdVectorType:
2144 ir_print_vector_type(irp, (IrInstructionVectorType *)instruction);2176 ir_print_vector_type(irp, (IrInstructionVectorType *)instruction);
2145 break;2177 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;
2146 case IrInstructionIdBoolNot:2187 case IrInstructionIdBoolNot:
2147 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);2188 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
2148 break;2189 break;
src/list.hpp+1-1
...@@ -15,7 +15,7 @@ struct ZigList {...@@ -15,7 +15,7 @@ struct ZigList {
15 void deinit() {15 void deinit() {
16 free(items);16 free(items);
17 }17 }
18 void append(T item) {18 void append(const T& item) {
19 ensure_capacity(length + 1);19 ensure_capacity(length + 1);
20 items[length++] = item;20 items[length++] = item;
21 }21 }
src/main.cpp+1-1
...@@ -90,7 +90,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -90,7 +90,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
90 " -mllvm [arg] (unsupported) forward an arg to LLVM's option processing\n"90 " -mllvm [arg] (unsupported) forward an arg to LLVM's option processing\n"
91 " --override-std-dir [arg] override path to Zig standard library\n"91 " --override-std-dir [arg] override path to Zig standard library\n"
92 " --override-lib-dir [arg] override path to Zig lib library\n"92 " --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"
94 "\n"94 "\n"
95 "Link Options:\n"95 "Link Options:\n"
96 " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n"96 " --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 {...@@ -306,6 +306,8 @@ pub fn Channel(comptime T: type) type {
306test "std.event.Channel" {306test "std.event.Channel" {
307 // https://github.com/ziglang/zig/issues/1908307 // https://github.com/ziglang/zig/issues/1908
308 if (builtin.single_threaded) return error.SkipZigTest;308 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
310 var loop: Loop = undefined;312 var loop: Loop = undefined;
311 // TODO make a multi threaded test313 // TODO make a multi threaded test
std/event/future.zig+2
...@@ -85,6 +85,8 @@ pub fn Future(comptime T: type) type {...@@ -85,6 +85,8 @@ pub fn Future(comptime T: type) type {
85test "std.event.Future" {85test "std.event.Future" {
86 // https://github.com/ziglang/zig/issues/190886 // https://github.com/ziglang/zig/issues/1908
87 if (builtin.single_threaded) return error.SkipZigTest;87 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
89 const allocator = std.heap.direct_allocator;91 const allocator = std.heap.direct_allocator;
9092
std/event/lock.zig+2
...@@ -118,6 +118,8 @@ pub const Lock = struct {...@@ -118,6 +118,8 @@ pub const Lock = struct {
118test "std.event.Lock" {118test "std.event.Lock" {
119 // TODO https://github.com/ziglang/zig/issues/1908119 // TODO https://github.com/ziglang/zig/issues/1908
120 if (builtin.single_threaded) return error.SkipZigTest;120 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
122 const allocator = std.heap.direct_allocator;124 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 {...@@ -116,7 +116,7 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {
116 // Otherwise, hash every element.116 // Otherwise, hash every element.
117 // TODO remove the copy to an array once field access is done.117 // TODO remove the copy to an array once field access is done.
118 const array: [info.len]info.child = key;118 const array: [info.len]info.child = key;
119 comptime var i: u32 = 0;119 comptime var i = 0;
120 inline while (i < info.len) : (i += 1) {120 inline while (i < info.len) : (i += 1) {
121 hash(hasher, array[i], strat);121 hash(hasher, array[i], strat);
122 }122 }
...@@ -357,10 +357,13 @@ test "testHash union" {...@@ -357,10 +357,13 @@ test "testHash union" {
357test "testHash vector" {357test "testHash vector" {
358 const a: @Vector(4, u32) = [_]u32{ 1, 2, 3, 4 };358 const a: @Vector(4, u32) = [_]u32{ 1, 2, 3, 4 };
359 const b: @Vector(4, u32) = [_]u32{ 1, 2, 3, 5 };359 const b: @Vector(4, u32) = [_]u32{ 1, 2, 3, 5 };
360 const c: @Vector(4, u31) = [_]u31{ 1, 2, 3, 4 };
361 testing.expect(testHash(a) == testHash(a));360 testing.expect(testHash(a) == testHash(a));
362 testing.expect(testHash(a) != testHash(b));361 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));
364}367}
365368
366test "testHash error union" {369test "testHash error union" {
std/http/headers.zig+1-1
...@@ -299,7 +299,7 @@ pub const Headers = struct {...@@ -299,7 +299,7 @@ pub const Headers = struct {
299 return buf;299 return buf;
300 }300 }
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.
303 ///303 ///
304 /// Useful for HTTP headers that follow RFC-7230 section 3.2.2:304 /// Useful for HTTP headers that follow RFC-7230 section 3.2.2:
305 /// A recipient MAY combine multiple header fields with the same field305 /// 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 {...@@ -269,16 +269,11 @@ nakedcc fn clone() void {
269 \\ bx lr269 \\ bx lr
270 \\270 \\
271 \\1: mov r0,r6271 \\1: mov r0,r6
272 \\ tst r5,#1272 \\ bl 3f
273 \\ bne 1f
274 \\ mov lr,pc
275 \\ mov pc,r5
276 \\2: mov r7,#1273 \\2: mov r7,#1
277 \\ svc 0274 \\ svc 0
278 \\
279 \\1: mov lr,pc
280 \\ bx r5
281 \\ b 2b275 \\ b 2b
276 \\3: bx r5
282 );277 );
283 } else {278 } else {
284 @compileError("Implement clone() for this arch.");279 @compileError("Implement clone() for this arch.");
std/special/start.zig+1-1
...@@ -23,7 +23,7 @@ comptime {...@@ -23,7 +23,7 @@ comptime {
23 } else if (builtin.os == .uefi) {23 } else if (builtin.os == .uefi) {
24 @export("EfiMain", EfiMain, .Strong);24 @export("EfiMain", EfiMain, .Strong);
25 } else {25 } else {
26 @export("_start", _start, .Strong);26 if (!@hasDecl(root, "_start")) @export("_start", _start, .Strong);
27 }27 }
28}28}
2929
std/zig/ast.zig+40-40
...@@ -255,39 +255,39 @@ pub const Error = union(enum) {...@@ -255,39 +255,39 @@ pub const Error = union(enum) {
255 }255 }
256 }256 }
257257
258 pub const InvalidToken = SingleTokenError("Invalid token {}");258 pub const InvalidToken = SingleTokenError("Invalid token '{}'");
259 pub const ExpectedContainerMembers = SingleTokenError("Expected test, comptime, var decl, or container field, found {}");259 pub const ExpectedContainerMembers = SingleTokenError("Expected test, comptime, var decl, or container field, found '{}'");
260 pub const ExpectedStringLiteral = SingleTokenError("Expected string literal, found {}");260 pub const ExpectedStringLiteral = SingleTokenError("Expected string literal, found '{}'");
261 pub const ExpectedIntegerLiteral = SingleTokenError("Expected integer literal, found {}");261 pub const ExpectedIntegerLiteral = SingleTokenError("Expected integer literal, found '{}'");
262 pub const ExpectedIdentifier = SingleTokenError("Expected identifier, found {}");262 pub const ExpectedIdentifier = SingleTokenError("Expected identifier, found '{}'");
263 pub const ExpectedStatement = SingleTokenError("Expected statement, found {}");263 pub const ExpectedStatement = SingleTokenError("Expected statement, found '{}'");
264 pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}");264 pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found '{}'");
265 pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found {}");265 pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{}'");
266 pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, 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 {}");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 {}");268 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{}'");
269 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");269 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found '{}'");
270 pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found {}");270 pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found '{}'");
271 pub const ExpectedLBrace = SingleTokenError("Expected '{{', found {}");271 pub const ExpectedLBrace = SingleTokenError("Expected '{{', found '{}'");
272 pub const ExpectedLabelOrLBrace = SingleTokenError("Expected label or '{{', found {}");272 pub const ExpectedLabelOrLBrace = SingleTokenError("Expected label or '{{', found '{}'");
273 pub const ExpectedColonOrRParen = SingleTokenError("Expected ':' or ')', found {}");273 pub const ExpectedColonOrRParen = SingleTokenError("Expected ':' or ')', found '{}'");
274 pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found {}");274 pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found '{}'");
275 pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found {}");275 pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found '{}'");
276 pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ @tagName(Token.Id.Identifier) ++ ", found {}");276 pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or '" ++ Token.Id.Identifier.symbol() ++ "', found '{}'");
277 pub const ExpectedSliceOrRBracket = SingleTokenError("Expected ']' or '..', found {}");277 pub const ExpectedSliceOrRBracket = SingleTokenError("Expected ']' or '..', found '{}'");
278 pub const ExpectedTypeExpr = SingleTokenError("Expected type expression, found {}");278 pub const ExpectedTypeExpr = SingleTokenError("Expected type expression, found '{}'");
279 pub const ExpectedPrimaryTypeExpr = SingleTokenError("Expected primary type expression, found {}");279 pub const ExpectedPrimaryTypeExpr = SingleTokenError("Expected primary type expression, found '{}'");
280 pub const ExpectedExpr = SingleTokenError("Expected expression, found {}");280 pub const ExpectedExpr = SingleTokenError("Expected expression, found '{}'");
281 pub const ExpectedPrimaryExpr = SingleTokenError("Expected primary expression, found {}");281 pub const ExpectedPrimaryExpr = SingleTokenError("Expected primary expression, found '{}'");
282 pub const ExpectedParamList = SingleTokenError("Expected parameter list, found {}");282 pub const ExpectedParamList = SingleTokenError("Expected parameter list, found '{}'");
283 pub const ExpectedPayload = SingleTokenError("Expected loop payload, found {}");283 pub const ExpectedPayload = SingleTokenError("Expected loop payload, found '{}'");
284 pub const ExpectedBlockOrAssignment = SingleTokenError("Expected block or assignment, found {}");284 pub const ExpectedBlockOrAssignment = SingleTokenError("Expected block or assignment, found '{}'");
285 pub const ExpectedBlockOrExpression = SingleTokenError("Expected block or expression, found {}");285 pub const ExpectedBlockOrExpression = SingleTokenError("Expected block or expression, found '{}'");
286 pub const ExpectedExprOrAssignment = SingleTokenError("Expected expression or assignment, found {}");286 pub const ExpectedExprOrAssignment = SingleTokenError("Expected expression or assignment, found '{}'");
287 pub const ExpectedPrefixExpr = SingleTokenError("Expected prefix expression, found {}");287 pub const ExpectedPrefixExpr = SingleTokenError("Expected prefix expression, found '{}'");
288 pub const ExpectedLoopExpr = SingleTokenError("Expected loop expression, found {}");288 pub const ExpectedLoopExpr = SingleTokenError("Expected loop expression, found '{}'");
289 pub const ExpectedDerefOrUnwrap = SingleTokenError("Expected pointer dereference or optional unwrap, 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 {}");290 pub const ExpectedSuffixOp = SingleTokenError("Expected pointer dereference, optional unwrap, or field access, found '{}'");
291291
292 pub const ExpectedParamType = SimpleError("Expected parameter type");292 pub const ExpectedParamType = SimpleError("Expected parameter type");
293 pub const ExpectedPubItem = SimpleError("Pub must be followed by fn decl, var decl, or container member");293 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) {...@@ -324,11 +324,11 @@ pub const Error = union(enum) {
324 return stream.print("`&&` is invalid. Note that `and` is boolean AND.");324 return stream.print("`&&` is invalid. Note that `and` is boolean AND.");
325 },325 },
326 .Invalid => {326 .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());
328 },328 },
329 else => {329 else => {
330 const token_name = @tagName(found_token.id);330 const token_name = found_token.id.symbol();
331 return stream.print("expected {}, found {}", @tagName(self.expected_id), token_name);331 return stream.print("expected '{}', found '{}'", self.expected_id.symbol(), token_name);
332 },332 },
333 }333 }
334 }334 }
...@@ -339,8 +339,8 @@ pub const Error = union(enum) {...@@ -339,8 +339,8 @@ pub const Error = union(enum) {
339 end_id: Token.Id,339 end_id: Token.Id,
340340
341 pub fn render(self: *const ExpectedCommaOrEnd, tokens: *Tree.TokenList, stream: var) !void {341 pub fn render(self: *const ExpectedCommaOrEnd, tokens: *Tree.TokenList, stream: var) !void {
342 const token_name = @tagName(tokens.at(self.token).id);342 const actual_token = tokens.at(self.token);
343 return stream.print("expected ',' or {}, found {}", @tagName(self.end_id), token_name);343 return stream.print("expected ',' or '{}', found '{}'", self.end_id.symbol(), actual_token.id.symbol());
344 }344 }
345 };345 };
346346
...@@ -351,8 +351,8 @@ pub const Error = union(enum) {...@@ -351,8 +351,8 @@ pub const Error = union(enum) {
351 token: TokenIndex,351 token: TokenIndex,
352352
353 pub fn render(self: *const ThisError, tokens: *Tree.TokenList, stream: var) !void {353 pub fn render(self: *const ThisError, tokens: *Tree.TokenList, stream: var) !void {
354 const token_name = @tagName(tokens.at(self.token).id);354 const actual_token = tokens.at(self.token);
355 return stream.print(msg, token_name);355 return stream.print(msg, actual_token.id.symbol());
356 }356 }
357 };357 };
358 }358 }
std/zig/tokenizer.zig+125
...@@ -196,6 +196,131 @@ pub const Token = struct {...@@ -196,6 +196,131 @@ pub const Token = struct {
196 Keyword_var,196 Keyword_var,
197 Keyword_volatile,197 Keyword_volatile,
198 Keyword_while,198 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 }
199 };324 };
200};325};
201326
test/compile_errors.zig+24-1
...@@ -6484,6 +6484,19 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6484,6 +6484,19 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6484 "tmp.zig:7:23: error: unable to evaluate constant expression",6484 "tmp.zig:7:23: error: unable to evaluate constant expression",
6485 );6485 );
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
6487 cases.addTest(6500 cases.addTest(
6488 "nested vectors",6501 "nested vectors",
6489 \\export fn entry() void {6502 \\export fn entry() void {
...@@ -6491,7 +6504,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6491,7 +6504,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6491 \\ var v: V = undefined;6504 \\ var v: V = undefined;
6492 \\}6505 \\}
6493 ,6506 ,
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",
6495 );6518 );
64966519
6497 cases.add("compileLog of tagged enum doesn't crash the compiler",6520 cases.add("compileLog of tagged enum doesn't crash the compiler",
test/stage1/behavior.zig+1
...@@ -80,6 +80,7 @@ comptime {...@@ -80,6 +80,7 @@ comptime {
80 _ = @import("behavior/pub_enum.zig");80 _ = @import("behavior/pub_enum.zig");
81 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");81 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
82 _ = @import("behavior/reflection.zig");82 _ = @import("behavior/reflection.zig");
83 _ = @import("behavior/shuffle.zig");
83 _ = @import("behavior/sizeof_and_typeof.zig");84 _ = @import("behavior/sizeof_and_typeof.zig");
84 _ = @import("behavior/slice.zig");85 _ = @import("behavior/slice.zig");
85 _ = @import("behavior/slicetobytes.zig");86 _ = @import("behavior/slicetobytes.zig");
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}
test/stage1/behavior/misc.zig+20
...@@ -721,3 +721,23 @@ test "global variable assignment with optional unwrapping with var initialized t...@@ -721,3 +721,23 @@ test "global variable assignment with optional unwrapping with var initialized t
721 };721 };
722 expect(global_foo.* == 1234);722 expect(global_foo.* == 1234);
723}723}
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");...@@ -2,6 +2,18 @@ const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
3const expect = std.testing.expect;3const 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
5test "vector wrap operators" {17test "vector wrap operators" {
6 const S = struct {18 const S = struct {
7 fn doTheTest() void {19 fn doTheTest() void {
...@@ -18,6 +30,23 @@ test "vector wrap operators" {...@@ -18,6 +30,23 @@ test "vector wrap operators" {
18 comptime S.doTheTest();30 comptime S.doTheTest();
19}31}
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
21test "vector int operators" {50test "vector int operators" {
22 const S = struct {51 const S = struct {
23 fn doTheTest() void {52 fn doTheTest() void {
...@@ -80,3 +109,49 @@ test "array to vector" {...@@ -80,3 +109,49 @@ test "array to vector" {
80 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };109 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
81 var vec: @Vector(4, f32) = arr;110 var vec: @Vector(4, f32) = arr;
82}111}
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}