| author | |
| committer | |
| log | 42004f9013ba2d06b457f858e0e269ef4ad23554 |
| tree | ee99dd89c9ce7e7c30a76e7bf0d9f7da7c0c64c7 |
| parent | afe3aae582d5051406832e32fc01374f2a0029b7 |
| parent | a966275e509670e750ef54a37f7202078aa4cf07 |
57 files changed, 2602 insertions(+), 1580 deletions(-)
CMakeLists.txt+8-3| ... | @@ -47,15 +47,20 @@ option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF) | ... | @@ -47,15 +47,20 @@ option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF) |
| 47 | option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead of the embedded LLD" OFF) | 47 | option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead of the embedded LLD" OFF) |
| 48 | 48 | ||
| 49 | find_package(llvm) | 49 | find_package(llvm) |
| 50 | include_directories(${LLVM_INCLUDE_DIRS}) | ||
| 51 | |||
| 52 | find_package(clang) | 50 | find_package(clang) |
| 53 | include_directories(${CLANG_INCLUDE_DIRS}) | ||
| 54 | 51 | ||
| 55 | if(ZIG_FORCE_EXTERNAL_LLD) | 52 | if(ZIG_FORCE_EXTERNAL_LLD) |
| 56 | find_package(lld) | 53 | find_package(lld) |
| 54 | include_directories(${LLVM_INCLUDE_DIRS}) | ||
| 57 | include_directories(${LLD_INCLUDE_DIRS}) | 55 | include_directories(${LLD_INCLUDE_DIRS}) |
| 56 | include_directories(${CLANG_INCLUDE_DIRS}) | ||
| 58 | else() | 57 | else() |
| 58 | # This goes first so that we find embedded LLD instead | ||
| 59 | # of system LLD. | ||
| 60 | include_directories("${CMAKE_SOURCE_DIR}/deps/lld/include") | ||
| 61 | |||
| 62 | include_directories(${LLVM_INCLUDE_DIRS}) | ||
| 63 | include_directories(${CLANG_INCLUDE_DIRS}) | ||
| 59 | set(EMBEDDED_LLD_LIB_SOURCES | 64 | set(EMBEDDED_LLD_LIB_SOURCES |
| 60 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Driver/DarwinLdDriver.cpp" | 65 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Driver/DarwinLdDriver.cpp" |
| 61 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Config/Version.cpp" | 66 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Config/Version.cpp" |
c_headers/avx512fintrin.h+229-395| ... | @@ -4543,37 +4543,6 @@ _mm512_maskz_unpacklo_epi64 (__mmask8 __U, __m512i __A, __m512i __B) | ... | @@ -4543,37 +4543,6 @@ _mm512_maskz_unpacklo_epi64 (__mmask8 __U, __m512i __A, __m512i __B) |
| 4543 | (__v8di)_mm512_setzero_si512()); | 4543 | (__v8di)_mm512_setzero_si512()); |
| 4544 | } | 4544 | } |
| 4545 | 4545 | ||
| 4546 | /* Bit Test */ | ||
| 4547 | |||
| 4548 | static __inline __mmask16 __DEFAULT_FN_ATTRS | ||
| 4549 | _mm512_test_epi32_mask(__m512i __A, __m512i __B) | ||
| 4550 | { | ||
| 4551 | return (__mmask16) __builtin_ia32_ptestmd512 ((__v16si) __A, | ||
| 4552 | (__v16si) __B, | ||
| 4553 | (__mmask16) -1); | ||
| 4554 | } | ||
| 4555 | |||
| 4556 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 4557 | _mm512_mask_test_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) | ||
| 4558 | { | ||
| 4559 | return (__mmask16) __builtin_ia32_ptestmd512 ((__v16si) __A, | ||
| 4560 | (__v16si) __B, __U); | ||
| 4561 | } | ||
| 4562 | |||
| 4563 | static __inline __mmask8 __DEFAULT_FN_ATTRS | ||
| 4564 | _mm512_test_epi64_mask(__m512i __A, __m512i __B) | ||
| 4565 | { | ||
| 4566 | return (__mmask8) __builtin_ia32_ptestmq512 ((__v8di) __A, | ||
| 4567 | (__v8di) __B, | ||
| 4568 | (__mmask8) -1); | ||
| 4569 | } | ||
| 4570 | |||
| 4571 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 4572 | _mm512_mask_test_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) | ||
| 4573 | { | ||
| 4574 | return (__mmask8) __builtin_ia32_ptestmq512 ((__v8di) __A, (__v8di) __B, __U); | ||
| 4575 | } | ||
| 4576 | |||
| 4577 | 4546 | ||
| 4578 | /* SIMD load ops */ | 4547 | /* SIMD load ops */ |
| 4579 | 4548 | ||
| ... | @@ -4844,293 +4813,105 @@ _mm512_knot(__mmask16 __M) | ... | @@ -4844,293 +4813,105 @@ _mm512_knot(__mmask16 __M) |
| 4844 | 4813 | ||
| 4845 | /* Integer compare */ | 4814 | /* Integer compare */ |
| 4846 | 4815 | ||
| 4847 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | 4816 | #define _mm512_cmpeq_epi32_mask(A, B) \ |
| 4848 | _mm512_cmpeq_epi32_mask(__m512i __a, __m512i __b) { | 4817 | _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_EQ) |
| 4849 | return (__mmask16)__builtin_ia32_pcmpeqd512_mask((__v16si)__a, (__v16si)__b, | 4818 | #define _mm512_mask_cmpeq_epi32_mask(k, A, B) \ |
| 4850 | (__mmask16)-1); | 4819 | _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_EQ) |
| 4851 | } | 4820 | #define _mm512_cmpge_epi32_mask(A, B) \ |
| 4852 | 4821 | _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_GE) | |
| 4853 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | 4822 | #define _mm512_mask_cmpge_epi32_mask(k, A, B) \ |
| 4854 | _mm512_mask_cmpeq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | 4823 | _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GE) |
| 4855 | return (__mmask16)__builtin_ia32_pcmpeqd512_mask((__v16si)__a, (__v16si)__b, | 4824 | #define _mm512_cmpgt_epi32_mask(A, B) \ |
| 4856 | __u); | 4825 | _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_GT) |
| 4857 | } | 4826 | #define _mm512_mask_cmpgt_epi32_mask(k, A, B) \ |
| 4858 | 4827 | _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GT) | |
| 4859 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | 4828 | #define _mm512_cmple_epi32_mask(A, B) \ |
| 4860 | _mm512_cmpeq_epu32_mask(__m512i __a, __m512i __b) { | 4829 | _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_LE) |
| 4861 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 0, | 4830 | #define _mm512_mask_cmple_epi32_mask(k, A, B) \ |
| 4862 | (__mmask16)-1); | 4831 | _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LE) |
| 4863 | } | 4832 | #define _mm512_cmplt_epi32_mask(A, B) \ |
| 4864 | 4833 | _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_LT) | |
| 4865 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | 4834 | #define _mm512_mask_cmplt_epi32_mask(k, A, B) \ |
| 4866 | _mm512_mask_cmpeq_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | 4835 | _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LT) |
| 4867 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 0, | 4836 | #define _mm512_cmpneq_epi32_mask(A, B) \ |
| 4868 | __u); | 4837 | _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_NE) |
| 4869 | } | 4838 | #define _mm512_mask_cmpneq_epi32_mask(k, A, B) \ |
| 4870 | 4839 | _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_NE) | |
| 4871 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | 4840 | |
| 4872 | _mm512_mask_cmpeq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | 4841 | #define _mm512_cmpeq_epu32_mask(A, B) \ |
| 4873 | return (__mmask8)__builtin_ia32_pcmpeqq512_mask((__v8di)__a, (__v8di)__b, | 4842 | _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_EQ) |
| 4874 | __u); | 4843 | #define _mm512_mask_cmpeq_epu32_mask(k, A, B) \ |
| 4875 | } | 4844 | _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_EQ) |
| 4876 | 4845 | #define _mm512_cmpge_epu32_mask(A, B) \ | |
| 4877 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | 4846 | _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_GE) |
| 4878 | _mm512_cmpeq_epi64_mask(__m512i __a, __m512i __b) { | 4847 | #define _mm512_mask_cmpge_epu32_mask(k, A, B) \ |
| 4879 | return (__mmask8)__builtin_ia32_pcmpeqq512_mask((__v8di)__a, (__v8di)__b, | 4848 | _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GE) |
| 4880 | (__mmask8)-1); | 4849 | #define _mm512_cmpgt_epu32_mask(A, B) \ |
| 4881 | } | 4850 | _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_GT) |
| 4882 | 4851 | #define _mm512_mask_cmpgt_epu32_mask(k, A, B) \ | |
| 4883 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | 4852 | _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GT) |
| 4884 | _mm512_cmpeq_epu64_mask(__m512i __a, __m512i __b) { | 4853 | #define _mm512_cmple_epu32_mask(A, B) \ |
| 4885 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 0, | 4854 | _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_LE) |
| 4886 | (__mmask8)-1); | 4855 | #define _mm512_mask_cmple_epu32_mask(k, A, B) \ |
| 4887 | } | 4856 | _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LE) |
| 4888 | 4857 | #define _mm512_cmplt_epu32_mask(A, B) \ | |
| 4889 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | 4858 | _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_LT) |
| 4890 | _mm512_mask_cmpeq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | 4859 | #define _mm512_mask_cmplt_epu32_mask(k, A, B) \ |
| 4891 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 0, | 4860 | _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LT) |
| 4892 | __u); | 4861 | #define _mm512_cmpneq_epu32_mask(A, B) \ |
| 4893 | } | 4862 | _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_NE) |
| 4894 | 4863 | #define _mm512_mask_cmpneq_epu32_mask(k, A, B) \ | |
| 4895 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | 4864 | _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_NE) |
| 4896 | _mm512_cmpge_epi32_mask(__m512i __a, __m512i __b) { | 4865 | |
| 4897 | return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 5, | 4866 | #define _mm512_cmpeq_epi64_mask(A, B) \ |
| 4898 | (__mmask16)-1); | 4867 | _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_EQ) |
| 4899 | } | 4868 | #define _mm512_mask_cmpeq_epi64_mask(k, A, B) \ |
| 4900 | 4869 | _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_EQ) | |
| 4901 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | 4870 | #define _mm512_cmpge_epi64_mask(A, B) \ |
| 4902 | _mm512_mask_cmpge_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | 4871 | _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_GE) |
| 4903 | return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 5, | 4872 | #define _mm512_mask_cmpge_epi64_mask(k, A, B) \ |
| 4904 | __u); | 4873 | _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GE) |
| 4905 | } | 4874 | #define _mm512_cmpgt_epi64_mask(A, B) \ |
| 4906 | 4875 | _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_GT) | |
| 4907 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | 4876 | #define _mm512_mask_cmpgt_epi64_mask(k, A, B) \ |
| 4908 | _mm512_cmpge_epu32_mask(__m512i __a, __m512i __b) { | 4877 | _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GT) |
| 4909 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 5, | 4878 | #define _mm512_cmple_epi64_mask(A, B) \ |
| 4910 | (__mmask16)-1); | 4879 | _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_LE) |
| 4911 | } | 4880 | #define _mm512_mask_cmple_epi64_mask(k, A, B) \ |
| 4912 | 4881 | _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LE) | |
| 4913 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | 4882 | #define _mm512_cmplt_epi64_mask(A, B) \ |
| 4914 | _mm512_mask_cmpge_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | 4883 | _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_LT) |
| 4915 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 5, | 4884 | #define _mm512_mask_cmplt_epi64_mask(k, A, B) \ |
| 4916 | __u); | 4885 | _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LT) |
| 4917 | } | 4886 | #define _mm512_cmpneq_epi64_mask(A, B) \ |
| 4918 | 4887 | _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_NE) | |
| 4919 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | 4888 | #define _mm512_mask_cmpneq_epi64_mask(k, A, B) \ |
| 4920 | _mm512_cmpge_epi64_mask(__m512i __a, __m512i __b) { | 4889 | _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_NE) |
| 4921 | return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 5, | 4890 | |
| 4922 | (__mmask8)-1); | 4891 | #define _mm512_cmpeq_epu64_mask(A, B) \ |
| 4923 | } | 4892 | _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_EQ) |
| 4924 | 4893 | #define _mm512_mask_cmpeq_epu64_mask(k, A, B) \ | |
| 4925 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | 4894 | _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_EQ) |
| 4926 | _mm512_mask_cmpge_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | 4895 | #define _mm512_cmpge_epu64_mask(A, B) \ |
| 4927 | return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 5, | 4896 | _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_GE) |
| 4928 | __u); | 4897 | #define _mm512_mask_cmpge_epu64_mask(k, A, B) \ |
| 4929 | } | 4898 | _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GE) |
| 4930 | 4899 | #define _mm512_cmpgt_epu64_mask(A, B) \ | |
| 4931 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | 4900 | _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_GT) |
| 4932 | _mm512_cmpge_epu64_mask(__m512i __a, __m512i __b) { | 4901 | #define _mm512_mask_cmpgt_epu64_mask(k, A, B) \ |
| 4933 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 5, | 4902 | _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GT) |
| 4934 | (__mmask8)-1); | 4903 | #define _mm512_cmple_epu64_mask(A, B) \ |
| 4935 | } | 4904 | _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_LE) |
| 4936 | 4905 | #define _mm512_mask_cmple_epu64_mask(k, A, B) \ | |
| 4937 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | 4906 | _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LE) |
| 4938 | _mm512_mask_cmpge_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | 4907 | #define _mm512_cmplt_epu64_mask(A, B) \ |
| 4939 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 5, | 4908 | _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_LT) |
| 4940 | __u); | 4909 | #define _mm512_mask_cmplt_epu64_mask(k, A, B) \ |
| 4941 | } | 4910 | _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LT) |
| 4942 | 4911 | #define _mm512_cmpneq_epu64_mask(A, B) \ | |
| 4943 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | 4912 | _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_NE) |
| 4944 | _mm512_cmpgt_epi32_mask(__m512i __a, __m512i __b) { | 4913 | #define _mm512_mask_cmpneq_epu64_mask(k, A, B) \ |
| 4945 | return (__mmask16)__builtin_ia32_pcmpgtd512_mask((__v16si)__a, (__v16si)__b, | 4914 | _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_NE) |
| 4946 | (__mmask16)-1); | ||
| 4947 | } | ||
| 4948 | |||
| 4949 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 4950 | _mm512_mask_cmpgt_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | ||
| 4951 | return (__mmask16)__builtin_ia32_pcmpgtd512_mask((__v16si)__a, (__v16si)__b, | ||
| 4952 | __u); | ||
| 4953 | } | ||
| 4954 | |||
| 4955 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 4956 | _mm512_cmpgt_epu32_mask(__m512i __a, __m512i __b) { | ||
| 4957 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 6, | ||
| 4958 | (__mmask16)-1); | ||
| 4959 | } | ||
| 4960 | |||
| 4961 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 4962 | _mm512_mask_cmpgt_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | ||
| 4963 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 6, | ||
| 4964 | __u); | ||
| 4965 | } | ||
| 4966 | |||
| 4967 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 4968 | _mm512_mask_cmpgt_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | ||
| 4969 | return (__mmask8)__builtin_ia32_pcmpgtq512_mask((__v8di)__a, (__v8di)__b, | ||
| 4970 | __u); | ||
| 4971 | } | ||
| 4972 | |||
| 4973 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 4974 | _mm512_cmpgt_epi64_mask(__m512i __a, __m512i __b) { | ||
| 4975 | return (__mmask8)__builtin_ia32_pcmpgtq512_mask((__v8di)__a, (__v8di)__b, | ||
| 4976 | (__mmask8)-1); | ||
| 4977 | } | ||
| 4978 | |||
| 4979 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 4980 | _mm512_cmpgt_epu64_mask(__m512i __a, __m512i __b) { | ||
| 4981 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 6, | ||
| 4982 | (__mmask8)-1); | ||
| 4983 | } | ||
| 4984 | |||
| 4985 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 4986 | _mm512_mask_cmpgt_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | ||
| 4987 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 6, | ||
| 4988 | __u); | ||
| 4989 | } | ||
| 4990 | |||
| 4991 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 4992 | _mm512_cmple_epi32_mask(__m512i __a, __m512i __b) { | ||
| 4993 | return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 2, | ||
| 4994 | (__mmask16)-1); | ||
| 4995 | } | ||
| 4996 | |||
| 4997 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 4998 | _mm512_mask_cmple_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | ||
| 4999 | return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 2, | ||
| 5000 | __u); | ||
| 5001 | } | ||
| 5002 | |||
| 5003 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5004 | _mm512_cmple_epu32_mask(__m512i __a, __m512i __b) { | ||
| 5005 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 2, | ||
| 5006 | (__mmask16)-1); | ||
| 5007 | } | ||
| 5008 | |||
| 5009 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5010 | _mm512_mask_cmple_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | ||
| 5011 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 2, | ||
| 5012 | __u); | ||
| 5013 | } | ||
| 5014 | |||
| 5015 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5016 | _mm512_cmple_epi64_mask(__m512i __a, __m512i __b) { | ||
| 5017 | return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 2, | ||
| 5018 | (__mmask8)-1); | ||
| 5019 | } | ||
| 5020 | |||
| 5021 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5022 | _mm512_mask_cmple_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | ||
| 5023 | return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 2, | ||
| 5024 | __u); | ||
| 5025 | } | ||
| 5026 | |||
| 5027 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5028 | _mm512_cmple_epu64_mask(__m512i __a, __m512i __b) { | ||
| 5029 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 2, | ||
| 5030 | (__mmask8)-1); | ||
| 5031 | } | ||
| 5032 | |||
| 5033 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5034 | _mm512_mask_cmple_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | ||
| 5035 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 2, | ||
| 5036 | __u); | ||
| 5037 | } | ||
| 5038 | |||
| 5039 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5040 | _mm512_cmplt_epi32_mask(__m512i __a, __m512i __b) { | ||
| 5041 | return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 1, | ||
| 5042 | (__mmask16)-1); | ||
| 5043 | } | ||
| 5044 | |||
| 5045 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5046 | _mm512_mask_cmplt_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | ||
| 5047 | return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 1, | ||
| 5048 | __u); | ||
| 5049 | } | ||
| 5050 | |||
| 5051 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5052 | _mm512_cmplt_epu32_mask(__m512i __a, __m512i __b) { | ||
| 5053 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 1, | ||
| 5054 | (__mmask16)-1); | ||
| 5055 | } | ||
| 5056 | |||
| 5057 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5058 | _mm512_mask_cmplt_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | ||
| 5059 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 1, | ||
| 5060 | __u); | ||
| 5061 | } | ||
| 5062 | |||
| 5063 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5064 | _mm512_cmplt_epi64_mask(__m512i __a, __m512i __b) { | ||
| 5065 | return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 1, | ||
| 5066 | (__mmask8)-1); | ||
| 5067 | } | ||
| 5068 | |||
| 5069 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5070 | _mm512_mask_cmplt_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | ||
| 5071 | return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 1, | ||
| 5072 | __u); | ||
| 5073 | } | ||
| 5074 | |||
| 5075 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5076 | _mm512_cmplt_epu64_mask(__m512i __a, __m512i __b) { | ||
| 5077 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 1, | ||
| 5078 | (__mmask8)-1); | ||
| 5079 | } | ||
| 5080 | |||
| 5081 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5082 | _mm512_mask_cmplt_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | ||
| 5083 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 1, | ||
| 5084 | __u); | ||
| 5085 | } | ||
| 5086 | |||
| 5087 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5088 | _mm512_cmpneq_epi32_mask(__m512i __a, __m512i __b) { | ||
| 5089 | return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 4, | ||
| 5090 | (__mmask16)-1); | ||
| 5091 | } | ||
| 5092 | |||
| 5093 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5094 | _mm512_mask_cmpneq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | ||
| 5095 | return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 4, | ||
| 5096 | __u); | ||
| 5097 | } | ||
| 5098 | |||
| 5099 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5100 | _mm512_cmpneq_epu32_mask(__m512i __a, __m512i __b) { | ||
| 5101 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 4, | ||
| 5102 | (__mmask16)-1); | ||
| 5103 | } | ||
| 5104 | |||
| 5105 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 5106 | _mm512_mask_cmpneq_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) { | ||
| 5107 | return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 4, | ||
| 5108 | __u); | ||
| 5109 | } | ||
| 5110 | |||
| 5111 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5112 | _mm512_cmpneq_epi64_mask(__m512i __a, __m512i __b) { | ||
| 5113 | return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 4, | ||
| 5114 | (__mmask8)-1); | ||
| 5115 | } | ||
| 5116 | |||
| 5117 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5118 | _mm512_mask_cmpneq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | ||
| 5119 | return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 4, | ||
| 5120 | __u); | ||
| 5121 | } | ||
| 5122 | |||
| 5123 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5124 | _mm512_cmpneq_epu64_mask(__m512i __a, __m512i __b) { | ||
| 5125 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 4, | ||
| 5126 | (__mmask8)-1); | ||
| 5127 | } | ||
| 5128 | |||
| 5129 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 5130 | _mm512_mask_cmpneq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) { | ||
| 5131 | return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 4, | ||
| 5132 | __u); | ||
| 5133 | } | ||
| 5134 | 4915 | ||
| 5135 | static __inline__ __m512i __DEFAULT_FN_ATTRS | 4916 | static __inline__ __m512i __DEFAULT_FN_ATTRS |
| 5136 | _mm512_cvtepi8_epi32(__m128i __A) | 4917 | _mm512_cvtepi8_epi32(__m128i __A) |
| ... | @@ -6797,35 +6578,6 @@ _mm512_maskz_permutex2var_ps (__mmask16 __U, __m512 __A, __m512i __I, | ... | @@ -6797,35 +6578,6 @@ _mm512_maskz_permutex2var_ps (__mmask16 __U, __m512 __A, __m512i __I, |
| 6797 | (__mmask16) __U); | 6578 | (__mmask16) __U); |
| 6798 | } | 6579 | } |
| 6799 | 6580 | ||
| 6800 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 6801 | _mm512_testn_epi32_mask (__m512i __A, __m512i __B) | ||
| 6802 | { | ||
| 6803 | return (__mmask16) __builtin_ia32_ptestnmd512 ((__v16si) __A, | ||
| 6804 | (__v16si) __B, | ||
| 6805 | (__mmask16) -1); | ||
| 6806 | } | ||
| 6807 | |||
| 6808 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 6809 | _mm512_mask_testn_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) | ||
| 6810 | { | ||
| 6811 | return (__mmask16) __builtin_ia32_ptestnmd512 ((__v16si) __A, | ||
| 6812 | (__v16si) __B, __U); | ||
| 6813 | } | ||
| 6814 | |||
| 6815 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 6816 | _mm512_testn_epi64_mask (__m512i __A, __m512i __B) | ||
| 6817 | { | ||
| 6818 | return (__mmask8) __builtin_ia32_ptestnmq512 ((__v8di) __A, | ||
| 6819 | (__v8di) __B, | ||
| 6820 | (__mmask8) -1); | ||
| 6821 | } | ||
| 6822 | |||
| 6823 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 6824 | _mm512_mask_testn_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) | ||
| 6825 | { | ||
| 6826 | return (__mmask8) __builtin_ia32_ptestnmq512 ((__v8di) __A, | ||
| 6827 | (__v8di) __B, __U); | ||
| 6828 | } | ||
| 6829 | 6581 | ||
| 6830 | #define _mm512_cvtt_roundpd_epu32(A, R) __extension__ ({ \ | 6582 | #define _mm512_cvtt_roundpd_epu32(A, R) __extension__ ({ \ |
| 6831 | (__m256i)__builtin_ia32_cvttpd2udq512_mask((__v8df)(__m512d)(A), \ | 6583 | (__m256i)__builtin_ia32_cvttpd2udq512_mask((__v8df)(__m512d)(A), \ |
| ... | @@ -7194,76 +6946,100 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) | ... | @@ -7194,76 +6946,100 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) |
| 7194 | } | 6946 | } |
| 7195 | 6947 | ||
| 7196 | #define _mm512_shuffle_f32x4(A, B, imm) __extension__ ({ \ | 6948 | #define _mm512_shuffle_f32x4(A, B, imm) __extension__ ({ \ |
| 7197 | (__m512)__builtin_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \ | 6949 | (__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \ |
| 7198 | (__v16sf)(__m512)(B), (int)(imm), \ | 6950 | (__v16sf)(__m512)(B), \ |
| 7199 | (__v16sf)_mm512_undefined_ps(), \ | 6951 | 0 + ((((imm) >> 0) & 0x3) * 4), \ |
| 7200 | (__mmask16)-1); }) | 6952 | 1 + ((((imm) >> 0) & 0x3) * 4), \ |
| 6953 | 2 + ((((imm) >> 0) & 0x3) * 4), \ | ||
| 6954 | 3 + ((((imm) >> 0) & 0x3) * 4), \ | ||
| 6955 | 0 + ((((imm) >> 2) & 0x3) * 4), \ | ||
| 6956 | 1 + ((((imm) >> 2) & 0x3) * 4), \ | ||
| 6957 | 2 + ((((imm) >> 2) & 0x3) * 4), \ | ||
| 6958 | 3 + ((((imm) >> 2) & 0x3) * 4), \ | ||
| 6959 | 16 + ((((imm) >> 4) & 0x3) * 4), \ | ||
| 6960 | 17 + ((((imm) >> 4) & 0x3) * 4), \ | ||
| 6961 | 18 + ((((imm) >> 4) & 0x3) * 4), \ | ||
| 6962 | 19 + ((((imm) >> 4) & 0x3) * 4), \ | ||
| 6963 | 16 + ((((imm) >> 6) & 0x3) * 4), \ | ||
| 6964 | 17 + ((((imm) >> 6) & 0x3) * 4), \ | ||
| 6965 | 18 + ((((imm) >> 6) & 0x3) * 4), \ | ||
| 6966 | 19 + ((((imm) >> 6) & 0x3) * 4)); }) | ||
| 7201 | 6967 | ||
| 7202 | #define _mm512_mask_shuffle_f32x4(W, U, A, B, imm) __extension__ ({ \ | 6968 | #define _mm512_mask_shuffle_f32x4(W, U, A, B, imm) __extension__ ({ \ |
| 7203 | (__m512)__builtin_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \ | 6969 | (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ |
| 7204 | (__v16sf)(__m512)(B), (int)(imm), \ | 6970 | (__v16sf)_mm512_shuffle_f32x4((A), (B), (imm)), \ |
| 7205 | (__v16sf)(__m512)(W), \ | 6971 | (__v16sf)(__m512)(W)); }) |
| 7206 | (__mmask16)(U)); }) | ||
| 7207 | 6972 | ||
| 7208 | #define _mm512_maskz_shuffle_f32x4(U, A, B, imm) __extension__ ({ \ | 6973 | #define _mm512_maskz_shuffle_f32x4(U, A, B, imm) __extension__ ({ \ |
| 7209 | (__m512)__builtin_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \ | 6974 | (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ |
| 7210 | (__v16sf)(__m512)(B), (int)(imm), \ | 6975 | (__v16sf)_mm512_shuffle_f32x4((A), (B), (imm)), \ |
| 7211 | (__v16sf)_mm512_setzero_ps(), \ | 6976 | (__v16sf)_mm512_setzero_ps()); }) |
| 7212 | (__mmask16)(U)); }) | ||
| 7213 | 6977 | ||
| 7214 | #define _mm512_shuffle_f64x2(A, B, imm) __extension__ ({ \ | 6978 | #define _mm512_shuffle_f64x2(A, B, imm) __extension__ ({ \ |
| 7215 | (__m512d)__builtin_ia32_shuf_f64x2_mask((__v8df)(__m512d)(A), \ | 6979 | (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \ |
| 7216 | (__v8df)(__m512d)(B), (int)(imm), \ | 6980 | (__v8df)(__m512d)(B), \ |
| 7217 | (__v8df)_mm512_undefined_pd(), \ | 6981 | 0 + ((((imm) >> 0) & 0x3) * 2), \ |
| 7218 | (__mmask8)-1); }) | 6982 | 1 + ((((imm) >> 0) & 0x3) * 2), \ |
| 6983 | 0 + ((((imm) >> 2) & 0x3) * 2), \ | ||
| 6984 | 1 + ((((imm) >> 2) & 0x3) * 2), \ | ||
| 6985 | 8 + ((((imm) >> 4) & 0x3) * 2), \ | ||
| 6986 | 9 + ((((imm) >> 4) & 0x3) * 2), \ | ||
| 6987 | 8 + ((((imm) >> 6) & 0x3) * 2), \ | ||
| 6988 | 9 + ((((imm) >> 6) & 0x3) * 2)); }) | ||
| 7219 | 6989 | ||
| 7220 | #define _mm512_mask_shuffle_f64x2(W, U, A, B, imm) __extension__ ({ \ | 6990 | #define _mm512_mask_shuffle_f64x2(W, U, A, B, imm) __extension__ ({ \ |
| 7221 | (__m512d)__builtin_ia32_shuf_f64x2_mask((__v8df)(__m512d)(A), \ | 6991 | (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ |
| 7222 | (__v8df)(__m512d)(B), (int)(imm), \ | 6992 | (__v8df)_mm512_shuffle_f64x2((A), (B), (imm)), \ |
| 7223 | (__v8df)(__m512d)(W), \ | 6993 | (__v8df)(__m512d)(W)); }) |
| 7224 | (__mmask8)(U)); }) | ||
| 7225 | 6994 | ||
| 7226 | #define _mm512_maskz_shuffle_f64x2(U, A, B, imm) __extension__ ({ \ | 6995 | #define _mm512_maskz_shuffle_f64x2(U, A, B, imm) __extension__ ({ \ |
| 7227 | (__m512d)__builtin_ia32_shuf_f64x2_mask((__v8df)(__m512d)(A), \ | 6996 | (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ |
| 7228 | (__v8df)(__m512d)(B), (int)(imm), \ | 6997 | (__v8df)_mm512_shuffle_f64x2((A), (B), (imm)), \ |
| 7229 | (__v8df)_mm512_setzero_pd(), \ | 6998 | (__v8df)_mm512_setzero_pd()); }) |
| 7230 | (__mmask8)(U)); }) | ||
| 7231 | 6999 | ||
| 7232 | #define _mm512_shuffle_i32x4(A, B, imm) __extension__ ({ \ | 7000 | #define _mm512_shuffle_i32x4(A, B, imm) __extension__ ({ \ |
| 7233 | (__m512i)__builtin_ia32_shuf_i32x4_mask((__v16si)(__m512i)(A), \ | 7001 | (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \ |
| 7234 | (__v16si)(__m512i)(B), (int)(imm), \ | 7002 | (__v8di)(__m512i)(B), \ |
| 7235 | (__v16si)_mm512_setzero_si512(), \ | 7003 | 0 + ((((imm) >> 0) & 0x3) * 2), \ |
| 7236 | (__mmask16)-1); }) | 7004 | 1 + ((((imm) >> 0) & 0x3) * 2), \ |
| 7005 | 0 + ((((imm) >> 2) & 0x3) * 2), \ | ||
| 7006 | 1 + ((((imm) >> 2) & 0x3) * 2), \ | ||
| 7007 | 8 + ((((imm) >> 4) & 0x3) * 2), \ | ||
| 7008 | 9 + ((((imm) >> 4) & 0x3) * 2), \ | ||
| 7009 | 8 + ((((imm) >> 6) & 0x3) * 2), \ | ||
| 7010 | 9 + ((((imm) >> 6) & 0x3) * 2)); }) | ||
| 7237 | 7011 | ||
| 7238 | #define _mm512_mask_shuffle_i32x4(W, U, A, B, imm) __extension__ ({ \ | 7012 | #define _mm512_mask_shuffle_i32x4(W, U, A, B, imm) __extension__ ({ \ |
| 7239 | (__m512i)__builtin_ia32_shuf_i32x4_mask((__v16si)(__m512i)(A), \ | 7013 | (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ |
| 7240 | (__v16si)(__m512i)(B), (int)(imm), \ | 7014 | (__v16si)_mm512_shuffle_i32x4((A), (B), (imm)), \ |
| 7241 | (__v16si)(__m512i)(W), \ | 7015 | (__v16si)(__m512i)(W)); }) |
| 7242 | (__mmask16)(U)); }) | ||
| 7243 | 7016 | ||
| 7244 | #define _mm512_maskz_shuffle_i32x4(U, A, B, imm) __extension__ ({ \ | 7017 | #define _mm512_maskz_shuffle_i32x4(U, A, B, imm) __extension__ ({ \ |
| 7245 | (__m512i)__builtin_ia32_shuf_i32x4_mask((__v16si)(__m512i)(A), \ | 7018 | (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ |
| 7246 | (__v16si)(__m512i)(B), (int)(imm), \ | 7019 | (__v16si)_mm512_shuffle_i32x4((A), (B), (imm)), \ |
| 7247 | (__v16si)_mm512_setzero_si512(), \ | 7020 | (__v16si)_mm512_setzero_si512()); }) |
| 7248 | (__mmask16)(U)); }) | ||
| 7249 | 7021 | ||
| 7250 | #define _mm512_shuffle_i64x2(A, B, imm) __extension__ ({ \ | 7022 | #define _mm512_shuffle_i64x2(A, B, imm) __extension__ ({ \ |
| 7251 | (__m512i)__builtin_ia32_shuf_i64x2_mask((__v8di)(__m512i)(A), \ | 7023 | (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \ |
| 7252 | (__v8di)(__m512i)(B), (int)(imm), \ | 7024 | (__v8di)(__m512i)(B), \ |
| 7253 | (__v8di)_mm512_setzero_si512(), \ | 7025 | 0 + ((((imm) >> 0) & 0x3) * 2), \ |
| 7254 | (__mmask8)-1); }) | 7026 | 1 + ((((imm) >> 0) & 0x3) * 2), \ |
| 7027 | 0 + ((((imm) >> 2) & 0x3) * 2), \ | ||
| 7028 | 1 + ((((imm) >> 2) & 0x3) * 2), \ | ||
| 7029 | 8 + ((((imm) >> 4) & 0x3) * 2), \ | ||
| 7030 | 9 + ((((imm) >> 4) & 0x3) * 2), \ | ||
| 7031 | 8 + ((((imm) >> 6) & 0x3) * 2), \ | ||
| 7032 | 9 + ((((imm) >> 6) & 0x3) * 2)); }) | ||
| 7255 | 7033 | ||
| 7256 | #define _mm512_mask_shuffle_i64x2(W, U, A, B, imm) __extension__ ({ \ | 7034 | #define _mm512_mask_shuffle_i64x2(W, U, A, B, imm) __extension__ ({ \ |
| 7257 | (__m512i)__builtin_ia32_shuf_i64x2_mask((__v8di)(__m512i)(A), \ | 7035 | (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ |
| 7258 | (__v8di)(__m512i)(B), (int)(imm), \ | 7036 | (__v8di)_mm512_shuffle_i64x2((A), (B), (imm)), \ |
| 7259 | (__v8di)(__m512i)(W), \ | 7037 | (__v8di)(__m512i)(W)); }) |
| 7260 | (__mmask8)(U)); }) | ||
| 7261 | 7038 | ||
| 7262 | #define _mm512_maskz_shuffle_i64x2(U, A, B, imm) __extension__ ({ \ | 7039 | #define _mm512_maskz_shuffle_i64x2(U, A, B, imm) __extension__ ({ \ |
| 7263 | (__m512i)__builtin_ia32_shuf_i64x2_mask((__v8di)(__m512i)(A), \ | 7040 | (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ |
| 7264 | (__v8di)(__m512i)(B), (int)(imm), \ | 7041 | (__v8di)_mm512_shuffle_i64x2((A), (B), (imm)), \ |
| 7265 | (__v8di)_mm512_setzero_si512(), \ | 7042 | (__v8di)_mm512_setzero_si512()); }) |
| 7266 | (__mmask8)(U)); }) | ||
| 7267 | 7043 | ||
| 7268 | #define _mm512_shuffle_pd(A, B, M) __extension__ ({ \ | 7044 | #define _mm512_shuffle_pd(A, B, M) __extension__ ({ \ |
| 7269 | (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \ | 7045 | (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \ |
| ... | @@ -9166,6 +8942,64 @@ _mm512_maskz_compress_epi32 (__mmask16 __U, __m512i __A) | ... | @@ -9166,6 +8942,64 @@ _mm512_maskz_compress_epi32 (__mmask16 __U, __m512i __A) |
| 9166 | (__mmask8)(M), \ | 8942 | (__mmask8)(M), \ |
| 9167 | _MM_FROUND_CUR_DIRECTION); }) | 8943 | _MM_FROUND_CUR_DIRECTION); }) |
| 9168 | 8944 | ||
| 8945 | /* Bit Test */ | ||
| 8946 | |||
| 8947 | static __inline __mmask16 __DEFAULT_FN_ATTRS | ||
| 8948 | _mm512_test_epi32_mask (__m512i __A, __m512i __B) | ||
| 8949 | { | ||
| 8950 | return _mm512_cmpneq_epi32_mask (_mm512_and_epi32(__A, __B), | ||
| 8951 | _mm512_setzero_epi32()); | ||
| 8952 | } | ||
| 8953 | |||
| 8954 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 8955 | _mm512_mask_test_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) | ||
| 8956 | { | ||
| 8957 | return _mm512_mask_cmpneq_epi32_mask (__U, _mm512_and_epi32 (__A, __B), | ||
| 8958 | _mm512_setzero_epi32()); | ||
| 8959 | } | ||
| 8960 | |||
| 8961 | static __inline __mmask8 __DEFAULT_FN_ATTRS | ||
| 8962 | _mm512_test_epi64_mask (__m512i __A, __m512i __B) | ||
| 8963 | { | ||
| 8964 | return _mm512_cmpneq_epi64_mask (_mm512_and_epi32 (__A, __B), | ||
| 8965 | _mm512_setzero_epi32()); | ||
| 8966 | } | ||
| 8967 | |||
| 8968 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 8969 | _mm512_mask_test_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) | ||
| 8970 | { | ||
| 8971 | return _mm512_mask_cmpneq_epi64_mask (__U, _mm512_and_epi32 (__A, __B), | ||
| 8972 | _mm512_setzero_epi32()); | ||
| 8973 | } | ||
| 8974 | |||
| 8975 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 8976 | _mm512_testn_epi32_mask (__m512i __A, __m512i __B) | ||
| 8977 | { | ||
| 8978 | return _mm512_cmpeq_epi32_mask (_mm512_and_epi32 (__A, __B), | ||
| 8979 | _mm512_setzero_epi32()); | ||
| 8980 | } | ||
| 8981 | |||
| 8982 | static __inline__ __mmask16 __DEFAULT_FN_ATTRS | ||
| 8983 | _mm512_mask_testn_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) | ||
| 8984 | { | ||
| 8985 | return _mm512_mask_cmpeq_epi32_mask (__U, _mm512_and_epi32 (__A, __B), | ||
| 8986 | _mm512_setzero_epi32()); | ||
| 8987 | } | ||
| 8988 | |||
| 8989 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 8990 | _mm512_testn_epi64_mask (__m512i __A, __m512i __B) | ||
| 8991 | { | ||
| 8992 | return _mm512_cmpeq_epi64_mask (_mm512_and_epi32 (__A, __B), | ||
| 8993 | _mm512_setzero_epi32()); | ||
| 8994 | } | ||
| 8995 | |||
| 8996 | static __inline__ __mmask8 __DEFAULT_FN_ATTRS | ||
| 8997 | _mm512_mask_testn_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) | ||
| 8998 | { | ||
| 8999 | return _mm512_mask_cmpeq_epi64_mask (__U, _mm512_and_epi32 (__A, __B), | ||
| 9000 | _mm512_setzero_epi32()); | ||
| 9001 | } | ||
| 9002 | |||
| 9169 | static __inline__ __m512 __DEFAULT_FN_ATTRS | 9003 | static __inline__ __m512 __DEFAULT_FN_ATTRS |
| 9170 | _mm512_movehdup_ps (__m512 __A) | 9004 | _mm512_movehdup_ps (__m512 __A) |
| 9171 | { | 9005 | { |
deps/lld-prebuilt/lld/Config/Version.inc+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | #define LLD_VERSION 5.0.0 | 1 | #define LLD_VERSION 5.0.1 |
| 2 | #define LLD_VERSION_STRING "5.0.0" | 2 | #define LLD_VERSION_STRING "5.0.1" |
| 3 | #define LLD_VERSION_MAJOR 5 | 3 | #define LLD_VERSION_MAJOR 5 |
| 4 | #define LLD_VERSION_MINOR 0 | 4 | #define LLD_VERSION_MINOR 0 |
| 5 | #define LLD_REVISION_STRING "" | 5 | #define LLD_REVISION_STRING "" |
deps/lld/COFF/Config.h+1| ... | @@ -157,6 +157,7 @@ struct Configuration { | ... | @@ -157,6 +157,7 @@ struct Configuration { |
| 157 | uint32_t MinorImageVersion = 0; | 157 | uint32_t MinorImageVersion = 0; |
| 158 | uint32_t MajorOSVersion = 6; | 158 | uint32_t MajorOSVersion = 6; |
| 159 | uint32_t MinorOSVersion = 0; | 159 | uint32_t MinorOSVersion = 0; |
| 160 | bool CanExitEarly = false; | ||
| 160 | bool DynamicBase = true; | 161 | bool DynamicBase = true; |
| 161 | bool NxCompat = true; | 162 | bool NxCompat = true; |
| 162 | bool AllowIsolation = true; | 163 | bool AllowIsolation = true; |
deps/lld/COFF/Driver.cpp+8-2| ... | @@ -52,15 +52,21 @@ BumpPtrAllocator BAlloc; | ... | @@ -52,15 +52,21 @@ BumpPtrAllocator BAlloc; |
| 52 | StringSaver Saver{BAlloc}; | 52 | StringSaver Saver{BAlloc}; |
| 53 | std::vector<SpecificAllocBase *> SpecificAllocBase::Instances; | 53 | std::vector<SpecificAllocBase *> SpecificAllocBase::Instances; |
| 54 | 54 | ||
| 55 | bool link(ArrayRef<const char *> Args, raw_ostream &Diag) { | 55 | bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) { |
| 56 | ErrorCount = 0; | 56 | ErrorCount = 0; |
| 57 | ErrorOS = &Diag; | 57 | ErrorOS = &Diag; |
| 58 | Config = make<Configuration>(); | 58 | Config = make<Configuration>(); |
| 59 | Config->Argv = {Args.begin(), Args.end()}; | 59 | Config->Argv = {Args.begin(), Args.end()}; |
| 60 | Config->ColorDiagnostics = | 60 | Config->ColorDiagnostics = |
| 61 | (ErrorOS == &llvm::errs() && Process::StandardErrHasColors()); | 61 | (ErrorOS == &llvm::errs() && Process::StandardErrHasColors()); |
| 62 | Config->CanExitEarly = CanExitEarly; | ||
| 62 | Driver = make<LinkerDriver>(); | 63 | Driver = make<LinkerDriver>(); |
| 63 | Driver->link(Args); | 64 | Driver->link(Args); |
| 65 | |||
| 66 | // Call exit() if we can to avoid calling destructors. | ||
| 67 | if (CanExitEarly) | ||
| 68 | exitLld(ErrorCount ? 1 : 0); | ||
| 69 | |||
| 64 | freeArena(); | 70 | freeArena(); |
| 65 | return !ErrorCount; | 71 | return !ErrorCount; |
| 66 | } | 72 | } |
| ... | @@ -1123,7 +1129,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1123,7 +1129,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1123 | // This is useful because MSVC link.exe can generate complete PDBs. | 1129 | // This is useful because MSVC link.exe can generate complete PDBs. |
| 1124 | if (Args.hasArg(OPT_msvclto)) { | 1130 | if (Args.hasArg(OPT_msvclto)) { |
| 1125 | invokeMSVC(Args); | 1131 | invokeMSVC(Args); |
| 1126 | exit(0); | 1132 | return; |
| 1127 | } | 1133 | } |
| 1128 | 1134 | ||
| 1129 | // Do LTO by compiling bitcode input files to a set of native COFF files then | 1135 | // Do LTO by compiling bitcode input files to a set of native COFF files then |
deps/lld/COFF/Error.cpp+3-2| ... | @@ -32,7 +32,7 @@ namespace coff { | ... | @@ -32,7 +32,7 @@ namespace coff { |
| 32 | uint64_t ErrorCount; | 32 | uint64_t ErrorCount; |
| 33 | raw_ostream *ErrorOS; | 33 | raw_ostream *ErrorOS; |
| 34 | 34 | ||
| 35 | static LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) { | 35 | LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) { |
| 36 | // Dealloc/destroy ManagedStatic variables before calling | 36 | // Dealloc/destroy ManagedStatic variables before calling |
| 37 | // _exit(). In a non-LTO build, this is a nop. In an LTO | 37 | // _exit(). In a non-LTO build, this is a nop. In an LTO |
| 38 | // build allows us to get the output of -time-passes. | 38 | // build allows us to get the output of -time-passes. |
| ... | @@ -78,7 +78,8 @@ void error(const Twine &Msg) { | ... | @@ -78,7 +78,8 @@ void error(const Twine &Msg) { |
| 78 | print("error: ", raw_ostream::RED); | 78 | print("error: ", raw_ostream::RED); |
| 79 | *ErrorOS << "too many errors emitted, stopping now" | 79 | *ErrorOS << "too many errors emitted, stopping now" |
| 80 | << " (use /ERRORLIMIT:0 to see all errors)\n"; | 80 | << " (use /ERRORLIMIT:0 to see all errors)\n"; |
| 81 | exitLld(1); | 81 | if (Config->CanExitEarly) |
| 82 | exitLld(1); | ||
| 82 | } | 83 | } |
| 83 | 84 | ||
| 84 | ++ErrorCount; | 85 | ++ErrorCount; |
deps/lld/COFF/Error.h+2| ... | @@ -27,6 +27,8 @@ LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); | ... | @@ -27,6 +27,8 @@ LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); |
| 27 | LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix); | 27 | LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix); |
| 28 | LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix); | 28 | LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix); |
| 29 | 29 | ||
| 30 | LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); | ||
| 31 | |||
| 30 | template <class T> T check(ErrorOr<T> V, const Twine &Prefix) { | 32 | template <class T> T check(ErrorOr<T> V, const Twine &Prefix) { |
| 31 | if (auto EC = V.getError()) | 33 | if (auto EC = V.getError()) |
| 32 | fatal(EC, Prefix); | 34 | fatal(EC, Prefix); |
deps/lld/ELF/SyntheticSections.cpp+9-3| ... | @@ -427,10 +427,11 @@ CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Piece, | ... | @@ -427,10 +427,11 @@ CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Piece, |
| 427 | &Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]); | 427 | &Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]); |
| 428 | 428 | ||
| 429 | // Search for an existing CIE by CIE contents/relocation target pair. | 429 | // Search for an existing CIE by CIE contents/relocation target pair. |
| 430 | CieRecord *Cie = &CieMap[{Piece.data(), Personality}]; | 430 | CieRecord *&Cie = CieMap[{Piece.data(), Personality}]; |
| 431 | 431 | ||
| 432 | // If not found, create a new one. | 432 | // If not found, create a new one. |
| 433 | if (Cie->Piece == nullptr) { | 433 | if (!Cie) { |
| 434 | Cie = make<CieRecord>(); | ||
| 434 | Cie->Piece = &Piece; | 435 | Cie->Piece = &Piece; |
| 435 | Cies.push_back(Cie); | 436 | Cies.push_back(Cie); |
| 436 | } | 437 | } |
| ... | @@ -522,9 +523,14 @@ template <class ELFT> | ... | @@ -522,9 +523,14 @@ template <class ELFT> |
| 522 | static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) { | 523 | static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) { |
| 523 | memcpy(Buf, D.data(), D.size()); | 524 | memcpy(Buf, D.data(), D.size()); |
| 524 | 525 | ||
| 526 | size_t Aligned = alignTo(D.size(), sizeof(typename ELFT::uint)); | ||
| 527 | |||
| 528 | // Zero-clear trailing padding if it exists. | ||
| 529 | memset(Buf + D.size(), 0, Aligned - D.size()); | ||
| 530 | |||
| 525 | // Fix the size field. -4 since size does not include the size field itself. | 531 | // Fix the size field. -4 since size does not include the size field itself. |
| 526 | const endianness E = ELFT::TargetEndianness; | 532 | const endianness E = ELFT::TargetEndianness; |
| 527 | write32<E>(Buf, alignTo(D.size(), sizeof(typename ELFT::uint)) - 4); | 533 | write32<E>(Buf, Aligned - 4); |
| 528 | } | 534 | } |
| 529 | 535 | ||
| 530 | template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() { | 536 | template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() { |
deps/lld/ELF/SyntheticSections.h+2-1| ... | @@ -103,7 +103,8 @@ private: | ... | @@ -103,7 +103,8 @@ private: |
| 103 | std::vector<CieRecord *> Cies; | 103 | std::vector<CieRecord *> Cies; |
| 104 | 104 | ||
| 105 | // CIE records are uniquified by their contents and personality functions. | 105 | // CIE records are uniquified by their contents and personality functions. |
| 106 | llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord> CieMap; | 106 | llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord *> |
| 107 | CieMap; | ||
| 107 | }; | 108 | }; |
| 108 | 109 | ||
| 109 | class GotSection : public SyntheticSection { | 110 | class GotSection : public SyntheticSection { |
deps/lld/include/lld/Driver/Driver.h+1-1| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | 15 | ||
| 16 | namespace lld { | 16 | namespace lld { |
| 17 | namespace coff { | 17 | namespace coff { |
| 18 | bool link(llvm::ArrayRef<const char *> Args, | 18 | bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly, |
| 19 | llvm::raw_ostream &Diag = llvm::errs()); | 19 | llvm::raw_ostream &Diag = llvm::errs()); |
| 20 | } | 20 | } |
| 21 | 21 |
deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp-1| ... | @@ -621,7 +621,6 @@ void ArchHandler_x86_64::applyFixupFinal( | ... | @@ -621,7 +621,6 @@ void ArchHandler_x86_64::applyFixupFinal( |
| 621 | // Fall into llvm_unreachable(). | 621 | // Fall into llvm_unreachable(). |
| 622 | break; | 622 | break; |
| 623 | } | 623 | } |
| 624 | return; | ||
| 625 | } | 624 | } |
| 626 | 625 | ||
| 627 | void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, | 626 | void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, |
deps/lld/test/ELF/eh-frame-padding-no-rosegment.s created+64| ... | @@ -0,0 +1,64 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | |||
| 3 | .cfi_startproc | ||
| 4 | .cfi_personality 0x1b, bar | ||
| 5 | .cfi_endproc | ||
| 6 | |||
| 7 | .global bar | ||
| 8 | .hidden bar | ||
| 9 | bar: | ||
| 10 | |||
| 11 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 12 | |||
| 13 | // Check the size of the CIE (0x18 + 4) and FDE (0x10 + 4) | ||
| 14 | // RUN: llvm-readobj -s -section-data %t.o | FileCheck --check-prefix=OBJ %s | ||
| 15 | |||
| 16 | // OBJ: Name: .eh_frame | ||
| 17 | // OBJ-NEXT: Type: | ||
| 18 | // OBJ-NEXT: Flags [ | ||
| 19 | // OBJ-NEXT: SHF_ALLOC | ||
| 20 | // OBJ-NEXT: ] | ||
| 21 | // OBJ-NEXT: Address: | ||
| 22 | // OBJ-NEXT: Offset: | ||
| 23 | // OBJ-NEXT: Size: | ||
| 24 | // OBJ-NEXT: Link: | ||
| 25 | // OBJ-NEXT: Info: | ||
| 26 | // OBJ-NEXT: AddressAlignment: | ||
| 27 | // OBJ-NEXT: EntrySize: | ||
| 28 | // OBJ-NEXT: SectionData ( | ||
| 29 | // OBJ-NEXT: 0000: 18000000 00000000 017A5052 00017810 | ||
| 30 | // OBJ-NEXT: 0010: 061B0000 00001B0C 07089001 10000000 | ||
| 31 | // OBJ-NEXT: 0020: 20000000 00000000 00000000 00000000 | ||
| 32 | // OBJ-NEXT: ) | ||
| 33 | |||
| 34 | // RUN: ld.lld %t.o -no-rosegment -o %t -shared | ||
| 35 | |||
| 36 | // Check that .eh_frame is in the same segment as .text | ||
| 37 | // RUN: llvm-readobj -l --elf-output-style=GNU %t | FileCheck --check-prefix=PHDR %s | ||
| 38 | |||
| 39 | // PHDR: Segment Sections | ||
| 40 | // PHDR: .text | ||
| 41 | // PHDR-SAME: .eh_frame | ||
| 42 | |||
| 43 | // Check that the CIE and FDE are padded with 0x00 and not 0xCC when the | ||
| 44 | // .eh_frame section is placed in the executable segment | ||
| 45 | // RUN: llvm-readobj -s -section-data %t | FileCheck %s | ||
| 46 | |||
| 47 | // CHECK: Name: .eh_frame | ||
| 48 | // CHECK-NEXT: Type: | ||
| 49 | // CHECK-NEXT: Flags | ||
| 50 | // CHECK-NEXT: SHF_ALLOC | ||
| 51 | // CHECK-NEXT: ] | ||
| 52 | // CHECK-NEXT: Address: | ||
| 53 | // CHECK-NEXT: Offset: | ||
| 54 | // CHECK-NEXT: Size: | ||
| 55 | // CHECK-NEXT: Link: | ||
| 56 | // CHECK-NEXT: Info: | ||
| 57 | // CHECK-NEXT: AddressAlignment: | ||
| 58 | // CHECK-NEXT: EntrySize: | ||
| 59 | // CHECK-NEXT: SectionData ( | ||
| 60 | // CHECK-NEXT: 0000: 1C000000 00000000 017A5052 00017810 | ||
| 61 | // CHECK-NEXT: 0010: 061BBEFF FFFF1B0C 07089001 00000000 | ||
| 62 | // CHECK-NEXT: 0020: 14000000 24000000 A8FFFFFF 00000000 | ||
| 63 | // CHECK-NEXT: 0030: 00000000 00000000 | ||
| 64 | // CHECK-NEXT: ) | ||
deps/lld/tools/lld/lld.cpp+1-1| ... | @@ -103,7 +103,7 @@ int main(int Argc, const char **Argv) { | ... | @@ -103,7 +103,7 @@ int main(int Argc, const char **Argv) { |
| 103 | case Gnu: | 103 | case Gnu: |
| 104 | return !elf::link(Args, true); | 104 | return !elf::link(Args, true); |
| 105 | case WinLink: | 105 | case WinLink: |
| 106 | return !coff::link(Args); | 106 | return !coff::link(Args, true); |
| 107 | case Darwin: | 107 | case Darwin: |
| 108 | return !mach_o::link(Args); | 108 | return !mach_o::link(Args); |
| 109 | default: | 109 | default: |
doc/langref.html.in+177-53| ... | @@ -136,7 +136,8 @@ | ... | @@ -136,7 +136,8 @@ |
| 136 | <li><a href="#builtin-divFloor">@divFloor</a></li> | 136 | <li><a href="#builtin-divFloor">@divFloor</a></li> |
| 137 | <li><a href="#builtin-divTrunc">@divTrunc</a></li> | 137 | <li><a href="#builtin-divTrunc">@divTrunc</a></li> |
| 138 | <li><a href="#builtin-embedFile">@embedFile</a></li> | 138 | <li><a href="#builtin-embedFile">@embedFile</a></li> |
| 139 | <li><a href="#builtin-enumTagName">@enumTagName</a></li> | 139 | <li><a href="#builtin-tagName">@tagName</a></li> |
| 140 | <li><a href="#builtin-EnumTagType">@EnumTagType</a></li> | ||
| 140 | <li><a href="#builtin-errorName">@errorName</a></li> | 141 | <li><a href="#builtin-errorName">@errorName</a></li> |
| 141 | <li><a href="#builtin-fence">@fence</a></li> | 142 | <li><a href="#builtin-fence">@fence</a></li> |
| 142 | <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li> | 143 | <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li> |
| ... | @@ -2095,30 +2096,38 @@ const Type = enum { | ... | @@ -2095,30 +2096,38 @@ const Type = enum { |
| 2095 | NotOk, | 2096 | NotOk, |
| 2096 | }; | 2097 | }; |
| 2097 | 2098 | ||
| 2098 | // Enums are sum types, and can hold more complex data of different types. | ||
| 2099 | const ComplexType = enum { | ||
| 2100 | Ok: u8, | ||
| 2101 | NotOk: void, | ||
| 2102 | }; | ||
| 2103 | |||
| 2104 | // Declare a specific instance of the enum variant. | 2099 | // Declare a specific instance of the enum variant. |
| 2105 | const c = ComplexType.Ok { 0 }; | 2100 | const c = Type.Ok; |
| 2106 | 2101 | ||
| 2107 | // The ordinal value of a simple enum with no data members can be | 2102 | // If you want access to the ordinal value of an enum, you |
| 2108 | // retrieved by a simple cast. | 2103 | // can specify the tag type. |
| 2109 | // The value starts from 0, counting up for each member. | 2104 | const Value = enum(u2) { |
| 2110 | const Value = enum { | ||
| 2111 | Zero, | 2105 | Zero, |
| 2112 | One, | 2106 | One, |
| 2113 | Two, | 2107 | Two, |
| 2114 | }; | 2108 | }; |
| 2109 | |||
| 2110 | // Now you can cast between u2 and Value. | ||
| 2111 | // The ordinal value starts from 0, counting up for each member. | ||
| 2115 | test "enum ordinal value" { | 2112 | test "enum ordinal value" { |
| 2116 | assert(usize(Value.Zero) == 0); | 2113 | assert(u2(Value.Zero) == 0); |
| 2117 | assert(usize(Value.One) == 1); | 2114 | assert(u2(Value.One) == 1); |
| 2118 | assert(usize(Value.Two) == 2); | 2115 | assert(u2(Value.Two) == 2); |
| 2116 | } | ||
| 2117 | |||
| 2118 | // You can override the ordinal value for an enum. | ||
| 2119 | const Value2 = enum(u32) { | ||
| 2120 | Hundred = 100, | ||
| 2121 | Thousand = 1000, | ||
| 2122 | Million = 1000000, | ||
| 2123 | }; | ||
| 2124 | test "set enum ordinal value" { | ||
| 2125 | assert(u32(Value2.Hundred) == 100); | ||
| 2126 | assert(u32(Value2.Thousand) == 1000); | ||
| 2127 | assert(u32(Value2.Million) == 1000000); | ||
| 2119 | } | 2128 | } |
| 2120 | 2129 | ||
| 2121 | // Enums can have methods, the same as structs. | 2130 | // Enums can have methods, the same as structs and unions. |
| 2122 | // Enum methods are not special, they are only namespaced | 2131 | // Enum methods are not special, they are only namespaced |
| 2123 | // functions that you can call with dot syntax. | 2132 | // functions that you can call with dot syntax. |
| 2124 | const Suit = enum { | 2133 | const Suit = enum { |
| ... | @@ -2127,26 +2136,120 @@ const Suit = enum { | ... | @@ -2127,26 +2136,120 @@ const Suit = enum { |
| 2127 | Diamonds, | 2136 | Diamonds, |
| 2128 | Hearts, | 2137 | Hearts, |
| 2129 | 2138 | ||
| 2130 | pub fn ordinal(self: &amp;const Suit) -&gt; u8 { | 2139 | pub fn isClubs(self: Suit) -&gt; bool { |
| 2131 | u8(*self) | 2140 | return self == Suit.Clubs; |
| 2132 | } | 2141 | } |
| 2133 | }; | 2142 | }; |
| 2134 | test "enum method" { | 2143 | test "enum method" { |
| 2135 | const p = Suit.Spades; | 2144 | const p = Suit.Spades; |
| 2136 | assert(p.ordinal() == 1); | 2145 | assert(!p.isClubs()); |
| 2137 | } | 2146 | } |
| 2138 | 2147 | ||
| 2139 | // An enum variant of different types can be switched upon. | 2148 | // An enum variant of different types can be switched upon. |
| 2140 | // The associated data can be retrieved using `|...|` syntax. | ||
| 2141 | // | ||
| 2142 | // A void type is not required on a tag-only member. | ||
| 2143 | const Foo = enum { | 2149 | const Foo = enum { |
| 2150 | String, | ||
| 2151 | Number, | ||
| 2152 | None, | ||
| 2153 | }; | ||
| 2154 | test "enum variant switch" { | ||
| 2155 | const p = Foo.Number; | ||
| 2156 | const what_is_it = switch (p) { | ||
| 2157 | Foo.String =&gt; "this is a string", | ||
| 2158 | Foo.Number =&gt; "this is a number", | ||
| 2159 | Foo.None =&gt; "this is a none", | ||
| 2160 | }; | ||
| 2161 | assert(mem.eql(u8, what_is_it, "this is a number")); | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | // @TagType can be used to access the integer tag type of an enum. | ||
| 2165 | const Small = enum { | ||
| 2166 | One, | ||
| 2167 | Two, | ||
| 2168 | Three, | ||
| 2169 | Four, | ||
| 2170 | }; | ||
| 2171 | test "@TagType" { | ||
| 2172 | assert(@TagType(Small) == u2); | ||
| 2173 | } | ||
| 2174 | |||
| 2175 | // @memberCount tells how many fields an enum has: | ||
| 2176 | test "@memberCount" { | ||
| 2177 | assert(@memberCount(Small) == 4); | ||
| 2178 | } | ||
| 2179 | |||
| 2180 | // @memberName tells the name of a field in an enum: | ||
| 2181 | test "@memberName" { | ||
| 2182 | assert(mem.eql(u8, @memberName(Small, 1), "Two")); | ||
| 2183 | } | ||
| 2184 | |||
| 2185 | // @tagName gives a []const u8 representation of an enum value: | ||
| 2186 | test "@tagName" { | ||
| 2187 | assert(mem.eql(u8, @tagName(Small.Three), "Three")); | ||
| 2188 | }</code></pre> | ||
| 2189 | <p>TODO extern enum</p> | ||
| 2190 | <p>TODO packed enum</p> | ||
| 2191 | <pre><code class="sh">$ zig test enum.zig | ||
| 2192 | Test 1/8 enum ordinal value...OK | ||
| 2193 | Test 2/8 set enum ordinal value...OK | ||
| 2194 | Test 3/8 enum method...OK | ||
| 2195 | Test 4/8 enum variant switch...OK | ||
| 2196 | Test 5/8 @TagType...OK | ||
| 2197 | Test 6/8 @memberCount...OK | ||
| 2198 | Test 7/8 @memberName...OK | ||
| 2199 | Test 8/8 @tagName...OK</code></pre> | ||
| 2200 | <p>See also:</p> | ||
| 2201 | <ul> | ||
| 2202 | <li><a href="#builtin-memberName">@memberName</a></li> | ||
| 2203 | <li><a href="#builtin-memberCount">@memberCount</a></li> | ||
| 2204 | <li><a href="#builtin-tagName">@tagName</a></li> | ||
| 2205 | </ul> | ||
| 2206 | <h2 id="union">union</h2> | ||
| 2207 | <pre><code class="zig">const assert = @import("std").debug.assert; | ||
| 2208 | const mem = @import("std").mem; | ||
| 2209 | |||
| 2210 | // A union has only 1 active field at a time. | ||
| 2211 | const Payload = union { | ||
| 2212 | Int: i64, | ||
| 2213 | Float: f64, | ||
| 2214 | Bool: bool, | ||
| 2215 | }; | ||
| 2216 | test "simple union" { | ||
| 2217 | var payload = Payload {.Int = 1234}; | ||
| 2218 | // payload.Float = 12.34; // ERROR! field not active | ||
| 2219 | assert(payload.Int == 1234); | ||
| 2220 | // You can activate another field by assigning the entire union. | ||
| 2221 | payload = Payload {.Float = 12.34}; | ||
| 2222 | assert(payload.Float == 12.34); | ||
| 2223 | } | ||
| 2224 | |||
| 2225 | // Unions can be given an enum tag type: | ||
| 2226 | const ComplexTypeTag = enum { Ok, NotOk }; | ||
| 2227 | const ComplexType = union(ComplexTypeTag) { | ||
| 2228 | Ok: u8, | ||
| 2229 | NotOk: void, | ||
| 2230 | }; | ||
| 2231 | |||
| 2232 | // Declare a specific instance of the union variant. | ||
| 2233 | test "declare union value" { | ||
| 2234 | const c = ComplexType { .Ok = 0 }; | ||
| 2235 | assert(ComplexTypeTag(c) == ComplexTypeTag.Ok); | ||
| 2236 | } | ||
| 2237 | |||
| 2238 | // @TagType can be used to access the enum tag type of a union. | ||
| 2239 | test "@TagType" { | ||
| 2240 | assert(@TagType(ComplexType) == ComplexTypeTag); | ||
| 2241 | } | ||
| 2242 | |||
| 2243 | // Unions can be made to infer the enum tag type. | ||
| 2244 | const Foo = union(enum) { | ||
| 2144 | String: []const u8, | 2245 | String: []const u8, |
| 2145 | Number: u64, | 2246 | Number: u64, |
| 2247 | |||
| 2248 | // void can be omitted when inferring enum tag type. | ||
| 2146 | None, | 2249 | None, |
| 2147 | }; | 2250 | }; |
| 2148 | test "enum variant switch" { | 2251 | test "union variant switch" { |
| 2149 | const p = Foo.Number { 54 }; | 2252 | const p = Foo { .Number = 54 }; |
| 2150 | const what_is_it = switch (p) { | 2253 | const what_is_it = switch (p) { |
| 2151 | // Capture by reference | 2254 | // Capture by reference |
| 2152 | Foo.String =&gt; |*x| { | 2255 | Foo.String =&gt; |*x| { |
| ... | @@ -2155,6 +2258,7 @@ test "enum variant switch" { | ... | @@ -2155,6 +2258,7 @@ test "enum variant switch" { |
| 2155 | 2258 | ||
| 2156 | // Capture by value | 2259 | // Capture by value |
| 2157 | Foo.Number =&gt; |x| { | 2260 | Foo.Number =&gt; |x| { |
| 2261 | assert(x == 54); | ||
| 2158 | "this is a number" | 2262 | "this is a number" |
| 2159 | }, | 2263 | }, |
| 2160 | 2264 | ||
| ... | @@ -2162,37 +2266,50 @@ test "enum variant switch" { | ... | @@ -2162,37 +2266,50 @@ test "enum variant switch" { |
| 2162 | "this is a none" | 2266 | "this is a none" |
| 2163 | } | 2267 | } |
| 2164 | }; | 2268 | }; |
| 2269 | assert(mem.eql(u8, what_is_it, "this is a number")); | ||
| 2165 | } | 2270 | } |
| 2166 | 2271 | ||
| 2167 | // The @enumTagName and @memberCount builtin functions can be used to | 2272 | // TODO union methods |
| 2168 | // the string representation and number of members respectively. | 2273 | |
| 2169 | const BuiltinType = enum { | 2274 | |
| 2170 | A: f32, | 2275 | const Small = union { |
| 2171 | B: u32, | 2276 | A: i32, |
| 2172 | C, | 2277 | B: bool, |
| 2278 | C: u8, | ||
| 2173 | }; | 2279 | }; |
| 2174 | 2280 | ||
| 2175 | test "enum builtins" { | 2281 | // @memberCount tells how many fields a union has: |
| 2176 | assert(mem.eql(u8, @enumTagName(BuiltinType.A { 0 }), "A")); | 2282 | test "@memberCount" { |
| 2177 | assert(mem.eql(u8, @enumTagName(BuiltinType.C), "C")); | 2283 | assert(@memberCount(Small) == 3); |
| 2178 | assert(@memberCount(BuiltinType) == 3); | 2284 | } |
| 2285 | |||
| 2286 | // @memberName tells the name of a field in an enum: | ||
| 2287 | test "@memberName" { | ||
| 2288 | assert(mem.eql(u8, @memberName(Small, 1), "B")); | ||
| 2289 | } | ||
| 2290 | |||
| 2291 | // @tagName gives a []const u8 representation of an enum value, | ||
| 2292 | // but only if the union has an enum tag type. | ||
| 2293 | const Small2 = union(enum) { | ||
| 2294 | A: i32, | ||
| 2295 | B: bool, | ||
| 2296 | C: u8, | ||
| 2297 | }; | ||
| 2298 | test "@tagName" { | ||
| 2299 | assert(mem.eql(u8, @tagName(Small2.C), "C")); | ||
| 2179 | }</code></pre> | 2300 | }</code></pre> |
| 2180 | <pre><code class="sh">$ zig test enum.zig | 2301 | <pre><code class="sh">$ zig test union.zig |
| 2181 | Test 1/4 enum ordinal value...OK | 2302 | Test 1/7 simple union...OK |
| 2182 | Test 2/4 enum method...OK | 2303 | Test 2/7 declare union value...OK |
| 2183 | Test 3/4 enum variant switch...OK | 2304 | Test 3/7 @TagType...OK |
| 2184 | Test 4/4 enum builtins...OK</code></pre> | 2305 | Test 4/7 union variant switch...OK |
| 2185 | <p> | 2306 | Test 5/7 @memberCount...OK |
| 2186 | Enums are generated as a struct with a tag field and union field. Zig | 2307 | Test 6/7 @memberName...OK |
| 2308 | Test 7/7 @tagName...OK</code></pre> | ||
| 2309 | <p> | ||
| 2310 | Unions with an enum tag are generated as a struct with a tag field and union field. Zig | ||
| 2187 | sorts the order of the tag and union field by the largest alignment. | 2311 | sorts the order of the tag and union field by the largest alignment. |
| 2188 | </p> | 2312 | </p> |
| 2189 | <p>See also:</p> | ||
| 2190 | <ul> | ||
| 2191 | <li><a href="#builtin-enumTagName">@enumTagName</a></li> | ||
| 2192 | <li><a href="#builtin-memberCount">@memberCount</a></li> | ||
| 2193 | </ul> | ||
| 2194 | <h2 id="union">union</h2> | ||
| 2195 | <p>TODO union documentation</p> | ||
| 2196 | <h2 id="switch">switch</h2> | 2313 | <h2 id="switch">switch</h2> |
| 2197 | <pre><code class="zig">const assert = @import("std").debug.assert; | 2314 | <pre><code class="zig">const assert = @import("std").debug.assert; |
| 2198 | const builtin = @import("builtin"); | 2315 | const builtin = @import("builtin"); |
| ... | @@ -4251,10 +4368,15 @@ test.zig:6:2: error: found compile log statement | ... | @@ -4251,10 +4368,15 @@ test.zig:6:2: error: found compile log statement |
| 4251 | <ul> | 4368 | <ul> |
| 4252 | <li><a href="#builtin-import">@import</a></li> | 4369 | <li><a href="#builtin-import">@import</a></li> |
| 4253 | </ul> | 4370 | </ul> |
| 4254 | <h3 id="builtin-enumTagName">@enumTagName</h3> | 4371 | <h3 id="builtin-tagName">@tagName</h3> |
| 4255 | <pre><code class="zig">@enumTagName(value: var) -&gt; []const u8</code></pre> | 4372 | <pre><code class="zig">@tagName(value: var) -&gt; []const u8</code></pre> |
| 4373 | <p> | ||
| 4374 | Converts an enum value or union value to a slice of bytes representing the name. | ||
| 4375 | </p> | ||
| 4376 | <h3 id="builtin-EnumTagType">@EnumTagType</h3> | ||
| 4377 | <pre><code class="zig">@EnumTagType(T: type) -&gt; type</code></pre> | ||
| 4256 | <p> | 4378 | <p> |
| 4257 | Converts an enum tag name to a slice of bytes. | 4379 | Returns the integer type that is used to store the enumeration value. |
| 4258 | </p> | 4380 | </p> |
| 4259 | <h3 id="builtin-errorName">@errorName</h3> | 4381 | <h3 id="builtin-errorName">@errorName</h3> |
| 4260 | <pre><code class="zig">@errorName(err: error) -&gt; []u8</code></pre> | 4382 | <pre><code class="zig">@errorName(err: error) -&gt; []u8</code></pre> |
| ... | @@ -5703,7 +5825,7 @@ VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" Typ | ... | @@ -5703,7 +5825,7 @@ VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" Typ |
| 5703 | 5825 | ||
| 5704 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) | 5826 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) |
| 5705 | 5827 | ||
| 5706 | ContainerField = Symbol option(":" Expression) "," | 5828 | ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression "," |
| 5707 | 5829 | ||
| 5708 | UseDecl = "use" Expression ";" | 5830 | UseDecl = "use" Expression ";" |
| 5709 | 5831 | ||
| ... | @@ -5837,7 +5959,9 @@ GroupedExpression = "(" Expression ")" | ... | @@ -5837,7 +5959,9 @@ GroupedExpression = "(" Expression ")" |
| 5837 | 5959 | ||
| 5838 | KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable" | 5960 | KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable" |
| 5839 | 5961 | ||
| 5840 | ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"</code></pre> | 5962 | ContainerDecl = option("extern" | "packed") |
| 5963 | ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression))) | ||
| 5964 | "{" many(ContainerMember) "}"</code></pre> | ||
| 5841 | <h2 id="zen">Zen</h2> | 5965 | <h2 id="zen">Zen</h2> |
| 5842 | <ul> | 5966 | <ul> |
| 5843 | <li>Communicate intent precisely.</li> | 5967 | <li>Communicate intent precisely.</li> |
example/guess_number/main.zig+2-1| ... | @@ -1,3 +1,4 @@ | ... | @@ -1,3 +1,4 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 1 | const std = @import("std"); | 2 | const std = @import("std"); |
| 2 | const io = std.io; | 3 | const io = std.io; |
| 3 | const fmt = std.fmt; | 4 | const fmt = std.fmt; |
| ... | @@ -15,7 +16,7 @@ pub fn main() -> %void { | ... | @@ -15,7 +16,7 @@ pub fn main() -> %void { |
| 15 | 16 | ||
| 16 | var seed_bytes: [@sizeOf(usize)]u8 = undefined; | 17 | var seed_bytes: [@sizeOf(usize)]u8 = undefined; |
| 17 | %%os.getRandomBytes(seed_bytes[0..]); | 18 | %%os.getRandomBytes(seed_bytes[0..]); |
| 18 | const seed = std.mem.readInt(seed_bytes, usize, true); | 19 | const seed = std.mem.readInt(seed_bytes, usize, builtin.Endian.Big); |
| 19 | var rand = Rand.init(seed); | 20 | var rand = Rand.init(seed); |
| 20 | 21 | ||
| 21 | const answer = rand.range(u8, 0, 100) + 1; | 22 | const answer = rand.range(u8, 0, 100) + 1; |
src/all_types.hpp+23-54| ... | @@ -97,18 +97,13 @@ struct ConstParent { | ... | @@ -97,18 +97,13 @@ struct ConstParent { |
| 97 | } data; | 97 | } data; |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | struct ConstEnumValue { | ||
| 101 | uint64_t tag; | ||
| 102 | ConstExprValue *payload; | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct ConstStructValue { | 100 | struct ConstStructValue { |
| 106 | ConstExprValue *fields; | 101 | ConstExprValue *fields; |
| 107 | ConstParent parent; | 102 | ConstParent parent; |
| 108 | }; | 103 | }; |
| 109 | 104 | ||
| 110 | struct ConstUnionValue { | 105 | struct ConstUnionValue { |
| 111 | uint64_t tag; | 106 | BigInt tag; |
| 112 | ConstExprValue *payload; | 107 | ConstExprValue *payload; |
| 113 | ConstParent parent; | 108 | ConstParent parent; |
| 114 | }; | 109 | }; |
| ... | @@ -249,7 +244,7 @@ struct ConstExprValue { | ... | @@ -249,7 +244,7 @@ struct ConstExprValue { |
| 249 | ConstExprValue *x_maybe; | 244 | ConstExprValue *x_maybe; |
| 250 | ConstErrValue x_err_union; | 245 | ConstErrValue x_err_union; |
| 251 | ErrorTableEntry *x_pure_err; | 246 | ErrorTableEntry *x_pure_err; |
| 252 | ConstEnumValue x_enum; | 247 | BigInt x_enum_tag; |
| 253 | ConstStructValue x_struct; | 248 | ConstStructValue x_struct; |
| 254 | ConstUnionValue x_union; | 249 | ConstUnionValue x_union; |
| 255 | ConstArrayValue x_array; | 250 | ConstArrayValue x_array; |
| ... | @@ -345,15 +340,14 @@ struct TldCompTime { | ... | @@ -345,15 +340,14 @@ struct TldCompTime { |
| 345 | 340 | ||
| 346 | struct TypeEnumField { | 341 | struct TypeEnumField { |
| 347 | Buf *name; | 342 | Buf *name; |
| 348 | TypeTableEntry *type_entry; | 343 | BigInt value; |
| 349 | uint32_t value; | 344 | uint32_t decl_index; |
| 350 | uint32_t gen_index; | ||
| 351 | }; | 345 | }; |
| 352 | 346 | ||
| 353 | struct TypeUnionField { | 347 | struct TypeUnionField { |
| 354 | Buf *name; | 348 | Buf *name; |
| 349 | TypeEnumField *enum_field; | ||
| 355 | TypeTableEntry *type_entry; | 350 | TypeTableEntry *type_entry; |
| 356 | uint32_t value; | ||
| 357 | uint32_t gen_index; | 351 | uint32_t gen_index; |
| 358 | }; | 352 | }; |
| 359 | 353 | ||
| ... | @@ -773,13 +767,15 @@ struct AstNodeContainerDecl { | ... | @@ -773,13 +767,15 @@ struct AstNodeContainerDecl { |
| 773 | ZigList<AstNode *> fields; | 767 | ZigList<AstNode *> fields; |
| 774 | ZigList<AstNode *> decls; | 768 | ZigList<AstNode *> decls; |
| 775 | ContainerLayout layout; | 769 | ContainerLayout layout; |
| 776 | AstNode *init_arg_expr; // enum(T) or struct(endianness) | 770 | AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T)) |
| 771 | bool auto_enum; // union(enum) | ||
| 777 | }; | 772 | }; |
| 778 | 773 | ||
| 779 | struct AstNodeStructField { | 774 | struct AstNodeStructField { |
| 780 | VisibMod visib_mod; | 775 | VisibMod visib_mod; |
| 781 | Buf *name; | 776 | Buf *name; |
| 782 | AstNode *type; | 777 | AstNode *type; |
| 778 | AstNode *value; | ||
| 783 | }; | 779 | }; |
| 784 | 780 | ||
| 785 | struct AstNodeStringLiteral { | 781 | struct AstNodeStringLiteral { |
| ... | @@ -1009,12 +1005,9 @@ struct TypeTableEntryEnum { | ... | @@ -1009,12 +1005,9 @@ struct TypeTableEntryEnum { |
| 1009 | AstNode *decl_node; | 1005 | AstNode *decl_node; |
| 1010 | ContainerLayout layout; | 1006 | ContainerLayout layout; |
| 1011 | uint32_t src_field_count; | 1007 | uint32_t src_field_count; |
| 1012 | // number of fields in the union. 0 if enum with no payload | ||
| 1013 | uint32_t gen_field_count; | ||
| 1014 | TypeEnumField *fields; | 1008 | TypeEnumField *fields; |
| 1015 | bool is_invalid; // true if any fields are invalid | 1009 | bool is_invalid; // true if any fields are invalid |
| 1016 | TypeTableEntry *tag_type; | 1010 | TypeTableEntry *tag_int_type; |
| 1017 | LLVMTypeRef union_type_ref; | ||
| 1018 | 1011 | ||
| 1019 | ScopeDecls *decls_scope; | 1012 | ScopeDecls *decls_scope; |
| 1020 | 1013 | ||
| ... | @@ -1026,18 +1019,7 @@ struct TypeTableEntryEnum { | ... | @@ -1026,18 +1019,7 @@ struct TypeTableEntryEnum { |
| 1026 | 1019 | ||
| 1027 | bool zero_bits_loop_flag; | 1020 | bool zero_bits_loop_flag; |
| 1028 | bool zero_bits_known; | 1021 | bool zero_bits_known; |
| 1029 | uint32_t abi_alignment; // also figured out with zero_bits pass | ||
| 1030 | |||
| 1031 | size_t gen_union_index; | ||
| 1032 | size_t gen_tag_index; | ||
| 1033 | |||
| 1034 | uint32_t union_size_bytes; | ||
| 1035 | TypeTableEntry *most_aligned_union_member; | ||
| 1036 | }; | ||
| 1037 | 1022 | ||
| 1038 | struct TypeTableEntryEnumTag { | ||
| 1039 | TypeTableEntry *enum_type; | ||
| 1040 | TypeTableEntry *int_type; | ||
| 1041 | bool generate_name_table; | 1023 | bool generate_name_table; |
| 1042 | LLVMValueRef name_table; | 1024 | LLVMValueRef name_table; |
| 1043 | }; | 1025 | }; |
| ... | @@ -1052,7 +1034,7 @@ struct TypeTableEntryUnion { | ... | @@ -1052,7 +1034,7 @@ struct TypeTableEntryUnion { |
| 1052 | uint32_t gen_field_count; | 1034 | uint32_t gen_field_count; |
| 1053 | TypeUnionField *fields; | 1035 | TypeUnionField *fields; |
| 1054 | bool is_invalid; // true if any fields are invalid | 1036 | bool is_invalid; // true if any fields are invalid |
| 1055 | TypeTableEntry *tag_type; | 1037 | TypeTableEntry *tag_type; // always an enum or null |
| 1056 | LLVMTypeRef union_type_ref; | 1038 | LLVMTypeRef union_type_ref; |
| 1057 | 1039 | ||
| 1058 | ScopeDecls *decls_scope; | 1040 | ScopeDecls *decls_scope; |
| ... | @@ -1117,7 +1099,6 @@ enum TypeTableEntryId { | ... | @@ -1117,7 +1099,6 @@ enum TypeTableEntryId { |
| 1117 | TypeTableEntryIdErrorUnion, | 1099 | TypeTableEntryIdErrorUnion, |
| 1118 | TypeTableEntryIdPureError, | 1100 | TypeTableEntryIdPureError, |
| 1119 | TypeTableEntryIdEnum, | 1101 | TypeTableEntryIdEnum, |
| 1120 | TypeTableEntryIdEnumTag, | ||
| 1121 | TypeTableEntryIdUnion, | 1102 | TypeTableEntryIdUnion, |
| 1122 | TypeTableEntryIdFn, | 1103 | TypeTableEntryIdFn, |
| 1123 | TypeTableEntryIdNamespace, | 1104 | TypeTableEntryIdNamespace, |
| ... | @@ -1146,7 +1127,6 @@ struct TypeTableEntry { | ... | @@ -1146,7 +1127,6 @@ struct TypeTableEntry { |
| 1146 | TypeTableEntryMaybe maybe; | 1127 | TypeTableEntryMaybe maybe; |
| 1147 | TypeTableEntryError error; | 1128 | TypeTableEntryError error; |
| 1148 | TypeTableEntryEnum enumeration; | 1129 | TypeTableEntryEnum enumeration; |
| 1149 | TypeTableEntryEnumTag enum_tag; | ||
| 1150 | TypeTableEntryUnion unionation; | 1130 | TypeTableEntryUnion unionation; |
| 1151 | TypeTableEntryFn fn; | 1131 | TypeTableEntryFn fn; |
| 1152 | TypeTableEntryBoundFn bound_fn; | 1132 | TypeTableEntryBoundFn bound_fn; |
| ... | @@ -1285,7 +1265,8 @@ enum BuiltinFnId { | ... | @@ -1285,7 +1265,8 @@ enum BuiltinFnId { |
| 1285 | BuiltinFnIdBitCast, | 1265 | BuiltinFnIdBitCast, |
| 1286 | BuiltinFnIdIntToPtr, | 1266 | BuiltinFnIdIntToPtr, |
| 1287 | BuiltinFnIdPtrToInt, | 1267 | BuiltinFnIdPtrToInt, |
| 1288 | BuiltinFnIdEnumTagName, | 1268 | BuiltinFnIdTagName, |
| 1269 | BuiltinFnIdTagType, | ||
| 1289 | BuiltinFnIdFieldParentPtr, | 1270 | BuiltinFnIdFieldParentPtr, |
| 1290 | BuiltinFnIdOffsetOf, | 1271 | BuiltinFnIdOffsetOf, |
| 1291 | BuiltinFnIdInlineCall, | 1272 | BuiltinFnIdInlineCall, |
| ... | @@ -1829,7 +1810,6 @@ enum IrInstructionId { | ... | @@ -1829,7 +1810,6 @@ enum IrInstructionId { |
| 1829 | IrInstructionIdStorePtr, | 1810 | IrInstructionIdStorePtr, |
| 1830 | IrInstructionIdFieldPtr, | 1811 | IrInstructionIdFieldPtr, |
| 1831 | IrInstructionIdStructFieldPtr, | 1812 | IrInstructionIdStructFieldPtr, |
| 1832 | IrInstructionIdEnumFieldPtr, | ||
| 1833 | IrInstructionIdUnionFieldPtr, | 1813 | IrInstructionIdUnionFieldPtr, |
| 1834 | IrInstructionIdElemPtr, | 1814 | IrInstructionIdElemPtr, |
| 1835 | IrInstructionIdVarPtr, | 1815 | IrInstructionIdVarPtr, |
| ... | @@ -1854,7 +1834,7 @@ enum IrInstructionId { | ... | @@ -1854,7 +1834,7 @@ enum IrInstructionId { |
| 1854 | IrInstructionIdTestNonNull, | 1834 | IrInstructionIdTestNonNull, |
| 1855 | IrInstructionIdUnwrapMaybe, | 1835 | IrInstructionIdUnwrapMaybe, |
| 1856 | IrInstructionIdMaybeWrap, | 1836 | IrInstructionIdMaybeWrap, |
| 1857 | IrInstructionIdEnumTag, | 1837 | IrInstructionIdUnionTag, |
| 1858 | IrInstructionIdClz, | 1838 | IrInstructionIdClz, |
| 1859 | IrInstructionIdCtz, | 1839 | IrInstructionIdCtz, |
| 1860 | IrInstructionIdImport, | 1840 | IrInstructionIdImport, |
| ... | @@ -1893,7 +1873,6 @@ enum IrInstructionId { | ... | @@ -1893,7 +1873,6 @@ enum IrInstructionId { |
| 1893 | IrInstructionIdErrWrapPayload, | 1873 | IrInstructionIdErrWrapPayload, |
| 1894 | IrInstructionIdFnProto, | 1874 | IrInstructionIdFnProto, |
| 1895 | IrInstructionIdTestComptime, | 1875 | IrInstructionIdTestComptime, |
| 1896 | IrInstructionIdInitEnum, | ||
| 1897 | IrInstructionIdPtrCast, | 1876 | IrInstructionIdPtrCast, |
| 1898 | IrInstructionIdBitCast, | 1877 | IrInstructionIdBitCast, |
| 1899 | IrInstructionIdWidenOrShorten, | 1878 | IrInstructionIdWidenOrShorten, |
| ... | @@ -1910,7 +1889,8 @@ enum IrInstructionId { | ... | @@ -1910,7 +1889,8 @@ enum IrInstructionId { |
| 1910 | IrInstructionIdSetGlobalLinkage, | 1889 | IrInstructionIdSetGlobalLinkage, |
| 1911 | IrInstructionIdDeclRef, | 1890 | IrInstructionIdDeclRef, |
| 1912 | IrInstructionIdPanic, | 1891 | IrInstructionIdPanic, |
| 1913 | IrInstructionIdEnumTagName, | 1892 | IrInstructionIdTagName, |
| 1893 | IrInstructionIdTagType, | ||
| 1914 | IrInstructionIdFieldParentPtr, | 1894 | IrInstructionIdFieldParentPtr, |
| 1915 | IrInstructionIdOffsetOf, | 1895 | IrInstructionIdOffsetOf, |
| 1916 | IrInstructionIdTypeId, | 1896 | IrInstructionIdTypeId, |
| ... | @@ -2088,14 +2068,6 @@ struct IrInstructionStructFieldPtr { | ... | @@ -2088,14 +2068,6 @@ struct IrInstructionStructFieldPtr { |
| 2088 | bool is_const; | 2068 | bool is_const; |
| 2089 | }; | 2069 | }; |
| 2090 | 2070 | ||
| 2091 | struct IrInstructionEnumFieldPtr { | ||
| 2092 | IrInstruction base; | ||
| 2093 | |||
| 2094 | IrInstruction *enum_ptr; | ||
| 2095 | TypeEnumField *field; | ||
| 2096 | bool is_const; | ||
| 2097 | }; | ||
| 2098 | |||
| 2099 | struct IrInstructionUnionFieldPtr { | 2071 | struct IrInstructionUnionFieldPtr { |
| 2100 | IrInstruction base; | 2072 | IrInstruction base; |
| 2101 | 2073 | ||
| ... | @@ -2299,7 +2271,7 @@ struct IrInstructionClz { | ... | @@ -2299,7 +2271,7 @@ struct IrInstructionClz { |
| 2299 | IrInstruction *value; | 2271 | IrInstruction *value; |
| 2300 | }; | 2272 | }; |
| 2301 | 2273 | ||
| 2302 | struct IrInstructionEnumTag { | 2274 | struct IrInstructionUnionTag { |
| 2303 | IrInstruction base; | 2275 | IrInstruction base; |
| 2304 | 2276 | ||
| 2305 | IrInstruction *value; | 2277 | IrInstruction *value; |
| ... | @@ -2569,15 +2541,6 @@ struct IrInstructionTestComptime { | ... | @@ -2569,15 +2541,6 @@ struct IrInstructionTestComptime { |
| 2569 | IrInstruction *value; | 2541 | IrInstruction *value; |
| 2570 | }; | 2542 | }; |
| 2571 | 2543 | ||
| 2572 | struct IrInstructionInitEnum { | ||
| 2573 | IrInstruction base; | ||
| 2574 | |||
| 2575 | TypeTableEntry *enum_type; | ||
| 2576 | TypeEnumField *field; | ||
| 2577 | IrInstruction *init_value; | ||
| 2578 | LLVMValueRef tmp_ptr; | ||
| 2579 | }; | ||
| 2580 | |||
| 2581 | struct IrInstructionPtrCast { | 2544 | struct IrInstructionPtrCast { |
| 2582 | IrInstruction base; | 2545 | IrInstruction base; |
| 2583 | 2546 | ||
| ... | @@ -2689,7 +2652,13 @@ struct IrInstructionPanic { | ... | @@ -2689,7 +2652,13 @@ struct IrInstructionPanic { |
| 2689 | IrInstruction *msg; | 2652 | IrInstruction *msg; |
| 2690 | }; | 2653 | }; |
| 2691 | 2654 | ||
| 2692 | struct IrInstructionEnumTagName { | 2655 | struct IrInstructionTagName { |
| 2656 | IrInstruction base; | ||
| 2657 | |||
| 2658 | IrInstruction *target; | ||
| 2659 | }; | ||
| 2660 | |||
| 2661 | struct IrInstructionTagType { | ||
| 2693 | IrInstruction base; | 2662 | IrInstruction base; |
| 2694 | 2663 | ||
| 2695 | IrInstruction *target; | 2664 | IrInstruction *target; |
src/analyze.cpp+501-317| ... | @@ -223,7 +223,6 @@ bool type_is_complete(TypeTableEntry *type_entry) { | ... | @@ -223,7 +223,6 @@ bool type_is_complete(TypeTableEntry *type_entry) { |
| 223 | case TypeTableEntryIdNamespace: | 223 | case TypeTableEntryIdNamespace: |
| 224 | case TypeTableEntryIdBlock: | 224 | case TypeTableEntryIdBlock: |
| 225 | case TypeTableEntryIdBoundFn: | 225 | case TypeTableEntryIdBoundFn: |
| 226 | case TypeTableEntryIdEnumTag: | ||
| 227 | case TypeTableEntryIdArgTuple: | 226 | case TypeTableEntryIdArgTuple: |
| 228 | return true; | 227 | return true; |
| 229 | } | 228 | } |
| ... | @@ -260,7 +259,6 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) { | ... | @@ -260,7 +259,6 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) { |
| 260 | case TypeTableEntryIdNamespace: | 259 | case TypeTableEntryIdNamespace: |
| 261 | case TypeTableEntryIdBlock: | 260 | case TypeTableEntryIdBlock: |
| 262 | case TypeTableEntryIdBoundFn: | 261 | case TypeTableEntryIdBoundFn: |
| 263 | case TypeTableEntryIdEnumTag: | ||
| 264 | case TypeTableEntryIdArgTuple: | 262 | case TypeTableEntryIdArgTuple: |
| 265 | case TypeTableEntryIdOpaque: | 263 | case TypeTableEntryIdOpaque: |
| 266 | return true; | 264 | return true; |
| ... | @@ -1175,7 +1173,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1175,7 +1173,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1175 | case TypeTableEntryIdEnum: | 1173 | case TypeTableEntryIdEnum: |
| 1176 | case TypeTableEntryIdUnion: | 1174 | case TypeTableEntryIdUnion: |
| 1177 | case TypeTableEntryIdFn: | 1175 | case TypeTableEntryIdFn: |
| 1178 | case TypeTableEntryIdEnumTag: | ||
| 1179 | ensure_complete_type(g, type_entry); | 1176 | ensure_complete_type(g, type_entry); |
| 1180 | if (fn_type_id.cc == CallingConventionUnspecified && !type_is_copyable(g, type_entry)) { | 1177 | if (fn_type_id.cc == CallingConventionUnspecified && !type_is_copyable(g, type_entry)) { |
| 1181 | add_node_error(g, param_node->data.param_decl.type, | 1178 | add_node_error(g, param_node->data.param_decl.type, |
| ... | @@ -1239,7 +1236,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1239,7 +1236,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1239 | case TypeTableEntryIdEnum: | 1236 | case TypeTableEntryIdEnum: |
| 1240 | case TypeTableEntryIdUnion: | 1237 | case TypeTableEntryIdUnion: |
| 1241 | case TypeTableEntryIdFn: | 1238 | case TypeTableEntryIdFn: |
| 1242 | case TypeTableEntryIdEnumTag: | ||
| 1243 | break; | 1239 | break; |
| 1244 | } | 1240 | } |
| 1245 | 1241 | ||
| ... | @@ -1263,22 +1259,6 @@ bool type_is_invalid(TypeTableEntry *type_entry) { | ... | @@ -1263,22 +1259,6 @@ bool type_is_invalid(TypeTableEntry *type_entry) { |
| 1263 | } | 1259 | } |
| 1264 | 1260 | ||
| 1265 | 1261 | ||
| 1266 | TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type) { | ||
| 1267 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnumTag); | ||
| 1268 | |||
| 1269 | buf_resize(&entry->name, 0); | ||
| 1270 | buf_appendf(&entry->name, "@enumTagType(%s)", buf_ptr(&enum_type->name)); | ||
| 1271 | |||
| 1272 | entry->is_copyable = true; | ||
| 1273 | entry->data.enum_tag.enum_type = enum_type; | ||
| 1274 | entry->data.enum_tag.int_type = int_type; | ||
| 1275 | entry->type_ref = int_type->type_ref; | ||
| 1276 | entry->di_type = int_type->di_type; | ||
| 1277 | entry->zero_bits = int_type->zero_bits; | ||
| 1278 | |||
| 1279 | return entry; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | 1262 | static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1283 | assert(enum_type->id == TypeTableEntryIdEnum); | 1263 | assert(enum_type->id == TypeTableEntryIdEnum); |
| 1284 | 1264 | ||
| ... | @@ -1308,14 +1288,6 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1308,14 +1288,6 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1308 | assert(enum_type->data.enumeration.fields); | 1288 | assert(enum_type->data.enumeration.fields); |
| 1309 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); | 1289 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); |
| 1310 | 1290 | ||
| 1311 | uint32_t gen_field_count = enum_type->data.enumeration.gen_field_count; | ||
| 1312 | ZigLLVMDIType **union_inner_di_types = allocate<ZigLLVMDIType*>(gen_field_count); | ||
| 1313 | |||
| 1314 | TypeTableEntry *most_aligned_union_member = nullptr; | ||
| 1315 | uint64_t size_of_most_aligned_member_in_bits = 0; | ||
| 1316 | uint64_t biggest_align_in_bits = 0; | ||
| 1317 | uint64_t biggest_size_in_bits = 0; | ||
| 1318 | |||
| 1319 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; | 1291 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| 1320 | ImportTableEntry *import = get_scope_import(scope); | 1292 | ImportTableEntry *import = get_scope_import(scope); |
| 1321 | 1293 | ||
| ... | @@ -1323,49 +1295,17 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1323,49 +1295,17 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1323 | enum_type->data.enumeration.embedded_in_current = true; | 1295 | enum_type->data.enumeration.embedded_in_current = true; |
| 1324 | 1296 | ||
| 1325 | for (uint32_t i = 0; i < field_count; i += 1) { | 1297 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 1326 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | 1298 | TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i]; |
| 1327 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; | ||
| 1328 | TypeTableEntry *field_type = type_enum_field->type_entry; | ||
| 1329 | |||
| 1330 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i); | ||
| 1331 | |||
| 1332 | ensure_complete_type(g, field_type); | ||
| 1333 | if (type_is_invalid(field_type)) { | ||
| 1334 | enum_type->data.enumeration.is_invalid = true; | ||
| 1335 | continue; | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | if (!type_has_bits(field_type)) | ||
| 1339 | continue; | ||
| 1340 | |||
| 1341 | uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); | ||
| 1342 | uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); | ||
| 1343 | |||
| 1344 | assert(store_size_in_bits > 0); | ||
| 1345 | assert(abi_align_in_bits > 0); | ||
| 1346 | |||
| 1347 | union_inner_di_types[type_enum_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 1348 | ZigLLVMTypeToScope(enum_type->di_type), buf_ptr(type_enum_field->name), | ||
| 1349 | import->di_file, (unsigned)(field_node->line + 1), | ||
| 1350 | store_size_in_bits, | ||
| 1351 | abi_align_in_bits, | ||
| 1352 | 0, | ||
| 1353 | 0, field_type->di_type); | ||
| 1354 | |||
| 1355 | biggest_size_in_bits = max(biggest_size_in_bits, store_size_in_bits); | ||
| 1356 | 1299 | ||
| 1357 | if (!most_aligned_union_member || abi_align_in_bits > biggest_align_in_bits) { | 1300 | // TODO send patch to LLVM to support APInt in createEnumerator instead of int64_t |
| 1358 | most_aligned_union_member = field_type; | 1301 | // http://lists.llvm.org/pipermail/llvm-dev/2017-December/119456.html |
| 1359 | biggest_align_in_bits = abi_align_in_bits; | 1302 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(enum_field->name), |
| 1360 | size_of_most_aligned_member_in_bits = store_size_in_bits; | 1303 | bigint_as_signed(&enum_field->value)); |
| 1361 | } | ||
| 1362 | } | 1304 | } |
| 1363 | 1305 | ||
| 1364 | // unset temporary flag | 1306 | // unset temporary flag |
| 1365 | enum_type->data.enumeration.embedded_in_current = false; | 1307 | enum_type->data.enumeration.embedded_in_current = false; |
| 1366 | enum_type->data.enumeration.complete = true; | 1308 | enum_type->data.enumeration.complete = true; |
| 1367 | enum_type->data.enumeration.union_size_bytes = biggest_size_in_bits / 8; | ||
| 1368 | enum_type->data.enumeration.most_aligned_union_member = most_aligned_union_member; | ||
| 1369 | 1309 | ||
| 1370 | if (enum_type->data.enumeration.is_invalid) | 1310 | if (enum_type->data.enumeration.is_invalid) |
| 1371 | return; | 1311 | return; |
| ... | @@ -1390,118 +1330,21 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1390,118 +1330,21 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1390 | return; | 1330 | return; |
| 1391 | } | 1331 | } |
| 1392 | 1332 | ||
| 1393 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); | 1333 | TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type; |
| 1394 | TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); | ||
| 1395 | enum_type->data.enumeration.tag_type = tag_type_entry; | ||
| 1396 | |||
| 1397 | uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | ||
| 1398 | |||
| 1399 | if (most_aligned_union_member) { | ||
| 1400 | // create llvm type for union | ||
| 1401 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; | ||
| 1402 | LLVMTypeRef union_type_ref; | ||
| 1403 | if (padding_in_bits > 0) { | ||
| 1404 | TypeTableEntry *u8_type = get_int_type(g, false, 8); | ||
| 1405 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); | ||
| 1406 | LLVMTypeRef union_element_types[] = { | ||
| 1407 | most_aligned_union_member->type_ref, | ||
| 1408 | padding_array->type_ref, | ||
| 1409 | }; | ||
| 1410 | union_type_ref = LLVMStructType(union_element_types, 2, false); | ||
| 1411 | } else { | ||
| 1412 | union_type_ref = most_aligned_union_member->type_ref; | ||
| 1413 | } | ||
| 1414 | enum_type->data.enumeration.union_type_ref = union_type_ref; | ||
| 1415 | |||
| 1416 | assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits); | ||
| 1417 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); | ||
| 1418 | |||
| 1419 | if (align_of_tag_in_bits >= biggest_align_in_bits) { | ||
| 1420 | enum_type->data.enumeration.gen_tag_index = 0; | ||
| 1421 | enum_type->data.enumeration.gen_union_index = 1; | ||
| 1422 | } else { | ||
| 1423 | enum_type->data.enumeration.gen_union_index = 0; | ||
| 1424 | enum_type->data.enumeration.gen_tag_index = 1; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | // create llvm type for root struct | ||
| 1428 | LLVMTypeRef root_struct_element_types[2]; | ||
| 1429 | root_struct_element_types[enum_type->data.enumeration.gen_tag_index] = tag_type_entry->type_ref; | ||
| 1430 | root_struct_element_types[enum_type->data.enumeration.gen_union_index] = union_type_ref; | ||
| 1431 | LLVMStructSetBody(enum_type->type_ref, root_struct_element_types, 2, false); | ||
| 1432 | |||
| 1433 | // create debug type for tag | ||
| 1434 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 1435 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 1436 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | ||
| 1437 | ZigLLVMTypeToScope(enum_type->di_type), "AnonEnum", | ||
| 1438 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1439 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, | ||
| 1440 | tag_type_entry->di_type, ""); | ||
| 1441 | |||
| 1442 | // create debug type for union | ||
| 1443 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, | ||
| 1444 | ZigLLVMTypeToScope(enum_type->di_type), "AnonUnion", | ||
| 1445 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1446 | biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types, | ||
| 1447 | gen_field_count, 0, ""); | ||
| 1448 | |||
| 1449 | // create debug types for members of root struct | ||
| 1450 | uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, | ||
| 1451 | enum_type->data.enumeration.gen_tag_index); | ||
| 1452 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 1453 | ZigLLVMTypeToScope(enum_type->di_type), "tag_field", | ||
| 1454 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1455 | tag_debug_size_in_bits, | ||
| 1456 | tag_debug_align_in_bits, | ||
| 1457 | tag_offset_in_bits, | ||
| 1458 | 0, tag_di_type); | ||
| 1459 | |||
| 1460 | uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, | ||
| 1461 | enum_type->data.enumeration.gen_union_index); | ||
| 1462 | ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 1463 | ZigLLVMTypeToScope(enum_type->di_type), "union_field", | ||
| 1464 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1465 | biggest_size_in_bits, | ||
| 1466 | biggest_align_in_bits, | ||
| 1467 | union_offset_in_bits, | ||
| 1468 | 0, union_di_type); | ||
| 1469 | |||
| 1470 | // create debug type for root struct | ||
| 1471 | ZigLLVMDIType *di_root_members[2]; | ||
| 1472 | di_root_members[enum_type->data.enumeration.gen_tag_index] = tag_member_di_type; | ||
| 1473 | di_root_members[enum_type->data.enumeration.gen_union_index] = union_member_di_type; | ||
| 1474 | |||
| 1475 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, enum_type->type_ref); | ||
| 1476 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, enum_type->type_ref); | ||
| 1477 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | ||
| 1478 | ZigLLVMFileToScope(import->di_file), | ||
| 1479 | buf_ptr(&enum_type->name), | ||
| 1480 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1481 | debug_size_in_bits, | ||
| 1482 | debug_align_in_bits, | ||
| 1483 | 0, nullptr, di_root_members, 2, 0, nullptr, ""); | ||
| 1484 | |||
| 1485 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type); | ||
| 1486 | enum_type->di_type = replacement_di_type; | ||
| 1487 | } else { | ||
| 1488 | // create llvm type for root struct | ||
| 1489 | enum_type->type_ref = tag_type_entry->type_ref; | ||
| 1490 | 1334 | ||
| 1491 | // create debug type for tag | 1335 | // create debug type for tag |
| 1492 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | 1336 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_int_type->type_ref); |
| 1493 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | 1337 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); |
| 1494 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | 1338 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, |
| 1495 | ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name), | 1339 | ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name), |
| 1496 | import->di_file, (unsigned)(decl_node->line + 1), | 1340 | import->di_file, (unsigned)(decl_node->line + 1), |
| 1497 | tag_debug_size_in_bits, | 1341 | tag_debug_size_in_bits, |
| 1498 | tag_debug_align_in_bits, | 1342 | tag_debug_align_in_bits, |
| 1499 | di_enumerators, field_count, | 1343 | di_enumerators, field_count, |
| 1500 | tag_type_entry->di_type, ""); | 1344 | tag_int_type->di_type, ""); |
| 1501 | 1345 | ||
| 1502 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type); | 1346 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type); |
| 1503 | enum_type->di_type = tag_di_type; | 1347 | enum_type->di_type = tag_di_type; |
| 1504 | } | ||
| 1505 | } | 1348 | } |
| 1506 | 1349 | ||
| 1507 | static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { | 1350 | static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { |
| ... | @@ -1517,8 +1360,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { | ... | @@ -1517,8 +1360,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { |
| 1517 | case TypeTableEntryIdNullLit: | 1360 | case TypeTableEntryIdNullLit: |
| 1518 | case TypeTableEntryIdErrorUnion: | 1361 | case TypeTableEntryIdErrorUnion: |
| 1519 | case TypeTableEntryIdPureError: | 1362 | case TypeTableEntryIdPureError: |
| 1520 | case TypeTableEntryIdEnum: | ||
| 1521 | case TypeTableEntryIdEnumTag: | ||
| 1522 | case TypeTableEntryIdNamespace: | 1363 | case TypeTableEntryIdNamespace: |
| 1523 | case TypeTableEntryIdBlock: | 1364 | case TypeTableEntryIdBlock: |
| 1524 | case TypeTableEntryIdBoundFn: | 1365 | case TypeTableEntryIdBoundFn: |
| ... | @@ -1541,6 +1382,8 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { | ... | @@ -1541,6 +1382,8 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { |
| 1541 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; | 1382 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 1542 | return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; | 1383 | return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; |
| 1543 | } | 1384 | } |
| 1385 | case TypeTableEntryIdEnum: | ||
| 1386 | return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr; | ||
| 1544 | } | 1387 | } |
| 1545 | zig_unreachable(); | 1388 | zig_unreachable(); |
| 1546 | } | 1389 | } |
| ... | @@ -1658,7 +1501,6 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -1658,7 +1501,6 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1658 | TypeTableEntry *field_type = type_struct_field->type_entry; | 1501 | TypeTableEntry *field_type = type_struct_field->type_entry; |
| 1659 | 1502 | ||
| 1660 | ensure_complete_type(g, field_type); | 1503 | ensure_complete_type(g, field_type); |
| 1661 | |||
| 1662 | if (type_is_invalid(field_type)) { | 1504 | if (type_is_invalid(field_type)) { |
| 1663 | struct_type->data.structure.is_invalid = true; | 1505 | struct_type->data.structure.is_invalid = true; |
| 1664 | break; | 1506 | break; |
| ... | @@ -1849,6 +1691,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1849,6 +1691,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1849 | if (union_type->data.unionation.embedded_in_current) { | 1691 | if (union_type->data.unionation.embedded_in_current) { |
| 1850 | if (!union_type->data.unionation.reported_infinite_err) { | 1692 | if (!union_type->data.unionation.reported_infinite_err) { |
| 1851 | union_type->data.unionation.reported_infinite_err = true; | 1693 | union_type->data.unionation.reported_infinite_err = true; |
| 1694 | union_type->data.unionation.is_invalid = true; | ||
| 1852 | add_node_error(g, decl_node, buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name))); | 1695 | add_node_error(g, decl_node, buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name))); |
| 1853 | } | 1696 | } |
| 1854 | return; | 1697 | return; |
| ... | @@ -1870,19 +1713,17 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1870,19 +1713,17 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1870 | uint64_t biggest_align_in_bits = 0; | 1713 | uint64_t biggest_align_in_bits = 0; |
| 1871 | uint64_t biggest_size_in_bits = 0; | 1714 | uint64_t biggest_size_in_bits = 0; |
| 1872 | 1715 | ||
| 1873 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); | ||
| 1874 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); | ||
| 1875 | |||
| 1876 | Scope *scope = &union_type->data.unionation.decls_scope->base; | 1716 | Scope *scope = &union_type->data.unionation.decls_scope->base; |
| 1877 | ImportTableEntry *import = get_scope_import(scope); | 1717 | ImportTableEntry *import = get_scope_import(scope); |
| 1878 | 1718 | ||
| 1879 | // set temporary flag | 1719 | // set temporary flag |
| 1880 | union_type->data.unionation.embedded_in_current = true; | 1720 | union_type->data.unionation.embedded_in_current = true; |
| 1881 | 1721 | ||
| 1722 | |||
| 1882 | for (uint32_t i = 0; i < field_count; i += 1) { | 1723 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 1883 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | 1724 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| 1884 | TypeUnionField *type_union_field = &union_type->data.unionation.fields[i]; | 1725 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; |
| 1885 | TypeTableEntry *field_type = type_union_field->type_entry; | 1726 | TypeTableEntry *field_type = union_field->type_entry; |
| 1886 | 1727 | ||
| 1887 | ensure_complete_type(g, field_type); | 1728 | ensure_complete_type(g, field_type); |
| 1888 | if (type_is_invalid(field_type)) { | 1729 | if (type_is_invalid(field_type)) { |
| ... | @@ -1893,16 +1734,14 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1893,16 +1734,14 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1893 | if (!type_has_bits(field_type)) | 1734 | if (!type_has_bits(field_type)) |
| 1894 | continue; | 1735 | continue; |
| 1895 | 1736 | ||
| 1896 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(type_union_field->name), i); | ||
| 1897 | |||
| 1898 | uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); | 1737 | uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); |
| 1899 | uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); | 1738 | uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); |
| 1900 | 1739 | ||
| 1901 | assert(store_size_in_bits > 0); | 1740 | assert(store_size_in_bits > 0); |
| 1902 | assert(abi_align_in_bits > 0); | 1741 | assert(abi_align_in_bits > 0); |
| 1903 | 1742 | ||
| 1904 | union_inner_di_types[type_union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, | 1743 | union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 1905 | ZigLLVMTypeToScope(union_type->di_type), buf_ptr(type_union_field->name), | 1744 | ZigLLVMTypeToScope(union_type->di_type), buf_ptr(union_field->enum_field->name), |
| 1906 | import->di_file, (unsigned)(field_node->line + 1), | 1745 | import->di_file, (unsigned)(field_node->line + 1), |
| 1907 | store_size_in_bits, | 1746 | store_size_in_bits, |
| 1908 | abi_align_in_bits, | 1747 | abi_align_in_bits, |
| ... | @@ -1918,6 +1757,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1918,6 +1757,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1918 | } | 1757 | } |
| 1919 | } | 1758 | } |
| 1920 | 1759 | ||
| 1760 | |||
| 1921 | // unset temporary flag | 1761 | // unset temporary flag |
| 1922 | union_type->data.unionation.embedded_in_current = false; | 1762 | union_type->data.unionation.embedded_in_current = false; |
| 1923 | union_type->data.unionation.complete = true; | 1763 | union_type->data.unionation.complete = true; |
| ... | @@ -1947,13 +1787,12 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1947,13 +1787,12 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1947 | return; | 1787 | return; |
| 1948 | } | 1788 | } |
| 1949 | 1789 | ||
| 1950 | assert(most_aligned_union_member != nullptr); | ||
| 1951 | |||
| 1952 | bool want_safety = auto_layout && (field_count >= 2); | ||
| 1953 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; | 1790 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; |
| 1954 | 1791 | ||
| 1792 | TypeTableEntry *tag_type = union_type->data.unionation.tag_type; | ||
| 1793 | if (tag_type == nullptr) { | ||
| 1794 | assert(most_aligned_union_member != nullptr); | ||
| 1955 | 1795 | ||
| 1956 | if (!want_safety) { | ||
| 1957 | if (padding_in_bits > 0) { | 1796 | if (padding_in_bits > 0) { |
| 1958 | TypeTableEntry *u8_type = get_int_type(g, false, 8); | 1797 | TypeTableEntry *u8_type = get_int_type(g, false, 8); |
| 1959 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); | 1798 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); |
| ... | @@ -1993,6 +1832,14 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1993,6 +1832,14 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1993 | padding_array->type_ref, | 1832 | padding_array->type_ref, |
| 1994 | }; | 1833 | }; |
| 1995 | union_type_ref = LLVMStructType(union_element_types, 2, false); | 1834 | union_type_ref = LLVMStructType(union_element_types, 2, false); |
| 1835 | } else if (most_aligned_union_member == nullptr) { | ||
| 1836 | union_type->data.unionation.gen_tag_index = SIZE_MAX; | ||
| 1837 | union_type->data.unionation.gen_union_index = SIZE_MAX; | ||
| 1838 | union_type->type_ref = tag_type->type_ref; | ||
| 1839 | |||
| 1840 | ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, tag_type->di_type); | ||
| 1841 | union_type->di_type = tag_type->di_type; | ||
| 1842 | return; | ||
| 1996 | } else { | 1843 | } else { |
| 1997 | union_type_ref = most_aligned_union_member->type_ref; | 1844 | union_type_ref = most_aligned_union_member->type_ref; |
| 1998 | } | 1845 | } |
| ... | @@ -2002,9 +1849,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2002,9 +1849,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2002 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); | 1849 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); |
| 2003 | 1850 | ||
| 2004 | // create llvm type for root struct | 1851 | // create llvm type for root struct |
| 2005 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); | 1852 | TypeTableEntry *tag_int_type = tag_type->data.enumeration.tag_int_type; |
| 2006 | TypeTableEntry *tag_type_entry = tag_int_type; | ||
| 2007 | union_type->data.unionation.tag_type = tag_type_entry; | ||
| 2008 | uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | 1853 | uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); |
| 2009 | 1854 | ||
| 2010 | if (align_of_tag_in_bits >= biggest_align_in_bits) { | 1855 | if (align_of_tag_in_bits >= biggest_align_in_bits) { |
| ... | @@ -2016,22 +1861,11 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2016,22 +1861,11 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2016 | } | 1861 | } |
| 2017 | 1862 | ||
| 2018 | LLVMTypeRef root_struct_element_types[2]; | 1863 | LLVMTypeRef root_struct_element_types[2]; |
| 2019 | root_struct_element_types[union_type->data.unionation.gen_tag_index] = tag_type_entry->type_ref; | 1864 | root_struct_element_types[union_type->data.unionation.gen_tag_index] = tag_type->type_ref; |
| 2020 | root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref; | 1865 | root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref; |
| 2021 | LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false); | 1866 | LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false); |
| 2022 | 1867 | ||
| 2023 | 1868 | ||
| 2024 | // create debug type for root struct | ||
| 2025 | |||
| 2026 | // create debug type for tag | ||
| 2027 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 2028 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 2029 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | ||
| 2030 | ZigLLVMTypeToScope(union_type->di_type), "AnonEnum", | ||
| 2031 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 2032 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, | ||
| 2033 | tag_type_entry->di_type, ""); | ||
| 2034 | |||
| 2035 | // create debug type for union | 1869 | // create debug type for union |
| 2036 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, | 1870 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, |
| 2037 | ZigLLVMTypeToScope(union_type->di_type), "AnonUnion", | 1871 | ZigLLVMTypeToScope(union_type->di_type), "AnonUnion", |
| ... | @@ -2045,19 +1879,23 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2045,19 +1879,23 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2045 | union_type->data.unionation.gen_tag_index); | 1879 | union_type->data.unionation.gen_tag_index); |
| 2046 | 1880 | ||
| 2047 | ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | 1881 | ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 2048 | ZigLLVMTypeToScope(union_type->di_type), "union_field", | 1882 | ZigLLVMTypeToScope(union_type->di_type), "payload", |
| 2049 | import->di_file, (unsigned)(decl_node->line + 1), | 1883 | import->di_file, (unsigned)(decl_node->line + 1), |
| 2050 | biggest_size_in_bits, | 1884 | biggest_size_in_bits, |
| 2051 | biggest_align_in_bits, | 1885 | biggest_align_in_bits, |
| 2052 | union_offset_in_bits, | 1886 | union_offset_in_bits, |
| 2053 | 0, union_di_type); | 1887 | 0, union_di_type); |
| 1888 | |||
| 1889 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); | ||
| 1890 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); | ||
| 1891 | |||
| 2054 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | 1892 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 2055 | ZigLLVMTypeToScope(union_type->di_type), "tag_field", | 1893 | ZigLLVMTypeToScope(union_type->di_type), "tag", |
| 2056 | import->di_file, (unsigned)(decl_node->line + 1), | 1894 | import->di_file, (unsigned)(decl_node->line + 1), |
| 2057 | tag_debug_size_in_bits, | 1895 | tag_debug_size_in_bits, |
| 2058 | tag_debug_align_in_bits, | 1896 | tag_debug_align_in_bits, |
| 2059 | tag_offset_in_bits, | 1897 | tag_offset_in_bits, |
| 2060 | 0, tag_di_type); | 1898 | 0, tag_type->di_type); |
| 2061 | 1899 | ||
| 2062 | ZigLLVMDIType *di_root_members[2]; | 1900 | ZigLLVMDIType *di_root_members[2]; |
| 2063 | di_root_members[union_type->data.unionation.gen_tag_index] = tag_member_di_type; | 1901 | di_root_members[union_type->data.unionation.gen_tag_index] = tag_member_di_type; |
| ... | @@ -2096,51 +1934,124 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -2096,51 +1934,124 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 2096 | 1934 | ||
| 2097 | assert(!enum_type->data.enumeration.fields); | 1935 | assert(!enum_type->data.enumeration.fields); |
| 2098 | uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length; | 1936 | uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length; |
| 1937 | if (field_count == 0) { | ||
| 1938 | add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields")); | ||
| 1939 | |||
| 1940 | enum_type->data.enumeration.src_field_count = field_count; | ||
| 1941 | enum_type->data.enumeration.fields = nullptr; | ||
| 1942 | enum_type->data.enumeration.is_invalid = true; | ||
| 1943 | enum_type->data.enumeration.zero_bits_loop_flag = false; | ||
| 1944 | enum_type->data.enumeration.zero_bits_known = true; | ||
| 1945 | return; | ||
| 1946 | } | ||
| 1947 | |||
| 2099 | enum_type->data.enumeration.src_field_count = field_count; | 1948 | enum_type->data.enumeration.src_field_count = field_count; |
| 2100 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); | 1949 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); |
| 2101 | 1950 | ||
| 2102 | uint32_t biggest_align_bytes = 0; | ||
| 2103 | |||
| 2104 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; | 1951 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| 2105 | 1952 | ||
| 2106 | uint32_t gen_field_index = 0; | 1953 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; |
| 2107 | for (uint32_t i = 0; i < field_count; i += 1) { | 1954 | occupied_tag_values.init(field_count); |
| 2108 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | ||
| 2109 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; | ||
| 2110 | type_enum_field->name = field_node->data.struct_field.name; | ||
| 2111 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | ||
| 2112 | type_enum_field->type_entry = field_type; | ||
| 2113 | type_enum_field->value = i; | ||
| 2114 | 1955 | ||
| 2115 | type_ensure_zero_bits_known(g, field_type); | 1956 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); |
| 2116 | if (type_is_invalid(field_type)) { | 1957 | |
| 1958 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { | ||
| 1959 | TypeTableEntry *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); | ||
| 1960 | if (type_is_invalid(wanted_tag_int_type)) { | ||
| 2117 | enum_type->data.enumeration.is_invalid = true; | 1961 | enum_type->data.enumeration.is_invalid = true; |
| 2118 | continue; | 1962 | } else if (wanted_tag_int_type->id != TypeTableEntryIdInt) { |
| 1963 | enum_type->data.enumeration.is_invalid = true; | ||
| 1964 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 1965 | buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | ||
| 1966 | } else if (wanted_tag_int_type->data.integral.is_signed) { | ||
| 1967 | enum_type->data.enumeration.is_invalid = true; | ||
| 1968 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 1969 | buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | ||
| 1970 | } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) { | ||
| 1971 | enum_type->data.enumeration.is_invalid = true; | ||
| 1972 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 1973 | buf_sprintf("'%s' too small to hold all bits; must be at least '%s'", | ||
| 1974 | buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name))); | ||
| 1975 | } else { | ||
| 1976 | tag_int_type = wanted_tag_int_type; | ||
| 2119 | } | 1977 | } |
| 1978 | } | ||
| 1979 | enum_type->data.enumeration.tag_int_type = tag_int_type; | ||
| 1980 | enum_type->type_ref = tag_int_type->type_ref; | ||
| 2120 | 1981 | ||
| 2121 | if (!type_has_bits(field_type)) | 1982 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 2122 | continue; | 1983 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| 1984 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | ||
| 1985 | type_enum_field->name = field_node->data.struct_field.name; | ||
| 1986 | type_enum_field->decl_index = field_i; | ||
| 2123 | 1987 | ||
| 2124 | type_enum_field->gen_index = gen_field_index; | 1988 | if (field_node->data.struct_field.type != nullptr) { |
| 2125 | gen_field_index += 1; | 1989 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type, |
| 1990 | buf_sprintf("structs and unions, not enums, support field types")); | ||
| 1991 | add_error_note(g, msg, decl_node, | ||
| 1992 | buf_sprintf("consider 'union(enum)' here")); | ||
| 1993 | } | ||
| 2126 | 1994 | ||
| 2127 | uint32_t field_align_bytes = get_abi_alignment(g, field_type); | 1995 | AstNode *tag_value = field_node->data.struct_field.value; |
| 2128 | if (field_align_bytes > biggest_align_bytes) { | 1996 | |
| 2129 | biggest_align_bytes = field_align_bytes; | 1997 | // In this first pass we resolve explicit tag values. |
| 1998 | // In a second pass we will fill in the unspecified ones. | ||
| 1999 | if (tag_value != nullptr) { | ||
| 2000 | IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | ||
| 2001 | if (result_inst->value.type->id == TypeTableEntryIdInvalid) { | ||
| 2002 | enum_type->data.enumeration.is_invalid = true; | ||
| 2003 | continue; | ||
| 2004 | } | ||
| 2005 | assert(result_inst->value.special != ConstValSpecialRuntime); | ||
| 2006 | assert(result_inst->value.type->id == TypeTableEntryIdInt); | ||
| 2007 | auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); | ||
| 2008 | if (entry == nullptr) { | ||
| 2009 | bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint); | ||
| 2010 | } else { | ||
| 2011 | Buf *val_buf = buf_alloc(); | ||
| 2012 | bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); | ||
| 2013 | |||
| 2014 | ErrorMsg *msg = add_node_error(g, tag_value, | ||
| 2015 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | ||
| 2016 | add_error_note(g, msg, entry->value, | ||
| 2017 | buf_sprintf("other occurrence here")); | ||
| 2018 | enum_type->data.enumeration.is_invalid = true; | ||
| 2019 | continue; | ||
| 2020 | } | ||
| 2130 | } | 2021 | } |
| 2131 | } | 2022 | } |
| 2132 | 2023 | ||
| 2133 | enum_type->data.enumeration.zero_bits_loop_flag = false; | 2024 | // Now iterate again and populate the unspecified tag values |
| 2134 | enum_type->data.enumeration.gen_field_count = gen_field_index; | 2025 | uint32_t next_maybe_unoccupied_index = 0; |
| 2135 | enum_type->zero_bits = (gen_field_index == 0 && field_count < 2); | 2026 | |
| 2136 | enum_type->data.enumeration.zero_bits_known = true; | 2027 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 2028 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | ||
| 2029 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | ||
| 2030 | AstNode *tag_value = field_node->data.struct_field.value; | ||
| 2137 | 2031 | ||
| 2138 | // also compute abi_alignment | 2032 | if (tag_value == nullptr) { |
| 2139 | if (!enum_type->zero_bits) { | 2033 | if (occupied_tag_values.size() == 0) { |
| 2140 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); | 2034 | bigint_init_unsigned(&type_enum_field->value, next_maybe_unoccupied_index); |
| 2141 | uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | 2035 | next_maybe_unoccupied_index += 1; |
| 2142 | enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes); | 2036 | } else { |
| 2037 | BigInt proposed_value; | ||
| 2038 | for (;;) { | ||
| 2039 | bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index); | ||
| 2040 | next_maybe_unoccupied_index += 1; | ||
| 2041 | auto entry = occupied_tag_values.put_unique(proposed_value, field_node); | ||
| 2042 | if (entry != nullptr) { | ||
| 2043 | continue; | ||
| 2044 | } | ||
| 2045 | break; | ||
| 2046 | } | ||
| 2047 | bigint_init_bigint(&type_enum_field->value, &proposed_value); | ||
| 2048 | } | ||
| 2049 | } | ||
| 2143 | } | 2050 | } |
| 2051 | |||
| 2052 | enum_type->data.enumeration.zero_bits_loop_flag = false; | ||
| 2053 | enum_type->zero_bits = (field_count < 2); | ||
| 2054 | enum_type->data.enumeration.zero_bits_known = true; | ||
| 2144 | } | 2055 | } |
| 2145 | 2056 | ||
| 2146 | static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | 2057 | static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| ... | @@ -2184,11 +2095,23 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -2184,11 +2095,23 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 2184 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | 2095 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| 2185 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | 2096 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 2186 | type_struct_field->name = field_node->data.struct_field.name; | 2097 | type_struct_field->name = field_node->data.struct_field.name; |
| 2098 | |||
| 2099 | if (field_node->data.struct_field.type == nullptr) { | ||
| 2100 | add_node_error(g, field_node, buf_sprintf("struct field missing type")); | ||
| 2101 | struct_type->data.structure.is_invalid = true; | ||
| 2102 | continue; | ||
| 2103 | } | ||
| 2104 | |||
| 2187 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | 2105 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); |
| 2188 | type_struct_field->type_entry = field_type; | 2106 | type_struct_field->type_entry = field_type; |
| 2189 | type_struct_field->src_index = i; | 2107 | type_struct_field->src_index = i; |
| 2190 | type_struct_field->gen_index = SIZE_MAX; | 2108 | type_struct_field->gen_index = SIZE_MAX; |
| 2191 | 2109 | ||
| 2110 | if (field_node->data.struct_field.value != nullptr) { | ||
| 2111 | add_node_error(g, field_node->data.struct_field.value, | ||
| 2112 | buf_sprintf("enums, not structs, support field assignment")); | ||
| 2113 | } | ||
| 2114 | |||
| 2192 | type_ensure_zero_bits_known(g, field_type); | 2115 | type_ensure_zero_bits_known(g, field_type); |
| 2193 | if (type_is_invalid(field_type)) { | 2116 | if (type_is_invalid(field_type)) { |
| 2194 | struct_type->data.structure.is_invalid = true; | 2117 | struct_type->data.structure.is_invalid = true; |
| ... | @@ -2225,8 +2148,23 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2225,8 +2148,23 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2225 | if (union_type->data.unionation.zero_bits_known) | 2148 | if (union_type->data.unionation.zero_bits_known) |
| 2226 | return; | 2149 | return; |
| 2227 | 2150 | ||
| 2151 | if (type_is_invalid(union_type)) | ||
| 2152 | return; | ||
| 2153 | |||
| 2228 | if (union_type->data.unionation.zero_bits_loop_flag) { | 2154 | if (union_type->data.unionation.zero_bits_loop_flag) { |
| 2155 | // If we get here it's due to recursion. From this we conclude that the struct is | ||
| 2156 | // not zero bits, and if abi_alignment == 0 we further conclude that the first field | ||
| 2157 | // is a pointer to this very struct, or a function pointer with parameters that | ||
| 2158 | // reference such a type. | ||
| 2229 | union_type->data.unionation.zero_bits_known = true; | 2159 | union_type->data.unionation.zero_bits_known = true; |
| 2160 | if (union_type->data.unionation.abi_alignment == 0) { | ||
| 2161 | if (union_type->data.unionation.layout == ContainerLayoutPacked) { | ||
| 2162 | union_type->data.unionation.abi_alignment = 1; | ||
| 2163 | } else { | ||
| 2164 | union_type->data.unionation.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, | ||
| 2165 | LLVMPointerType(LLVMInt8Type(), 0)); | ||
| 2166 | } | ||
| 2167 | } | ||
| 2230 | return; | 2168 | return; |
| 2231 | } | 2169 | } |
| 2232 | 2170 | ||
| ... | @@ -2238,6 +2176,16 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2238,6 +2176,16 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2238 | 2176 | ||
| 2239 | assert(!union_type->data.unionation.fields); | 2177 | assert(!union_type->data.unionation.fields); |
| 2240 | uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length; | 2178 | uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length; |
| 2179 | if (field_count == 0) { | ||
| 2180 | add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields")); | ||
| 2181 | |||
| 2182 | union_type->data.unionation.src_field_count = field_count; | ||
| 2183 | union_type->data.unionation.fields = nullptr; | ||
| 2184 | union_type->data.unionation.is_invalid = true; | ||
| 2185 | union_type->data.unionation.zero_bits_loop_flag = false; | ||
| 2186 | union_type->data.unionation.zero_bits_known = true; | ||
| 2187 | return; | ||
| 2188 | } | ||
| 2241 | union_type->data.unionation.src_field_count = field_count; | 2189 | union_type->data.unionation.src_field_count = field_count; |
| 2242 | union_type->data.unionation.fields = allocate<TypeUnionField>(field_count); | 2190 | union_type->data.unionation.fields = allocate<TypeUnionField>(field_count); |
| 2243 | 2191 | ||
| ... | @@ -2245,44 +2193,261 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2245,44 +2193,261 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2245 | 2193 | ||
| 2246 | Scope *scope = &union_type->data.unionation.decls_scope->base; | 2194 | Scope *scope = &union_type->data.unionation.decls_scope->base; |
| 2247 | 2195 | ||
| 2196 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; | ||
| 2197 | |||
| 2198 | AstNode *enum_type_node = decl_node->data.container_decl.init_arg_expr; | ||
| 2199 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); | ||
| 2200 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr); | ||
| 2201 | TypeTableEntry *tag_type; | ||
| 2202 | bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety); | ||
| 2203 | bool *covered_enum_fields; | ||
| 2204 | ZigLLVMDIEnumerator **di_enumerators; | ||
| 2205 | if (create_enum_type) { | ||
| 2206 | occupied_tag_values.init(field_count); | ||
| 2207 | |||
| 2208 | di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); | ||
| 2209 | |||
| 2210 | TypeTableEntry *tag_int_type; | ||
| 2211 | if (enum_type_node != nullptr) { | ||
| 2212 | tag_int_type = analyze_type_expr(g, scope, enum_type_node); | ||
| 2213 | if (type_is_invalid(tag_int_type)) { | ||
| 2214 | union_type->data.unionation.is_invalid = true; | ||
| 2215 | return; | ||
| 2216 | } | ||
| 2217 | if (tag_int_type->id != TypeTableEntryIdInt) { | ||
| 2218 | add_node_error(g, enum_type_node, | ||
| 2219 | buf_sprintf("expected integer tag type, found '%s'", buf_ptr(&tag_int_type->name))); | ||
| 2220 | union_type->data.unionation.is_invalid = true; | ||
| 2221 | return; | ||
| 2222 | } | ||
| 2223 | } else { | ||
| 2224 | tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); | ||
| 2225 | } | ||
| 2226 | union_type->data.unionation.abi_alignment = get_abi_alignment(g, tag_int_type); | ||
| 2227 | |||
| 2228 | tag_type = new_type_table_entry(TypeTableEntryIdEnum); | ||
| 2229 | buf_resize(&tag_type->name, 0); | ||
| 2230 | buf_appendf(&tag_type->name, "@EnumTagType(%s)", buf_ptr(&union_type->name)); | ||
| 2231 | tag_type->is_copyable = true; | ||
| 2232 | tag_type->type_ref = tag_int_type->type_ref; | ||
| 2233 | tag_type->zero_bits = tag_int_type->zero_bits; | ||
| 2234 | |||
| 2235 | tag_type->data.enumeration.tag_int_type = tag_int_type; | ||
| 2236 | tag_type->data.enumeration.zero_bits_known = true; | ||
| 2237 | tag_type->data.enumeration.decl_node = decl_node; | ||
| 2238 | tag_type->data.enumeration.layout = ContainerLayoutAuto; | ||
| 2239 | tag_type->data.enumeration.src_field_count = field_count; | ||
| 2240 | tag_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); | ||
| 2241 | tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope; | ||
| 2242 | tag_type->data.enumeration.complete = true; | ||
| 2243 | } else if (enum_type_node != nullptr) { | ||
| 2244 | TypeTableEntry *enum_type = analyze_type_expr(g, scope, enum_type_node); | ||
| 2245 | if (type_is_invalid(enum_type)) { | ||
| 2246 | union_type->data.unionation.is_invalid = true; | ||
| 2247 | union_type->data.unionation.embedded_in_current = false; | ||
| 2248 | return; | ||
| 2249 | } | ||
| 2250 | if (enum_type->id != TypeTableEntryIdEnum) { | ||
| 2251 | union_type->data.unionation.is_invalid = true; | ||
| 2252 | union_type->data.unionation.embedded_in_current = false; | ||
| 2253 | add_node_error(g, enum_type_node, | ||
| 2254 | buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name))); | ||
| 2255 | return; | ||
| 2256 | } | ||
| 2257 | tag_type = enum_type; | ||
| 2258 | covered_enum_fields = allocate<bool>(enum_type->data.enumeration.src_field_count); | ||
| 2259 | union_type->data.unionation.abi_alignment = get_abi_alignment(g, enum_type); | ||
| 2260 | } else { | ||
| 2261 | tag_type = nullptr; | ||
| 2262 | } | ||
| 2263 | union_type->data.unionation.tag_type = tag_type; | ||
| 2264 | |||
| 2248 | uint32_t gen_field_index = 0; | 2265 | uint32_t gen_field_index = 0; |
| 2249 | for (uint32_t i = 0; i < field_count; i += 1) { | 2266 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 2250 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | 2267 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| 2251 | TypeUnionField *type_union_field = &union_type->data.unionation.fields[i]; | 2268 | Buf *field_name = field_node->data.struct_field.name; |
| 2252 | type_union_field->name = field_node->data.struct_field.name; | 2269 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; |
| 2253 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | 2270 | union_field->name = field_node->data.struct_field.name; |
| 2254 | type_union_field->type_entry = field_type; | 2271 | |
| 2255 | type_union_field->value = i; | 2272 | TypeTableEntry *field_type; |
| 2273 | if (field_node->data.struct_field.type == nullptr) { | ||
| 2274 | if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) { | ||
| 2275 | field_type = g->builtin_types.entry_void; | ||
| 2276 | } else { | ||
| 2277 | add_node_error(g, field_node, buf_sprintf("union field missing type")); | ||
| 2278 | union_type->data.unionation.is_invalid = true; | ||
| 2279 | continue; | ||
| 2280 | } | ||
| 2281 | } else { | ||
| 2282 | field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | ||
| 2283 | type_ensure_zero_bits_known(g, field_type); | ||
| 2284 | if (type_is_invalid(field_type)) { | ||
| 2285 | union_type->data.unionation.is_invalid = true; | ||
| 2286 | continue; | ||
| 2287 | } | ||
| 2288 | } | ||
| 2289 | union_field->type_entry = field_type; | ||
| 2256 | 2290 | ||
| 2257 | type_ensure_zero_bits_known(g, field_type); | 2291 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { |
| 2258 | if (type_is_invalid(field_type)) { | 2292 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, |
| 2259 | union_type->data.unionation.is_invalid = true; | 2293 | buf_sprintf("non-enum union field assignment")); |
| 2260 | continue; | 2294 | add_error_note(g, msg, decl_node, |
| 2295 | buf_sprintf("consider 'union(enum)' here")); | ||
| 2296 | } | ||
| 2297 | |||
| 2298 | if (create_enum_type) { | ||
| 2299 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(field_name), i); | ||
| 2300 | union_field->enum_field = &tag_type->data.enumeration.fields[i]; | ||
| 2301 | union_field->enum_field->name = field_name; | ||
| 2302 | union_field->enum_field->decl_index = i; | ||
| 2303 | |||
| 2304 | AstNode *tag_value = field_node->data.struct_field.value; | ||
| 2305 | // In this first pass we resolve explicit tag values. | ||
| 2306 | // In a second pass we will fill in the unspecified ones. | ||
| 2307 | if (tag_value != nullptr) { | ||
| 2308 | TypeTableEntry *tag_int_type = tag_type->data.enumeration.tag_int_type; | ||
| 2309 | IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | ||
| 2310 | if (result_inst->value.type->id == TypeTableEntryIdInvalid) { | ||
| 2311 | union_type->data.unionation.is_invalid = true; | ||
| 2312 | continue; | ||
| 2313 | } | ||
| 2314 | assert(result_inst->value.special != ConstValSpecialRuntime); | ||
| 2315 | assert(result_inst->value.type->id == TypeTableEntryIdInt); | ||
| 2316 | auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); | ||
| 2317 | if (entry == nullptr) { | ||
| 2318 | bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint); | ||
| 2319 | } else { | ||
| 2320 | Buf *val_buf = buf_alloc(); | ||
| 2321 | bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); | ||
| 2322 | |||
| 2323 | ErrorMsg *msg = add_node_error(g, tag_value, | ||
| 2324 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | ||
| 2325 | add_error_note(g, msg, entry->value, | ||
| 2326 | buf_sprintf("other occurrence here")); | ||
| 2327 | union_type->data.unionation.is_invalid = true; | ||
| 2328 | continue; | ||
| 2329 | } | ||
| 2330 | } | ||
| 2331 | } else if (enum_type_node != nullptr) { | ||
| 2332 | union_field->enum_field = find_enum_type_field(tag_type, field_name); | ||
| 2333 | if (union_field->enum_field == nullptr) { | ||
| 2334 | ErrorMsg *msg = add_node_error(g, field_node, | ||
| 2335 | buf_sprintf("enum field not found: '%s'", buf_ptr(field_name))); | ||
| 2336 | add_error_note(g, msg, tag_type->data.enumeration.decl_node, | ||
| 2337 | buf_sprintf("enum declared here")); | ||
| 2338 | union_type->data.unionation.is_invalid = true; | ||
| 2339 | continue; | ||
| 2340 | } | ||
| 2341 | covered_enum_fields[union_field->enum_field->decl_index] = true; | ||
| 2342 | } else { | ||
| 2343 | union_field->enum_field = allocate<TypeEnumField>(1); | ||
| 2344 | union_field->enum_field->name = field_name; | ||
| 2345 | union_field->enum_field->decl_index = i; | ||
| 2346 | bigint_init_unsigned(&union_field->enum_field->value, i); | ||
| 2261 | } | 2347 | } |
| 2348 | assert(union_field->enum_field != nullptr); | ||
| 2262 | 2349 | ||
| 2263 | if (!type_has_bits(field_type)) | 2350 | if (!type_has_bits(field_type)) |
| 2264 | continue; | 2351 | continue; |
| 2265 | 2352 | ||
| 2266 | type_union_field->gen_index = gen_field_index; | 2353 | union_field->gen_index = gen_field_index; |
| 2267 | gen_field_index += 1; | 2354 | gen_field_index += 1; |
| 2268 | 2355 | ||
| 2269 | uint32_t field_align_bytes = get_abi_alignment(g, field_type); | 2356 | uint32_t field_align_bytes = get_abi_alignment(g, field_type); |
| 2270 | if (field_align_bytes > biggest_align_bytes) { | 2357 | if (field_align_bytes > biggest_align_bytes) { |
| 2271 | biggest_align_bytes = field_align_bytes; | 2358 | biggest_align_bytes = field_align_bytes; |
| 2359 | if (biggest_align_bytes > union_type->data.unionation.abi_alignment) { | ||
| 2360 | union_type->data.unionation.abi_alignment = biggest_align_bytes; | ||
| 2361 | } | ||
| 2272 | } | 2362 | } |
| 2273 | } | 2363 | } |
| 2274 | 2364 | ||
| 2275 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); | 2365 | if (union_type->data.unionation.is_invalid) |
| 2366 | return; | ||
| 2367 | |||
| 2368 | bool src_have_tag = decl_node->data.container_decl.auto_enum || | ||
| 2369 | decl_node->data.container_decl.init_arg_expr != nullptr; | ||
| 2370 | |||
| 2371 | if (src_have_tag && union_type->data.unionation.layout != ContainerLayoutAuto) { | ||
| 2372 | const char *qual_str; | ||
| 2373 | switch (union_type->data.unionation.layout) { | ||
| 2374 | case ContainerLayoutAuto: | ||
| 2375 | zig_unreachable(); | ||
| 2376 | case ContainerLayoutPacked: | ||
| 2377 | qual_str = "packed"; | ||
| 2378 | break; | ||
| 2379 | case ContainerLayoutExtern: | ||
| 2380 | qual_str = "extern"; | ||
| 2381 | break; | ||
| 2382 | } | ||
| 2383 | AstNode *source_node = (decl_node->data.container_decl.init_arg_expr != nullptr) ? | ||
| 2384 | decl_node->data.container_decl.init_arg_expr : decl_node; | ||
| 2385 | add_node_error(g, source_node, | ||
| 2386 | buf_sprintf("%s union does not support enum tag type", qual_str)); | ||
| 2387 | union_type->data.unionation.is_invalid = true; | ||
| 2388 | return; | ||
| 2389 | } | ||
| 2390 | |||
| 2391 | if (create_enum_type) { | ||
| 2392 | // Now iterate again and populate the unspecified tag values | ||
| 2393 | uint32_t next_maybe_unoccupied_index = 0; | ||
| 2394 | |||
| 2395 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | ||
| 2396 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | ||
| 2397 | TypeUnionField *union_field = &union_type->data.unionation.fields[field_i]; | ||
| 2398 | AstNode *tag_value = field_node->data.struct_field.value; | ||
| 2399 | |||
| 2400 | if (tag_value == nullptr) { | ||
| 2401 | if (occupied_tag_values.size() == 0) { | ||
| 2402 | bigint_init_unsigned(&union_field->enum_field->value, next_maybe_unoccupied_index); | ||
| 2403 | next_maybe_unoccupied_index += 1; | ||
| 2404 | } else { | ||
| 2405 | BigInt proposed_value; | ||
| 2406 | for (;;) { | ||
| 2407 | bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index); | ||
| 2408 | next_maybe_unoccupied_index += 1; | ||
| 2409 | auto entry = occupied_tag_values.put_unique(proposed_value, field_node); | ||
| 2410 | if (entry != nullptr) { | ||
| 2411 | continue; | ||
| 2412 | } | ||
| 2413 | break; | ||
| 2414 | } | ||
| 2415 | bigint_init_bigint(&union_field->enum_field->value, &proposed_value); | ||
| 2416 | } | ||
| 2417 | } | ||
| 2418 | } | ||
| 2419 | } else if (enum_type_node != nullptr) { | ||
| 2420 | for (uint32_t i = 0; i < tag_type->data.enumeration.src_field_count; i += 1) { | ||
| 2421 | TypeEnumField *enum_field = &tag_type->data.enumeration.fields[i]; | ||
| 2422 | if (!covered_enum_fields[i]) { | ||
| 2423 | AstNode *enum_decl_node = tag_type->data.enumeration.decl_node; | ||
| 2424 | AstNode *field_node = enum_decl_node->data.container_decl.fields.at(i); | ||
| 2425 | ErrorMsg *msg = add_node_error(g, decl_node, | ||
| 2426 | buf_sprintf("enum field missing: '%s'", buf_ptr(enum_field->name))); | ||
| 2427 | add_error_note(g, msg, field_node, | ||
| 2428 | buf_sprintf("declared here")); | ||
| 2429 | union_type->data.unionation.is_invalid = true; | ||
| 2430 | } | ||
| 2431 | } | ||
| 2432 | } | ||
| 2433 | |||
| 2434 | if (create_enum_type) { | ||
| 2435 | ImportTableEntry *import = get_scope_import(scope); | ||
| 2436 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); | ||
| 2437 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); | ||
| 2438 | // TODO get a more accurate debug scope | ||
| 2439 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | ||
| 2440 | ZigLLVMFileToScope(import->di_file), buf_ptr(&tag_type->name), | ||
| 2441 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 2442 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, | ||
| 2443 | tag_type->di_type, ""); | ||
| 2444 | tag_type->di_type = tag_di_type; | ||
| 2445 | } | ||
| 2276 | 2446 | ||
| 2277 | union_type->data.unionation.zero_bits_loop_flag = false; | 2447 | union_type->data.unionation.zero_bits_loop_flag = false; |
| 2278 | union_type->data.unionation.gen_field_count = gen_field_index; | 2448 | union_type->data.unionation.gen_field_count = gen_field_index; |
| 2279 | union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !auto_layout)); | 2449 | union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !src_have_tag)); |
| 2280 | union_type->data.unionation.zero_bits_known = true; | 2450 | union_type->data.unionation.zero_bits_known = true; |
| 2281 | |||
| 2282 | // also compute abi_alignment | ||
| 2283 | if (!union_type->zero_bits) { | ||
| 2284 | union_type->data.unionation.abi_alignment = biggest_align_bytes; | ||
| 2285 | } | ||
| 2286 | } | 2451 | } |
| 2287 | 2452 | ||
| 2288 | static void get_fully_qualified_decl_name_internal(Buf *buf, Scope *scope, uint8_t sep) { | 2453 | static void get_fully_qualified_decl_name_internal(Buf *buf, Scope *scope, uint8_t sep) { |
| ... | @@ -2741,7 +2906,6 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt | ... | @@ -2741,7 +2906,6 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt |
| 2741 | case TypeTableEntryIdUnion: | 2906 | case TypeTableEntryIdUnion: |
| 2742 | case TypeTableEntryIdFn: | 2907 | case TypeTableEntryIdFn: |
| 2743 | case TypeTableEntryIdBoundFn: | 2908 | case TypeTableEntryIdBoundFn: |
| 2744 | case TypeTableEntryIdEnumTag: | ||
| 2745 | return type_entry; | 2909 | return type_entry; |
| 2746 | } | 2910 | } |
| 2747 | zig_unreachable(); | 2911 | zig_unreachable(); |
| ... | @@ -3158,13 +3322,37 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) { | ... | @@ -3158,13 +3322,37 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) { |
| 3158 | assert(type_entry->data.unionation.complete); | 3322 | assert(type_entry->data.unionation.complete); |
| 3159 | for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { | 3323 | for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { |
| 3160 | TypeUnionField *field = &type_entry->data.unionation.fields[i]; | 3324 | TypeUnionField *field = &type_entry->data.unionation.fields[i]; |
| 3161 | if (buf_eql_buf(field->name, name)) { | 3325 | if (buf_eql_buf(field->enum_field->name, name)) { |
| 3162 | return field; | 3326 | return field; |
| 3163 | } | 3327 | } |
| 3164 | } | 3328 | } |
| 3165 | return nullptr; | 3329 | return nullptr; |
| 3166 | } | 3330 | } |
| 3167 | 3331 | ||
| 3332 | TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) { | ||
| 3333 | assert(type_entry->id == TypeTableEntryIdUnion); | ||
| 3334 | assert(type_entry->data.unionation.complete); | ||
| 3335 | assert(type_entry->data.unionation.gen_tag_index != SIZE_MAX); | ||
| 3336 | for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { | ||
| 3337 | TypeUnionField *field = &type_entry->data.unionation.fields[i]; | ||
| 3338 | if (bigint_cmp(&field->enum_field->value, tag) == CmpEQ) { | ||
| 3339 | return field; | ||
| 3340 | } | ||
| 3341 | } | ||
| 3342 | return nullptr; | ||
| 3343 | } | ||
| 3344 | |||
| 3345 | TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag) { | ||
| 3346 | for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { | ||
| 3347 | TypeEnumField *field = &enum_type->data.enumeration.fields[i]; | ||
| 3348 | if (bigint_cmp(&field->value, tag) == CmpEQ) { | ||
| 3349 | return field; | ||
| 3350 | } | ||
| 3351 | } | ||
| 3352 | return nullptr; | ||
| 3353 | } | ||
| 3354 | |||
| 3355 | |||
| 3168 | static bool is_container(TypeTableEntry *type_entry) { | 3356 | static bool is_container(TypeTableEntry *type_entry) { |
| 3169 | switch (type_entry->id) { | 3357 | switch (type_entry->id) { |
| 3170 | case TypeTableEntryIdInvalid: | 3358 | case TypeTableEntryIdInvalid: |
| ... | @@ -3193,7 +3381,6 @@ static bool is_container(TypeTableEntry *type_entry) { | ... | @@ -3193,7 +3381,6 @@ static bool is_container(TypeTableEntry *type_entry) { |
| 3193 | case TypeTableEntryIdNamespace: | 3381 | case TypeTableEntryIdNamespace: |
| 3194 | case TypeTableEntryIdBlock: | 3382 | case TypeTableEntryIdBlock: |
| 3195 | case TypeTableEntryIdBoundFn: | 3383 | case TypeTableEntryIdBoundFn: |
| 3196 | case TypeTableEntryIdEnumTag: | ||
| 3197 | case TypeTableEntryIdArgTuple: | 3384 | case TypeTableEntryIdArgTuple: |
| 3198 | case TypeTableEntryIdOpaque: | 3385 | case TypeTableEntryIdOpaque: |
| 3199 | return false; | 3386 | return false; |
| ... | @@ -3244,7 +3431,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { | ... | @@ -3244,7 +3431,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { |
| 3244 | case TypeTableEntryIdBoundFn: | 3431 | case TypeTableEntryIdBoundFn: |
| 3245 | case TypeTableEntryIdInvalid: | 3432 | case TypeTableEntryIdInvalid: |
| 3246 | case TypeTableEntryIdVar: | 3433 | case TypeTableEntryIdVar: |
| 3247 | case TypeTableEntryIdEnumTag: | ||
| 3248 | case TypeTableEntryIdArgTuple: | 3434 | case TypeTableEntryIdArgTuple: |
| 3249 | case TypeTableEntryIdOpaque: | 3435 | case TypeTableEntryIdOpaque: |
| 3250 | zig_unreachable(); | 3436 | zig_unreachable(); |
| ... | @@ -3698,7 +3884,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { | ... | @@ -3698,7 +3884,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 3698 | case TypeTableEntryIdPointer: | 3884 | case TypeTableEntryIdPointer: |
| 3699 | case TypeTableEntryIdPureError: | 3885 | case TypeTableEntryIdPureError: |
| 3700 | case TypeTableEntryIdFn: | 3886 | case TypeTableEntryIdFn: |
| 3701 | case TypeTableEntryIdEnumTag: | 3887 | case TypeTableEntryIdEnum: |
| 3702 | return false; | 3888 | return false; |
| 3703 | case TypeTableEntryIdArray: | 3889 | case TypeTableEntryIdArray: |
| 3704 | case TypeTableEntryIdStruct: | 3890 | case TypeTableEntryIdStruct: |
| ... | @@ -3706,9 +3892,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { | ... | @@ -3706,9 +3892,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 3706 | return type_has_bits(type_entry); | 3892 | return type_has_bits(type_entry); |
| 3707 | case TypeTableEntryIdErrorUnion: | 3893 | case TypeTableEntryIdErrorUnion: |
| 3708 | return type_has_bits(type_entry->data.error.child_type); | 3894 | return type_has_bits(type_entry->data.error.child_type); |
| 3709 | case TypeTableEntryIdEnum: | ||
| 3710 | assert(type_entry->data.enumeration.complete); | ||
| 3711 | return type_entry->data.enumeration.gen_field_count != 0; | ||
| 3712 | case TypeTableEntryIdMaybe: | 3895 | case TypeTableEntryIdMaybe: |
| 3713 | return type_has_bits(type_entry->data.maybe.child_type) && | 3896 | return type_has_bits(type_entry->data.maybe.child_type) && |
| 3714 | type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer && | 3897 | type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer && |
| ... | @@ -3850,7 +4033,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -3850,7 +4033,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 3850 | return (uint32_t)4149439618; | 4033 | return (uint32_t)4149439618; |
| 3851 | case TypeTableEntryIdInt: | 4034 | case TypeTableEntryIdInt: |
| 3852 | case TypeTableEntryIdNumLitInt: | 4035 | case TypeTableEntryIdNumLitInt: |
| 3853 | case TypeTableEntryIdEnumTag: | ||
| 3854 | { | 4036 | { |
| 3855 | uint32_t result = 1331471175; | 4037 | uint32_t result = 1331471175; |
| 3856 | for (size_t i = 0; i < const_val->data.x_bigint.digit_count; i += 1) { | 4038 | for (size_t i = 0; i < const_val->data.x_bigint.digit_count; i += 1) { |
| ... | @@ -3859,6 +4041,15 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -3859,6 +4041,15 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 3859 | } | 4041 | } |
| 3860 | return result; | 4042 | return result; |
| 3861 | } | 4043 | } |
| 4044 | case TypeTableEntryIdEnum: | ||
| 4045 | { | ||
| 4046 | uint32_t result = 31643936; | ||
| 4047 | for (size_t i = 0; i < const_val->data.x_enum_tag.digit_count; i += 1) { | ||
| 4048 | uint64_t digit = bigint_ptr(&const_val->data.x_enum_tag)[i]; | ||
| 4049 | result ^= ((uint32_t)(digit >> 32)) ^ (uint32_t)(result); | ||
| 4050 | } | ||
| 4051 | return result; | ||
| 4052 | } | ||
| 3862 | case TypeTableEntryIdFloat: | 4053 | case TypeTableEntryIdFloat: |
| 3863 | switch (const_val->type->data.floating.bit_count) { | 4054 | switch (const_val->type->data.floating.bit_count) { |
| 3864 | case 32: | 4055 | case 32: |
| ... | @@ -3959,9 +4150,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -3959,9 +4150,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 3959 | case TypeTableEntryIdPureError: | 4150 | case TypeTableEntryIdPureError: |
| 3960 | // TODO better hashing algorithm | 4151 | // TODO better hashing algorithm |
| 3961 | return 2630160122; | 4152 | return 2630160122; |
| 3962 | case TypeTableEntryIdEnum: | ||
| 3963 | // TODO better hashing algorithm | ||
| 3964 | return 31643936; | ||
| 3965 | case TypeTableEntryIdFn: | 4153 | case TypeTableEntryIdFn: |
| 3966 | return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry); | 4154 | return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry); |
| 3967 | case TypeTableEntryIdNamespace: | 4155 | case TypeTableEntryIdNamespace: |
| ... | @@ -4094,7 +4282,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { | ... | @@ -4094,7 +4282,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { |
| 4094 | case TypeTableEntryIdInt: | 4282 | case TypeTableEntryIdInt: |
| 4095 | case TypeTableEntryIdFloat: | 4283 | case TypeTableEntryIdFloat: |
| 4096 | case TypeTableEntryIdPointer: | 4284 | case TypeTableEntryIdPointer: |
| 4097 | case TypeTableEntryIdEnumTag: | ||
| 4098 | case TypeTableEntryIdVoid: | 4285 | case TypeTableEntryIdVoid: |
| 4099 | case TypeTableEntryIdUnreachable: | 4286 | case TypeTableEntryIdUnreachable: |
| 4100 | return false; | 4287 | return false; |
| ... | @@ -4153,6 +4340,19 @@ ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) { | ... | @@ -4153,6 +4340,19 @@ ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) { |
| 4153 | return const_val; | 4340 | return const_val; |
| 4154 | } | 4341 | } |
| 4155 | 4342 | ||
| 4343 | void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint) { | ||
| 4344 | const_val->special = ConstValSpecialStatic; | ||
| 4345 | const_val->type = type; | ||
| 4346 | bigint_init_bigint(&const_val->data.x_bigint, bigint); | ||
| 4347 | } | ||
| 4348 | |||
| 4349 | ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint) { | ||
| 4350 | ConstExprValue *const_val = create_const_vals(1); | ||
| 4351 | init_const_bigint(const_val, type, bigint); | ||
| 4352 | return const_val; | ||
| 4353 | } | ||
| 4354 | |||
| 4355 | |||
| 4156 | void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) { | 4356 | void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) { |
| 4157 | const_val->special = ConstValSpecialStatic; | 4357 | const_val->special = ConstValSpecialStatic; |
| 4158 | const_val->type = type; | 4358 | const_val->type = type; |
| ... | @@ -4216,18 +4416,19 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) { | ... | @@ -4216,18 +4416,19 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) { |
| 4216 | return const_val; | 4416 | return const_val; |
| 4217 | } | 4417 | } |
| 4218 | 4418 | ||
| 4219 | void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag) { | 4419 | void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag) { |
| 4220 | const_val->special = ConstValSpecialStatic; | 4420 | const_val->special = ConstValSpecialStatic; |
| 4221 | const_val->type = type; | 4421 | const_val->type = type; |
| 4222 | const_val->data.x_enum.tag = tag; | 4422 | bigint_init_bigint(&const_val->data.x_enum_tag, tag); |
| 4223 | } | 4423 | } |
| 4224 | 4424 | ||
| 4225 | ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag) { | 4425 | ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag) { |
| 4226 | ConstExprValue *const_val = create_const_vals(1); | 4426 | ConstExprValue *const_val = create_const_vals(1); |
| 4227 | init_const_enum_tag(const_val, type, tag); | 4427 | init_const_enum(const_val, type, tag); |
| 4228 | return const_val; | 4428 | return const_val; |
| 4229 | } | 4429 | } |
| 4230 | 4430 | ||
| 4431 | |||
| 4231 | void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value) { | 4432 | void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value) { |
| 4232 | const_val->special = ConstValSpecialStatic; | 4433 | const_val->special = ConstValSpecialStatic; |
| 4233 | const_val->type = g->builtin_types.entry_bool; | 4434 | const_val->type = g->builtin_types.entry_bool; |
| ... | @@ -4426,19 +4627,22 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -4426,19 +4627,22 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 4426 | case TypeTableEntryIdOpaque: | 4627 | case TypeTableEntryIdOpaque: |
| 4427 | zig_unreachable(); | 4628 | zig_unreachable(); |
| 4428 | case TypeTableEntryIdEnum: | 4629 | case TypeTableEntryIdEnum: |
| 4429 | { | 4630 | return bigint_cmp(&a->data.x_enum_tag, &b->data.x_enum_tag) == CmpEQ; |
| 4430 | ConstEnumValue *enum1 = &a->data.x_enum; | 4631 | case TypeTableEntryIdUnion: { |
| 4431 | ConstEnumValue *enum2 = &b->data.x_enum; | 4632 | ConstUnionValue *union1 = &a->data.x_union; |
| 4432 | if (enum1->tag == enum2->tag) { | 4633 | ConstUnionValue *union2 = &b->data.x_union; |
| 4433 | TypeEnumField *enum_field = &a->type->data.enumeration.fields[enum1->tag]; | 4634 | |
| 4434 | if (type_has_bits(enum_field->type_entry)) { | 4635 | if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) { |
| 4435 | zig_panic("TODO const expr analyze enum special value for equality"); | 4636 | TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag); |
| 4436 | } else { | 4637 | assert(field != nullptr); |
| 4437 | return true; | 4638 | if (type_has_bits(field->type_entry)) { |
| 4438 | } | 4639 | zig_panic("TODO const expr analyze union field value for equality"); |
| 4640 | } else { | ||
| 4641 | return true; | ||
| 4439 | } | 4642 | } |
| 4440 | return false; | ||
| 4441 | } | 4643 | } |
| 4644 | return false; | ||
| 4645 | } | ||
| 4442 | case TypeTableEntryIdMetaType: | 4646 | case TypeTableEntryIdMetaType: |
| 4443 | return a->data.x_type == b->data.x_type; | 4647 | return a->data.x_type == b->data.x_type; |
| 4444 | case TypeTableEntryIdVoid: | 4648 | case TypeTableEntryIdVoid: |
| ... | @@ -4465,7 +4669,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -4465,7 +4669,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 4465 | return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ; | 4669 | return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ; |
| 4466 | case TypeTableEntryIdInt: | 4670 | case TypeTableEntryIdInt: |
| 4467 | case TypeTableEntryIdNumLitInt: | 4671 | case TypeTableEntryIdNumLitInt: |
| 4468 | case TypeTableEntryIdEnumTag: | ||
| 4469 | return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ; | 4672 | return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ; |
| 4470 | case TypeTableEntryIdPointer: | 4673 | case TypeTableEntryIdPointer: |
| 4471 | if (a->data.x_ptr.special != b->data.x_ptr.special) | 4674 | if (a->data.x_ptr.special != b->data.x_ptr.special) |
| ... | @@ -4519,8 +4722,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -4519,8 +4722,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 4519 | return false; | 4722 | return false; |
| 4520 | } | 4723 | } |
| 4521 | return true; | 4724 | return true; |
| 4522 | case TypeTableEntryIdUnion: | ||
| 4523 | zig_panic("TODO"); | ||
| 4524 | case TypeTableEntryIdUndefLit: | 4725 | case TypeTableEntryIdUndefLit: |
| 4525 | zig_panic("TODO"); | 4726 | zig_panic("TODO"); |
| 4526 | case TypeTableEntryIdNullLit: | 4727 | case TypeTableEntryIdNullLit: |
| ... | @@ -4664,7 +4865,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -4664,7 +4865,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 4664 | buf_appendf(buf, "%s", buf_ptr(&const_val->data.x_type->name)); | 4865 | buf_appendf(buf, "%s", buf_ptr(&const_val->data.x_type->name)); |
| 4665 | return; | 4866 | return; |
| 4666 | case TypeTableEntryIdUnreachable: | 4867 | case TypeTableEntryIdUnreachable: |
| 4667 | buf_appendf(buf, "@unreachable()"); | 4868 | buf_appendf(buf, "unreachable"); |
| 4668 | return; | 4869 | return; |
| 4669 | case TypeTableEntryIdBool: | 4870 | case TypeTableEntryIdBool: |
| 4670 | { | 4871 | { |
| ... | @@ -4794,7 +4995,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -4794,7 +4995,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 4794 | } | 4995 | } |
| 4795 | case TypeTableEntryIdEnum: | 4996 | case TypeTableEntryIdEnum: |
| 4796 | { | 4997 | { |
| 4797 | buf_appendf(buf, "(enum %s constant)", buf_ptr(&type_entry->name)); | 4998 | TypeEnumField *field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum_tag); |
| 4999 | buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(field->name)); | ||
| 4798 | return; | 5000 | return; |
| 4799 | } | 5001 | } |
| 4800 | case TypeTableEntryIdErrorUnion: | 5002 | case TypeTableEntryIdErrorUnion: |
| ... | @@ -4812,14 +5014,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -4812,14 +5014,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 4812 | buf_appendf(buf, "(pure error constant)"); | 5014 | buf_appendf(buf, "(pure error constant)"); |
| 4813 | return; | 5015 | return; |
| 4814 | } | 5016 | } |
| 4815 | case TypeTableEntryIdEnumTag: | ||
| 4816 | { | ||
| 4817 | TypeTableEntry *enum_type = type_entry->data.enum_tag.enum_type; | ||
| 4818 | size_t field_index = bigint_as_unsigned(&const_val->data.x_bigint); | ||
| 4819 | TypeEnumField *field = &enum_type->data.enumeration.fields[field_index]; | ||
| 4820 | buf_appendf(buf, "%s.%s", buf_ptr(&enum_type->name), buf_ptr(field->name)); | ||
| 4821 | return; | ||
| 4822 | } | ||
| 4823 | case TypeTableEntryIdArgTuple: | 5017 | case TypeTableEntryIdArgTuple: |
| 4824 | { | 5018 | { |
| 4825 | buf_appendf(buf, "(args value)"); | 5019 | buf_appendf(buf, "(args value)"); |
| ... | @@ -4830,11 +5024,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -4830,11 +5024,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 4830 | } | 5024 | } |
| 4831 | 5025 | ||
| 4832 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { | 5026 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { |
| 4833 | assert(size_in_bits > 0); | ||
| 4834 | |||
| 4835 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); | 5027 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 4836 | entry->is_copyable = true; | 5028 | entry->is_copyable = true; |
| 4837 | entry->type_ref = LLVMIntType(size_in_bits); | 5029 | entry->type_ref = (size_in_bits == 0) ? LLVMVoidType() : LLVMIntType(size_in_bits); |
| 5030 | entry->zero_bits = (size_in_bits == 0); | ||
| 4838 | 5031 | ||
| 4839 | const char u_or_i = is_signed ? 'i' : 'u'; | 5032 | const char u_or_i = is_signed ? 'i' : 'u'; |
| 4840 | buf_resize(&entry->name, 0); | 5033 | buf_resize(&entry->name, 0); |
| ... | @@ -4855,7 +5048,8 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) | ... | @@ -4855,7 +5048,8 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) |
| 4855 | } | 5048 | } |
| 4856 | } | 5049 | } |
| 4857 | 5050 | ||
| 4858 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | 5051 | uint64_t debug_size_in_bits = (size_in_bits == 0) ? |
| 5052 | 0 : (8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref)); | ||
| 4859 | entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), debug_size_in_bits, dwarf_tag); | 5053 | entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), debug_size_in_bits, dwarf_tag); |
| 4860 | entry->data.integral.is_signed = is_signed; | 5054 | entry->data.integral.is_signed = is_signed; |
| 4861 | entry->data.integral.bit_count = size_in_bits; | 5055 | entry->data.integral.bit_count = size_in_bits; |
| ... | @@ -4881,7 +5075,6 @@ uint32_t type_id_hash(TypeId x) { | ... | @@ -4881,7 +5075,6 @@ uint32_t type_id_hash(TypeId x) { |
| 4881 | case TypeTableEntryIdErrorUnion: | 5075 | case TypeTableEntryIdErrorUnion: |
| 4882 | case TypeTableEntryIdPureError: | 5076 | case TypeTableEntryIdPureError: |
| 4883 | case TypeTableEntryIdEnum: | 5077 | case TypeTableEntryIdEnum: |
| 4884 | case TypeTableEntryIdEnumTag: | ||
| 4885 | case TypeTableEntryIdUnion: | 5078 | case TypeTableEntryIdUnion: |
| 4886 | case TypeTableEntryIdFn: | 5079 | case TypeTableEntryIdFn: |
| 4887 | case TypeTableEntryIdNamespace: | 5080 | case TypeTableEntryIdNamespace: |
| ... | @@ -4926,7 +5119,6 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -4926,7 +5119,6 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 4926 | case TypeTableEntryIdErrorUnion: | 5119 | case TypeTableEntryIdErrorUnion: |
| 4927 | case TypeTableEntryIdPureError: | 5120 | case TypeTableEntryIdPureError: |
| 4928 | case TypeTableEntryIdEnum: | 5121 | case TypeTableEntryIdEnum: |
| 4929 | case TypeTableEntryIdEnumTag: | ||
| 4930 | case TypeTableEntryIdUnion: | 5122 | case TypeTableEntryIdUnion: |
| 4931 | case TypeTableEntryIdFn: | 5123 | case TypeTableEntryIdFn: |
| 4932 | case TypeTableEntryIdNamespace: | 5124 | case TypeTableEntryIdNamespace: |
| ... | @@ -5041,7 +5233,6 @@ static const TypeTableEntryId all_type_ids[] = { | ... | @@ -5041,7 +5233,6 @@ static const TypeTableEntryId all_type_ids[] = { |
| 5041 | TypeTableEntryIdErrorUnion, | 5233 | TypeTableEntryIdErrorUnion, |
| 5042 | TypeTableEntryIdPureError, | 5234 | TypeTableEntryIdPureError, |
| 5043 | TypeTableEntryIdEnum, | 5235 | TypeTableEntryIdEnum, |
| 5044 | TypeTableEntryIdEnumTag, | ||
| 5045 | TypeTableEntryIdUnion, | 5236 | TypeTableEntryIdUnion, |
| 5046 | TypeTableEntryIdFn, | 5237 | TypeTableEntryIdFn, |
| 5047 | TypeTableEntryIdNamespace, | 5238 | TypeTableEntryIdNamespace, |
| ... | @@ -5099,22 +5290,20 @@ size_t type_id_index(TypeTableEntryId id) { | ... | @@ -5099,22 +5290,20 @@ size_t type_id_index(TypeTableEntryId id) { |
| 5099 | return 15; | 5290 | return 15; |
| 5100 | case TypeTableEntryIdEnum: | 5291 | case TypeTableEntryIdEnum: |
| 5101 | return 16; | 5292 | return 16; |
| 5102 | case TypeTableEntryIdEnumTag: | ||
| 5103 | return 17; | ||
| 5104 | case TypeTableEntryIdUnion: | 5293 | case TypeTableEntryIdUnion: |
| 5105 | return 18; | 5294 | return 17; |
| 5106 | case TypeTableEntryIdFn: | 5295 | case TypeTableEntryIdFn: |
| 5107 | return 19; | 5296 | return 18; |
| 5108 | case TypeTableEntryIdNamespace: | 5297 | case TypeTableEntryIdNamespace: |
| 5109 | return 20; | 5298 | return 19; |
| 5110 | case TypeTableEntryIdBlock: | 5299 | case TypeTableEntryIdBlock: |
| 5111 | return 21; | 5300 | return 20; |
| 5112 | case TypeTableEntryIdBoundFn: | 5301 | case TypeTableEntryIdBoundFn: |
| 5113 | return 22; | 5302 | return 21; |
| 5114 | case TypeTableEntryIdArgTuple: | 5303 | case TypeTableEntryIdArgTuple: |
| 5115 | return 23; | 5304 | return 22; |
| 5116 | case TypeTableEntryIdOpaque: | 5305 | case TypeTableEntryIdOpaque: |
| 5117 | return 24; | 5306 | return 23; |
| 5118 | } | 5307 | } |
| 5119 | zig_unreachable(); | 5308 | zig_unreachable(); |
| 5120 | } | 5309 | } |
| ... | @@ -5158,8 +5347,6 @@ const char *type_id_name(TypeTableEntryId id) { | ... | @@ -5158,8 +5347,6 @@ const char *type_id_name(TypeTableEntryId id) { |
| 5158 | return "Error"; | 5347 | return "Error"; |
| 5159 | case TypeTableEntryIdEnum: | 5348 | case TypeTableEntryIdEnum: |
| 5160 | return "Enum"; | 5349 | return "Enum"; |
| 5161 | case TypeTableEntryIdEnumTag: | ||
| 5162 | return "EnumTag"; | ||
| 5163 | case TypeTableEntryIdUnion: | 5350 | case TypeTableEntryIdUnion: |
| 5164 | return "Union"; | 5351 | return "Union"; |
| 5165 | case TypeTableEntryIdFn: | 5352 | case TypeTableEntryIdFn: |
| ... | @@ -5226,9 +5413,6 @@ uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) { | ... | @@ -5226,9 +5413,6 @@ uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) { |
| 5226 | if (type_entry->id == TypeTableEntryIdStruct) { | 5413 | if (type_entry->id == TypeTableEntryIdStruct) { |
| 5227 | assert(type_entry->data.structure.abi_alignment != 0); | 5414 | assert(type_entry->data.structure.abi_alignment != 0); |
| 5228 | return type_entry->data.structure.abi_alignment; | 5415 | return type_entry->data.structure.abi_alignment; |
| 5229 | } else if (type_entry->id == TypeTableEntryIdEnum) { | ||
| 5230 | assert(type_entry->data.enumeration.abi_alignment != 0); | ||
| 5231 | return type_entry->data.enumeration.abi_alignment; | ||
| 5232 | } else if (type_entry->id == TypeTableEntryIdUnion) { | 5416 | } else if (type_entry->id == TypeTableEntryIdUnion) { |
| 5233 | assert(type_entry->data.unionation.abi_alignment != 0); | 5417 | assert(type_entry->data.unionation.abi_alignment != 0); |
| 5234 | return type_entry->data.unionation.abi_alignment; | 5418 | return type_entry->data.unionation.abi_alignment; |
src/analyze.hpp+8-3| ... | @@ -64,6 +64,9 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name); | ... | @@ -64,6 +64,9 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name); |
| 64 | ScopeDecls *get_container_scope(TypeTableEntry *type_entry); | 64 | ScopeDecls *get_container_scope(TypeTableEntry *type_entry); |
| 65 | TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name); | 65 | TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name); |
| 66 | TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name); | 66 | TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name); |
| 67 | TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag); | ||
| 68 | TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag); | ||
| 69 | |||
| 67 | bool is_container_ref(TypeTableEntry *type_entry); | 70 | bool is_container_ref(TypeTableEntry *type_entry); |
| 68 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); | 71 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); |
| 69 | void scan_import(CodeGen *g, ImportTableEntry *import); | 72 | void scan_import(CodeGen *g, ImportTableEntry *import); |
| ... | @@ -109,6 +112,9 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str); | ... | @@ -109,6 +112,9 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str); |
| 109 | void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str); | 112 | void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str); |
| 110 | ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str); | 113 | ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str); |
| 111 | 114 | ||
| 115 | void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint); | ||
| 116 | ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint); | ||
| 117 | |||
| 112 | void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative); | 118 | void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative); |
| 113 | ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative); | 119 | ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative); |
| 114 | 120 | ||
| ... | @@ -121,8 +127,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x); | ... | @@ -121,8 +127,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x); |
| 121 | void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value); | 127 | void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value); |
| 122 | ConstExprValue *create_const_float(TypeTableEntry *type, double value); | 128 | ConstExprValue *create_const_float(TypeTableEntry *type, double value); |
| 123 | 129 | ||
| 124 | void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag); | 130 | void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag); |
| 125 | ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag); | 131 | ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag); |
| 126 | 132 | ||
| 127 | void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value); | 133 | void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value); |
| 128 | ConstExprValue *create_const_bool(CodeGen *g, bool value); | 134 | ConstExprValue *create_const_bool(CodeGen *g, bool value); |
| ... | @@ -158,7 +164,6 @@ ConstExprValue *create_const_vals(size_t count); | ... | @@ -158,7 +164,6 @@ ConstExprValue *create_const_vals(size_t count); |
| 158 | 164 | ||
| 159 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); | 165 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); |
| 160 | ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value); | 166 | ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value); |
| 161 | TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type); | ||
| 162 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val); | 167 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val); |
| 163 | void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value); | 168 | void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value); |
| 164 | 169 |
src/ast_render.cpp+18-1| ... | @@ -660,7 +660,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -660,7 +660,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 660 | { | 660 | { |
| 661 | const char *layout_str = layout_string(node->data.container_decl.layout); | 661 | const char *layout_str = layout_string(node->data.container_decl.layout); |
| 662 | const char *container_str = container_string(node->data.container_decl.kind); | 662 | const char *container_str = container_string(node->data.container_decl.kind); |
| 663 | fprintf(ar->f, "%s%s {\n", layout_str, container_str); | 663 | fprintf(ar->f, "%s%s", layout_str, container_str); |
| 664 | if (node->data.container_decl.auto_enum) { | ||
| 665 | fprintf(ar->f, "(enum"); | ||
| 666 | } | ||
| 667 | if (node->data.container_decl.init_arg_expr != nullptr) { | ||
| 668 | fprintf(ar->f, "("); | ||
| 669 | render_node_grouped(ar, node->data.container_decl.init_arg_expr); | ||
| 670 | fprintf(ar->f, ")"); | ||
| 671 | } | ||
| 672 | if (node->data.container_decl.auto_enum) { | ||
| 673 | fprintf(ar->f, ")"); | ||
| 674 | } | ||
| 675 | |||
| 676 | fprintf(ar->f, " {\n"); | ||
| 664 | ar->indent += ar->indent_size; | 677 | ar->indent += ar->indent_size; |
| 665 | for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) { | 678 | for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) { |
| 666 | AstNode *field_node = node->data.container_decl.fields.at(field_i); | 679 | AstNode *field_node = node->data.container_decl.fields.at(field_i); |
| ... | @@ -671,6 +684,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -671,6 +684,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 671 | fprintf(ar->f, ": "); | 684 | fprintf(ar->f, ": "); |
| 672 | render_node_grouped(ar, field_node->data.struct_field.type); | 685 | render_node_grouped(ar, field_node->data.struct_field.type); |
| 673 | } | 686 | } |
| 687 | if (field_node->data.struct_field.value != nullptr) { | ||
| 688 | fprintf(ar->f, "= "); | ||
| 689 | render_node_grouped(ar, field_node->data.struct_field.value); | ||
| 690 | } | ||
| 674 | fprintf(ar->f, ",\n"); | 691 | fprintf(ar->f, ",\n"); |
| 675 | } | 692 | } |
| 676 | 693 |
src/bigint.cpp+32| ... | @@ -1224,3 +1224,35 @@ Cmp bigint_cmp_zero(const BigInt *op) { | ... | @@ -1224,3 +1224,35 @@ Cmp bigint_cmp_zero(const BigInt *op) { |
| 1224 | } | 1224 | } |
| 1225 | return op->is_negative ? CmpLT : CmpGT; | 1225 | return op->is_negative ? CmpLT : CmpGT; |
| 1226 | } | 1226 | } |
| 1227 | |||
| 1228 | uint32_t bigint_hash(BigInt x) { | ||
| 1229 | if (x.digit_count == 0) { | ||
| 1230 | return 0; | ||
| 1231 | } else { | ||
| 1232 | return bigint_ptr(&x)[0]; | ||
| 1233 | } | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | bool bigint_eql(BigInt a, BigInt b) { | ||
| 1237 | return bigint_cmp(&a, &b) == CmpEQ; | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | void bigint_incr(BigInt *x) { | ||
| 1241 | if (x->digit_count == 0) { | ||
| 1242 | bigint_init_unsigned(x, 1); | ||
| 1243 | return; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | if (x->digit_count == 1 && x->data.digit != UINT64_MAX) { | ||
| 1247 | x->data.digit += 1; | ||
| 1248 | return; | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | BigInt copy; | ||
| 1252 | bigint_init_bigint(&copy, x); | ||
| 1253 | |||
| 1254 | BigInt one; | ||
| 1255 | bigint_init_unsigned(&one, 1); | ||
| 1256 | |||
| 1257 | bigint_add(x, &copy, &one); | ||
| 1258 | } |
src/bigint.hpp+5| ... | @@ -88,6 +88,11 @@ size_t bigint_bits_needed(const BigInt *op); | ... | @@ -88,6 +88,11 @@ size_t bigint_bits_needed(const BigInt *op); |
| 88 | // convenience functions | 88 | // convenience functions |
| 89 | Cmp bigint_cmp_zero(const BigInt *op); | 89 | Cmp bigint_cmp_zero(const BigInt *op); |
| 90 | 90 | ||
| 91 | void bigint_incr(BigInt *value); | ||
| 92 | |||
| 91 | bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result); | 93 | bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result); |
| 92 | 94 | ||
| 95 | uint32_t bigint_hash(BigInt x); | ||
| 96 | bool bigint_eql(BigInt a, BigInt b); | ||
| 97 | |||
| 93 | #endif | 98 | #endif |
src/codegen.cpp+105-180| ... | @@ -1362,8 +1362,12 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) { | ... | @@ -1362,8 +1362,12 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) { |
| 1362 | if (bigint->digit_count == 0) { | 1362 | if (bigint->digit_count == 0) { |
| 1363 | return LLVMConstNull(type_ref); | 1363 | return LLVMConstNull(type_ref); |
| 1364 | } | 1364 | } |
| 1365 | LLVMValueRef unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref, | 1365 | LLVMValueRef unsigned_val; |
| 1366 | bigint->digit_count, bigint_ptr(bigint)); | 1366 | if (bigint->digit_count == 1) { |
| 1367 | unsigned_val = LLVMConstInt(type_ref, bigint_ptr(bigint)[0], false); | ||
| 1368 | } else { | ||
| 1369 | unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref, bigint->digit_count, bigint_ptr(bigint)); | ||
| 1370 | } | ||
| 1367 | if (bigint->is_negative) { | 1371 | if (bigint->is_negative) { |
| 1368 | return LLVMConstNeg(unsigned_val); | 1372 | return LLVMConstNeg(unsigned_val); |
| 1369 | } else { | 1373 | } else { |
| ... | @@ -1627,12 +1631,8 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, | ... | @@ -1627,12 +1631,8 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 1627 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed); | 1631 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed); |
| 1628 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); | 1632 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); |
| 1629 | } else if (type_entry->id == TypeTableEntryIdEnum) { | 1633 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 1630 | if (type_entry->data.enumeration.gen_field_count == 0) { | 1634 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); |
| 1631 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); | 1635 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); |
| 1632 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); | ||
| 1633 | } else { | ||
| 1634 | zig_unreachable(); | ||
| 1635 | } | ||
| 1636 | } else if (type_entry->id == TypeTableEntryIdPureError || | 1636 | } else if (type_entry->id == TypeTableEntryIdPureError || |
| 1637 | type_entry->id == TypeTableEntryIdPointer || | 1637 | type_entry->id == TypeTableEntryIdPointer || |
| 1638 | type_entry->id == TypeTableEntryIdBool) | 1638 | type_entry->id == TypeTableEntryIdBool) |
| ... | @@ -1916,9 +1916,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa | ... | @@ -1916,9 +1916,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa |
| 1916 | // enum_tag to the underlying int type | 1916 | // enum_tag to the underlying int type |
| 1917 | TypeTableEntry *int_type; | 1917 | TypeTableEntry *int_type; |
| 1918 | if (actual_type->id == TypeTableEntryIdEnum) { | 1918 | if (actual_type->id == TypeTableEntryIdEnum) { |
| 1919 | TypeTableEntry *tag_type = actual_type->data.enumeration.tag_type; | 1919 | int_type = actual_type->data.enumeration.tag_int_type; |
| 1920 | assert(tag_type->id == TypeTableEntryIdEnumTag); | ||
| 1921 | int_type = tag_type->data.enum_tag.int_type; | ||
| 1922 | } else { | 1920 | } else { |
| 1923 | int_type = actual_type; | 1921 | int_type = actual_type; |
| 1924 | } | 1922 | } |
| ... | @@ -1942,19 +1940,11 @@ static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, I | ... | @@ -1942,19 +1940,11 @@ static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, I |
| 1942 | static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) { | 1940 | static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) { |
| 1943 | TypeTableEntry *wanted_type = instruction->base.value.type; | 1941 | TypeTableEntry *wanted_type = instruction->base.value.type; |
| 1944 | assert(wanted_type->id == TypeTableEntryIdEnum); | 1942 | assert(wanted_type->id == TypeTableEntryIdEnum); |
| 1945 | TypeTableEntry *tag_type = wanted_type->data.enumeration.tag_type; | 1943 | TypeTableEntry *tag_int_type = wanted_type->data.enumeration.tag_int_type; |
| 1946 | TypeTableEntry *wanted_int_type; | ||
| 1947 | if (tag_type->id == TypeTableEntryIdEnumTag) { | ||
| 1948 | wanted_int_type = tag_type->data.enum_tag.int_type; | ||
| 1949 | } else if (tag_type->id == TypeTableEntryIdInt) { | ||
| 1950 | wanted_int_type = tag_type; | ||
| 1951 | } else { | ||
| 1952 | zig_unreachable(); | ||
| 1953 | } | ||
| 1954 | 1944 | ||
| 1955 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); | 1945 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 1956 | return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base), | 1946 | return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base), |
| 1957 | instruction->target->value.type, wanted_int_type, target_val); | 1947 | instruction->target->value.type, tag_int_type, target_val); |
| 1958 | } | 1948 | } |
| 1959 | 1949 | ||
| 1960 | static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) { | 1950 | static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) { |
| ... | @@ -2374,27 +2364,6 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa | ... | @@ -2374,27 +2364,6 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa |
| 2374 | return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); | 2364 | return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); |
| 2375 | } | 2365 | } |
| 2376 | 2366 | ||
| 2377 | static LLVMValueRef ir_render_enum_field_ptr(CodeGen *g, IrExecutable *executable, | ||
| 2378 | IrInstructionEnumFieldPtr *instruction) | ||
| 2379 | { | ||
| 2380 | TypeTableEntry *enum_ptr_type = instruction->enum_ptr->value.type; | ||
| 2381 | assert(enum_ptr_type->id == TypeTableEntryIdPointer); | ||
| 2382 | TypeTableEntry *enum_type = enum_ptr_type->data.pointer.child_type; | ||
| 2383 | assert(enum_type->id == TypeTableEntryIdEnum); | ||
| 2384 | |||
| 2385 | TypeEnumField *field = instruction->field; | ||
| 2386 | |||
| 2387 | if (!type_has_bits(field->type_entry)) | ||
| 2388 | return nullptr; | ||
| 2389 | |||
| 2390 | LLVMValueRef enum_ptr = ir_llvm_value(g, instruction->enum_ptr); | ||
| 2391 | LLVMTypeRef field_type_ref = LLVMPointerType(field->type_entry->type_ref, 0); | ||
| 2392 | LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, enum_ptr, enum_type->data.enumeration.gen_union_index, ""); | ||
| 2393 | LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); | ||
| 2394 | |||
| 2395 | return bitcasted_union_field_ptr; | ||
| 2396 | } | ||
| 2397 | |||
| 2398 | static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable, | 2367 | static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable, |
| 2399 | IrInstructionUnionFieldPtr *instruction) | 2368 | IrInstructionUnionFieldPtr *instruction) |
| 2400 | { | 2369 | { |
| ... | @@ -2420,9 +2389,10 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab | ... | @@ -2420,9 +2389,10 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab |
| 2420 | if (ir_want_debug_safety(g, &instruction->base)) { | 2389 | if (ir_want_debug_safety(g, &instruction->base)) { |
| 2421 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, ""); | 2390 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, ""); |
| 2422 | LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, ""); | 2391 | LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, ""); |
| 2423 | LLVMValueRef expected_tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref, | ||
| 2424 | field->value, false); | ||
| 2425 | 2392 | ||
| 2393 | |||
| 2394 | LLVMValueRef expected_tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref, | ||
| 2395 | &field->enum_field->value); | ||
| 2426 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk"); | 2396 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk"); |
| 2427 | LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail"); | 2397 | LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail"); |
| 2428 | LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, ""); | 2398 | LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, ""); |
| ... | @@ -2747,21 +2717,21 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -2747,21 +2717,21 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI |
| 2747 | } | 2717 | } |
| 2748 | 2718 | ||
| 2749 | static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable, | 2719 | static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable, |
| 2750 | IrInstructionEnumTagName *instruction) | 2720 | IrInstructionTagName *instruction) |
| 2751 | { | 2721 | { |
| 2752 | TypeTableEntry *enum_tag_type = instruction->target->value.type; | 2722 | TypeTableEntry *enum_type = instruction->target->value.type; |
| 2753 | assert(enum_tag_type->data.enum_tag.generate_name_table); | 2723 | assert(enum_type->id == TypeTableEntryIdEnum); |
| 2724 | assert(enum_type->data.enumeration.generate_name_table); | ||
| 2754 | 2725 | ||
| 2726 | TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type; | ||
| 2755 | LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); | 2727 | LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); |
| 2756 | if (ir_want_debug_safety(g, &instruction->base)) { | 2728 | if (ir_want_debug_safety(g, &instruction->base)) { |
| 2757 | TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type; | ||
| 2758 | size_t field_count = enum_type->data.enumeration.src_field_count; | 2729 | size_t field_count = enum_type->data.enumeration.src_field_count; |
| 2759 | 2730 | ||
| 2760 | // if the field_count can't fit in the bits of the enum_tag_type, then it can't possibly | 2731 | // if the field_count can't fit in the bits of the enum_type, then it can't possibly |
| 2761 | // be the wrong value | 2732 | // be the wrong value |
| 2762 | BigInt field_bi; | 2733 | BigInt field_bi; |
| 2763 | bigint_init_unsigned(&field_bi, field_count); | 2734 | bigint_init_unsigned(&field_bi, field_count); |
| 2764 | TypeTableEntry *tag_int_type = enum_tag_type->data.enum_tag.int_type; | ||
| 2765 | if (bigint_fits_in_bits(&field_bi, tag_int_type->data.integral.bit_count, false)) { | 2735 | if (bigint_fits_in_bits(&field_bi, tag_int_type->data.integral.bit_count, false)) { |
| 2766 | LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(enum_tag_value), field_count, false); | 2736 | LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(enum_tag_value), field_count, false); |
| 2767 | add_bounds_check(g, enum_tag_value, LLVMIntEQ, nullptr, LLVMIntULT, end_val); | 2737 | add_bounds_check(g, enum_tag_value, LLVMIntEQ, nullptr, LLVMIntULT, end_val); |
| ... | @@ -2770,10 +2740,10 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable | ... | @@ -2770,10 +2740,10 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable |
| 2770 | 2740 | ||
| 2771 | LLVMValueRef indices[] = { | 2741 | LLVMValueRef indices[] = { |
| 2772 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), | 2742 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), |
| 2773 | gen_widen_or_shorten(g, false, enum_tag_type->data.enum_tag.int_type, | 2743 | gen_widen_or_shorten(g, false, tag_int_type, |
| 2774 | g->builtin_types.entry_usize, enum_tag_value), | 2744 | g->builtin_types.entry_usize, enum_tag_value), |
| 2775 | }; | 2745 | }; |
| 2776 | return LLVMBuildInBoundsGEP(g->builder, enum_tag_type->data.enum_tag.name_table, indices, 2, ""); | 2746 | return LLVMBuildInBoundsGEP(g->builder, enum_type->data.enumeration.name_table, indices, 2, ""); |
| 2777 | } | 2747 | } |
| 2778 | 2748 | ||
| 2779 | static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable, | 2749 | static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable, |
| ... | @@ -3347,48 +3317,24 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa | ... | @@ -3347,48 +3317,24 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa |
| 3347 | return instruction->tmp_ptr; | 3317 | return instruction->tmp_ptr; |
| 3348 | } | 3318 | } |
| 3349 | 3319 | ||
| 3350 | static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrInstructionEnumTag *instruction) { | 3320 | static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) { |
| 3351 | TypeTableEntry *enum_type = instruction->value->value.type; | 3321 | TypeTableEntry *union_type = instruction->value->value.type; |
| 3352 | TypeTableEntry *tag_type = enum_type->data.enumeration.tag_type; | 3322 | assert(union_type->data.unionation.gen_tag_index != SIZE_MAX); |
| 3323 | |||
| 3324 | TypeTableEntry *tag_type = union_type->data.unionation.tag_type; | ||
| 3353 | if (!type_has_bits(tag_type)) | 3325 | if (!type_has_bits(tag_type)) |
| 3354 | return nullptr; | 3326 | return nullptr; |
| 3355 | 3327 | ||
| 3356 | LLVMValueRef enum_val = ir_llvm_value(g, instruction->value); | 3328 | LLVMValueRef union_val = ir_llvm_value(g, instruction->value); |
| 3357 | if (enum_type->data.enumeration.gen_field_count == 0) | 3329 | if (union_type->data.unionation.gen_field_count == 0) |
| 3358 | return enum_val; | 3330 | return union_val; |
| 3359 | 3331 | ||
| 3360 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, enum_val, enum_type->data.enumeration.gen_tag_index, ""); | 3332 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_val, |
| 3333 | union_type->data.unionation.gen_tag_index, ""); | ||
| 3361 | TypeTableEntry *ptr_type = get_pointer_to_type(g, tag_type, false); | 3334 | TypeTableEntry *ptr_type = get_pointer_to_type(g, tag_type, false); |
| 3362 | return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); | 3335 | return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); |
| 3363 | } | 3336 | } |
| 3364 | 3337 | ||
| 3365 | static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) { | ||
| 3366 | TypeTableEntry *enum_type = instruction->enum_type; | ||
| 3367 | uint32_t value = instruction->field->value; | ||
| 3368 | LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref; | ||
| 3369 | LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false); | ||
| 3370 | |||
| 3371 | if (enum_type->data.enumeration.gen_field_count == 0) | ||
| 3372 | return tag_value; | ||
| 3373 | |||
| 3374 | LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr; | ||
| 3375 | |||
| 3376 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_type->data.enumeration.gen_tag_index, ""); | ||
| 3377 | gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); | ||
| 3378 | |||
| 3379 | TypeTableEntry *union_val_type = instruction->field->type_entry; | ||
| 3380 | if (type_has_bits(union_val_type)) { | ||
| 3381 | LLVMValueRef new_union_val = ir_llvm_value(g, instruction->init_value); | ||
| 3382 | LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_type->data.enumeration.gen_union_index, ""); | ||
| 3383 | LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, | ||
| 3384 | LLVMPointerType(union_val_type->type_ref, 0), ""); | ||
| 3385 | |||
| 3386 | gen_assign_raw(g, bitcasted_union_field_ptr, get_pointer_to_type(g, union_val_type, false), new_union_val); | ||
| 3387 | } | ||
| 3388 | |||
| 3389 | return tmp_struct_ptr; | ||
| 3390 | } | ||
| 3391 | |||
| 3392 | static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) { | 3338 | static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) { |
| 3393 | for (size_t i = 0; i < instruction->field_count; i += 1) { | 3339 | for (size_t i = 0; i < instruction->field_count; i += 1) { |
| 3394 | IrInstructionStructInitField *field = &instruction->fields[i]; | 3340 | IrInstructionStructInitField *field = &instruction->fields[i]; |
| ... | @@ -3429,8 +3375,9 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I | ... | @@ -3429,8 +3375,9 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I |
| 3429 | if (union_type->data.unionation.gen_tag_index != SIZE_MAX) { | 3375 | if (union_type->data.unionation.gen_tag_index != SIZE_MAX) { |
| 3430 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, | 3376 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, |
| 3431 | union_type->data.unionation.gen_tag_index, ""); | 3377 | union_type->data.unionation.gen_tag_index, ""); |
| 3432 | LLVMValueRef tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref, | 3378 | |
| 3433 | type_union_field->value, false); | 3379 | LLVMValueRef tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref, |
| 3380 | &type_union_field->enum_field->value); | ||
| 3434 | gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); | 3381 | gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); |
| 3435 | 3382 | ||
| 3436 | uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, | 3383 | uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, |
| ... | @@ -3537,6 +3484,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3537,6 +3484,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3537 | case IrInstructionIdOpaqueType: | 3484 | case IrInstructionIdOpaqueType: |
| 3538 | case IrInstructionIdSetAlignStack: | 3485 | case IrInstructionIdSetAlignStack: |
| 3539 | case IrInstructionIdArgType: | 3486 | case IrInstructionIdArgType: |
| 3487 | case IrInstructionIdTagType: | ||
| 3540 | zig_unreachable(); | 3488 | zig_unreachable(); |
| 3541 | case IrInstructionIdReturn: | 3489 | case IrInstructionIdReturn: |
| 3542 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); | 3490 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| ... | @@ -3566,8 +3514,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3566,8 +3514,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3566 | return ir_render_call(g, executable, (IrInstructionCall *)instruction); | 3514 | return ir_render_call(g, executable, (IrInstructionCall *)instruction); |
| 3567 | case IrInstructionIdStructFieldPtr: | 3515 | case IrInstructionIdStructFieldPtr: |
| 3568 | return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction); | 3516 | return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction); |
| 3569 | case IrInstructionIdEnumFieldPtr: | ||
| 3570 | return ir_render_enum_field_ptr(g, executable, (IrInstructionEnumFieldPtr *)instruction); | ||
| 3571 | case IrInstructionIdUnionFieldPtr: | 3517 | case IrInstructionIdUnionFieldPtr: |
| 3572 | return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction); | 3518 | return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction); |
| 3573 | case IrInstructionIdAsm: | 3519 | case IrInstructionIdAsm: |
| ... | @@ -3622,10 +3568,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3622,10 +3568,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3622 | return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction); | 3568 | return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction); |
| 3623 | case IrInstructionIdErrWrapPayload: | 3569 | case IrInstructionIdErrWrapPayload: |
| 3624 | return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction); | 3570 | return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction); |
| 3625 | case IrInstructionIdEnumTag: | 3571 | case IrInstructionIdUnionTag: |
| 3626 | return ir_render_enum_tag(g, executable, (IrInstructionEnumTag *)instruction); | 3572 | return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction); |
| 3627 | case IrInstructionIdInitEnum: | ||
| 3628 | return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction); | ||
| 3629 | case IrInstructionIdStructInit: | 3573 | case IrInstructionIdStructInit: |
| 3630 | return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction); | 3574 | return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction); |
| 3631 | case IrInstructionIdUnionInit: | 3575 | case IrInstructionIdUnionInit: |
| ... | @@ -3650,8 +3594,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3650,8 +3594,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3650 | return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction); | 3594 | return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction); |
| 3651 | case IrInstructionIdPanic: | 3595 | case IrInstructionIdPanic: |
| 3652 | return ir_render_panic(g, executable, (IrInstructionPanic *)instruction); | 3596 | return ir_render_panic(g, executable, (IrInstructionPanic *)instruction); |
| 3653 | case IrInstructionIdEnumTagName: | 3597 | case IrInstructionIdTagName: |
| 3654 | return ir_render_enum_tag_name(g, executable, (IrInstructionEnumTagName *)instruction); | 3598 | return ir_render_enum_tag_name(g, executable, (IrInstructionTagName *)instruction); |
| 3655 | case IrInstructionIdFieldParentPtr: | 3599 | case IrInstructionIdFieldParentPtr: |
| 3656 | return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction); | 3600 | return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction); |
| 3657 | case IrInstructionIdAlignCast: | 3601 | case IrInstructionIdAlignCast: |
| ... | @@ -3761,8 +3705,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con | ... | @@ -3761,8 +3705,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 3761 | case TypeTableEntryIdNullLit: | 3705 | case TypeTableEntryIdNullLit: |
| 3762 | case TypeTableEntryIdErrorUnion: | 3706 | case TypeTableEntryIdErrorUnion: |
| 3763 | case TypeTableEntryIdPureError: | 3707 | case TypeTableEntryIdPureError: |
| 3764 | case TypeTableEntryIdEnum: | ||
| 3765 | case TypeTableEntryIdEnumTag: | ||
| 3766 | case TypeTableEntryIdNamespace: | 3708 | case TypeTableEntryIdNamespace: |
| 3767 | case TypeTableEntryIdBlock: | 3709 | case TypeTableEntryIdBlock: |
| 3768 | case TypeTableEntryIdBoundFn: | 3710 | case TypeTableEntryIdBoundFn: |
| ... | @@ -3772,6 +3714,12 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con | ... | @@ -3772,6 +3714,12 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 3772 | zig_unreachable(); | 3714 | zig_unreachable(); |
| 3773 | case TypeTableEntryIdBool: | 3715 | case TypeTableEntryIdBool: |
| 3774 | return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false); | 3716 | return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false); |
| 3717 | case TypeTableEntryIdEnum: | ||
| 3718 | { | ||
| 3719 | assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr); | ||
| 3720 | LLVMValueRef int_val = gen_const_val(g, const_val); | ||
| 3721 | return LLVMConstZExt(int_val, big_int_type_ref); | ||
| 3722 | } | ||
| 3775 | case TypeTableEntryIdInt: | 3723 | case TypeTableEntryIdInt: |
| 3776 | { | 3724 | { |
| 3777 | LLVMValueRef int_val = gen_const_val(g, const_val); | 3725 | LLVMValueRef int_val = gen_const_val(g, const_val); |
| ... | @@ -3813,6 +3761,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con | ... | @@ -3813,6 +3761,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 3813 | } | 3761 | } |
| 3814 | return val; | 3762 | return val; |
| 3815 | } | 3763 | } |
| 3764 | |||
| 3816 | } | 3765 | } |
| 3817 | zig_unreachable(); | 3766 | zig_unreachable(); |
| 3818 | } | 3767 | } |
| ... | @@ -3838,7 +3787,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -3838,7 +3787,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3838 | 3787 | ||
| 3839 | switch (type_entry->id) { | 3788 | switch (type_entry->id) { |
| 3840 | case TypeTableEntryIdInt: | 3789 | case TypeTableEntryIdInt: |
| 3841 | case TypeTableEntryIdEnumTag: | ||
| 3842 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); | 3790 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); |
| 3843 | case TypeTableEntryIdPureError: | 3791 | case TypeTableEntryIdPureError: |
| 3844 | assert(const_val->data.x_pure_err); | 3792 | assert(const_val->data.x_pure_err); |
| ... | @@ -4001,37 +3949,52 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -4001,37 +3949,52 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 4001 | ConstExprValue *payload_value = const_val->data.x_union.payload; | 3949 | ConstExprValue *payload_value = const_val->data.x_union.payload; |
| 4002 | assert(payload_value != nullptr); | 3950 | assert(payload_value != nullptr); |
| 4003 | 3951 | ||
| 4004 | if (!type_has_bits(payload_value->type)) { | 3952 | if (type_entry->data.unionation.gen_field_count == 0) { |
| 4005 | return LLVMGetUndef(union_type_ref); | 3953 | if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) { |
| 3954 | return nullptr; | ||
| 3955 | } else { | ||
| 3956 | return bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref, | ||
| 3957 | &const_val->data.x_union.tag); | ||
| 3958 | } | ||
| 4006 | } | 3959 | } |
| 4007 | 3960 | ||
| 4008 | uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref); | ||
| 4009 | uint64_t pad_bytes = type_entry->data.unionation.union_size_bytes - field_type_bytes; | ||
| 4010 | LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value); | ||
| 4011 | bool make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) || | ||
| 4012 | payload_value->type != type_entry->data.unionation.most_aligned_union_member; | ||
| 4013 | |||
| 4014 | LLVMValueRef union_value_ref; | 3961 | LLVMValueRef union_value_ref; |
| 4015 | { | 3962 | bool make_unnamed_struct; |
| 4016 | if (pad_bytes == 0) { | 3963 | if (!type_has_bits(payload_value->type)) { |
| 4017 | union_value_ref = correctly_typed_value; | 3964 | if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) |
| 4018 | } else { | 3965 | return LLVMGetUndef(type_entry->type_ref); |
| 4019 | LLVMValueRef fields[2]; | 3966 | |
| 4020 | fields[0] = correctly_typed_value; | 3967 | union_value_ref = LLVMGetUndef(type_entry->data.unionation.most_aligned_union_member->type_ref); |
| 4021 | fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes)); | 3968 | make_unnamed_struct = false; |
| 4022 | if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) { | 3969 | } else { |
| 4023 | union_value_ref = LLVMConstStruct(fields, 2, false); | 3970 | uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref); |
| 3971 | uint64_t pad_bytes = type_entry->data.unionation.union_size_bytes - field_type_bytes; | ||
| 3972 | LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value); | ||
| 3973 | make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) || | ||
| 3974 | payload_value->type != type_entry->data.unionation.most_aligned_union_member; | ||
| 3975 | |||
| 3976 | { | ||
| 3977 | if (pad_bytes == 0) { | ||
| 3978 | union_value_ref = correctly_typed_value; | ||
| 4024 | } else { | 3979 | } else { |
| 4025 | union_value_ref = LLVMConstNamedStruct(union_type_ref, fields, 2); | 3980 | LLVMValueRef fields[2]; |
| 3981 | fields[0] = correctly_typed_value; | ||
| 3982 | fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes)); | ||
| 3983 | if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) { | ||
| 3984 | union_value_ref = LLVMConstStruct(fields, 2, false); | ||
| 3985 | } else { | ||
| 3986 | union_value_ref = LLVMConstNamedStruct(union_type_ref, fields, 2); | ||
| 3987 | } | ||
| 4026 | } | 3988 | } |
| 4027 | } | 3989 | } |
| 4028 | } | ||
| 4029 | 3990 | ||
| 4030 | if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) { | 3991 | if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) { |
| 4031 | return union_value_ref; | 3992 | return union_value_ref; |
| 3993 | } | ||
| 4032 | } | 3994 | } |
| 4033 | 3995 | ||
| 4034 | LLVMValueRef tag_value = LLVMConstInt(type_entry->data.unionation.tag_type->type_ref, const_val->data.x_union.tag, false); | 3996 | LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref, |
| 3997 | &const_val->data.x_union.tag); | ||
| 4035 | 3998 | ||
| 4036 | LLVMValueRef fields[2]; | 3999 | LLVMValueRef fields[2]; |
| 4037 | fields[type_entry->data.unionation.gen_union_index] = union_value_ref; | 4000 | fields[type_entry->data.unionation.gen_union_index] = union_value_ref; |
| ... | @@ -4044,55 +4007,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -4044,55 +4007,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 4044 | } | 4007 | } |
| 4045 | 4008 | ||
| 4046 | } | 4009 | } |
| 4047 | case TypeTableEntryIdEnum: | ||
| 4048 | { | ||
| 4049 | LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref; | ||
| 4050 | LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false); | ||
| 4051 | if (type_entry->data.enumeration.gen_field_count == 0) { | ||
| 4052 | return tag_value; | ||
| 4053 | } else { | ||
| 4054 | LLVMTypeRef union_type_ref = type_entry->data.enumeration.union_type_ref; | ||
| 4055 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag]; | ||
| 4056 | assert(enum_field->value == const_val->data.x_enum.tag); | ||
| 4057 | LLVMValueRef union_value; | ||
| 4058 | 4010 | ||
| 4059 | bool make_unnamed_struct; | 4011 | case TypeTableEntryIdEnum: |
| 4060 | 4012 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag); | |
| 4061 | if (type_has_bits(enum_field->type_entry)) { | ||
| 4062 | uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, | ||
| 4063 | enum_field->type_entry->type_ref); | ||
| 4064 | uint64_t pad_bytes = type_entry->data.enumeration.union_size_bytes - field_type_bytes; | ||
| 4065 | |||
| 4066 | ConstExprValue *payload_value = const_val->data.x_enum.payload; | ||
| 4067 | LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value); | ||
| 4068 | |||
| 4069 | make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) || | ||
| 4070 | payload_value->type != type_entry->data.enumeration.most_aligned_union_member; | ||
| 4071 | |||
| 4072 | if (pad_bytes == 0) { | ||
| 4073 | union_value = correctly_typed_value; | ||
| 4074 | } else { | ||
| 4075 | LLVMValueRef fields[] = { | ||
| 4076 | correctly_typed_value, | ||
| 4077 | LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes)), | ||
| 4078 | }; | ||
| 4079 | union_value = LLVMConstStruct(fields, 2, false); | ||
| 4080 | } | ||
| 4081 | } else { | ||
| 4082 | make_unnamed_struct = false; | ||
| 4083 | union_value = LLVMGetUndef(union_type_ref); | ||
| 4084 | } | ||
| 4085 | LLVMValueRef fields[2]; | ||
| 4086 | fields[type_entry->data.enumeration.gen_tag_index] = tag_value; | ||
| 4087 | fields[type_entry->data.enumeration.gen_union_index] = union_value; | ||
| 4088 | |||
| 4089 | if (make_unnamed_struct) { | ||
| 4090 | return LLVMConstStruct(fields, 2, false); | ||
| 4091 | } else { | ||
| 4092 | return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); | ||
| 4093 | } | ||
| 4094 | } | ||
| 4095 | } | ||
| 4096 | case TypeTableEntryIdFn: | 4013 | case TypeTableEntryIdFn: |
| 4097 | return fn_llvm_value(g, const_val->data.x_fn.fn_entry); | 4014 | return fn_llvm_value(g, const_val->data.x_fn.fn_entry); |
| 4098 | case TypeTableEntryIdPointer: | 4015 | case TypeTableEntryIdPointer: |
| ... | @@ -4303,9 +4220,8 @@ static void generate_enum_name_tables(CodeGen *g) { | ... | @@ -4303,9 +4220,8 @@ static void generate_enum_name_tables(CodeGen *g) { |
| 4303 | 4220 | ||
| 4304 | 4221 | ||
| 4305 | for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) { | 4222 | for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) { |
| 4306 | TypeTableEntry *enum_tag_type = g->name_table_enums.at(enum_i); | 4223 | TypeTableEntry *enum_type = g->name_table_enums.at(enum_i); |
| 4307 | assert(enum_tag_type->id == TypeTableEntryIdEnumTag); | 4224 | assert(enum_type->id == TypeTableEntryIdEnum); |
| 4308 | TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type; | ||
| 4309 | 4225 | ||
| 4310 | size_t field_count = enum_type->data.enumeration.src_field_count; | 4226 | size_t field_count = enum_type->data.enumeration.src_field_count; |
| 4311 | LLVMValueRef *values = allocate<LLVMValueRef>(field_count); | 4227 | LLVMValueRef *values = allocate<LLVMValueRef>(field_count); |
| ... | @@ -4336,7 +4252,7 @@ static void generate_enum_name_tables(CodeGen *g) { | ... | @@ -4336,7 +4252,7 @@ static void generate_enum_name_tables(CodeGen *g) { |
| 4336 | LLVMSetGlobalConstant(name_table, true); | 4252 | LLVMSetGlobalConstant(name_table, true); |
| 4337 | LLVMSetUnnamedAddr(name_table, true); | 4253 | LLVMSetUnnamedAddr(name_table, true); |
| 4338 | LLVMSetAlignment(name_table, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(name_table_init))); | 4254 | LLVMSetAlignment(name_table, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(name_table_init))); |
| 4339 | enum_tag_type->data.enum_tag.name_table = name_table; | 4255 | enum_type->data.enumeration.name_table = name_table; |
| 4340 | } | 4256 | } |
| 4341 | } | 4257 | } |
| 4342 | 4258 | ||
| ... | @@ -4540,9 +4456,6 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4540,9 +4456,6 @@ static void do_code_gen(CodeGen *g) { |
| 4540 | } else if (instruction->id == IrInstructionIdErrWrapCode) { | 4456 | } else if (instruction->id == IrInstructionIdErrWrapCode) { |
| 4541 | IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction; | 4457 | IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction; |
| 4542 | slot = &err_wrap_code_instruction->tmp_ptr; | 4458 | slot = &err_wrap_code_instruction->tmp_ptr; |
| 4543 | } else if (instruction->id == IrInstructionIdInitEnum) { | ||
| 4544 | IrInstructionInitEnum *init_enum_instruction = (IrInstructionInitEnum *)instruction; | ||
| 4545 | slot = &init_enum_instruction->tmp_ptr; | ||
| 4546 | } else { | 4459 | } else { |
| 4547 | zig_unreachable(); | 4460 | zig_unreachable(); |
| 4548 | } | 4461 | } |
| ... | @@ -5039,7 +4952,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -5039,7 +4952,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 5039 | create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2); | 4952 | create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2); |
| 5040 | create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); | 4953 | create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); |
| 5041 | create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); | 4954 | create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); |
| 5042 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); | 4955 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int |
| 5043 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); | 4956 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); |
| 5044 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); | 4957 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); |
| 5045 | create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); | 4958 | create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); |
| ... | @@ -5049,7 +4962,8 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -5049,7 +4962,8 @@ static void define_builtin_fns(CodeGen *g) { |
| 5049 | create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2); | 4962 | create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2); |
| 5050 | create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2); | 4963 | create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2); |
| 5051 | create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1); | 4964 | create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1); |
| 5052 | create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1); | 4965 | create_builtin_fn(g, BuiltinFnIdTagName, "tagName", 1); |
| 4966 | create_builtin_fn(g, BuiltinFnIdTagType, "TagType", 1); | ||
| 5053 | create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3); | 4967 | create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3); |
| 5054 | create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2); | 4968 | create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2); |
| 5055 | create_builtin_fn(g, BuiltinFnIdDivExact, "divExact", 2); | 4969 | create_builtin_fn(g, BuiltinFnIdDivExact, "divExact", 2); |
| ... | @@ -5215,7 +5129,19 @@ static void define_builtin_compile_vars(CodeGen *g) { | ... | @@ -5215,7 +5129,19 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 5215 | assert(FloatModeOptimized == 0); | 5129 | assert(FloatModeOptimized == 0); |
| 5216 | assert(FloatModeStrict == 1); | 5130 | assert(FloatModeStrict == 1); |
| 5217 | } | 5131 | } |
| 5218 | buf_appendf(contents, "pub const is_big_endian = %s;\n", bool_to_str(g->is_big_endian)); | 5132 | { |
| 5133 | buf_appendf(contents, | ||
| 5134 | "pub const Endian = enum {\n" | ||
| 5135 | " Big,\n" | ||
| 5136 | " Little,\n" | ||
| 5137 | "};\n\n"); | ||
| 5138 | assert(FloatModeOptimized == 0); | ||
| 5139 | assert(FloatModeStrict == 1); | ||
| 5140 | } | ||
| 5141 | { | ||
| 5142 | const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little"; | ||
| 5143 | buf_appendf(contents, "pub const endian = %s;\n", endian_str); | ||
| 5144 | } | ||
| 5219 | buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); | 5145 | buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); |
| 5220 | buf_appendf(contents, "pub const os = Os.%s;\n", cur_os); | 5146 | buf_appendf(contents, "pub const os = Os.%s;\n", cur_os); |
| 5221 | buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch); | 5147 | buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch); |
| ... | @@ -5665,7 +5591,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { | ... | @@ -5665,7 +5591,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { |
| 5665 | case TypeTableEntryIdEnum: | 5591 | case TypeTableEntryIdEnum: |
| 5666 | case TypeTableEntryIdUnion: | 5592 | case TypeTableEntryIdUnion: |
| 5667 | case TypeTableEntryIdFn: | 5593 | case TypeTableEntryIdFn: |
| 5668 | case TypeTableEntryIdEnumTag: | ||
| 5669 | zig_panic("TODO implement get_c_type for more types"); | 5594 | zig_panic("TODO implement get_c_type for more types"); |
| 5670 | case TypeTableEntryIdInvalid: | 5595 | case TypeTableEntryIdInvalid: |
| 5671 | case TypeTableEntryIdMetaType: | 5596 | case TypeTableEntryIdMetaType: |
src/errmsg.cpp+4-4| ... | @@ -24,20 +24,20 @@ static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type) | ... | @@ -24,20 +24,20 @@ static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type) |
| 24 | bool is_tty = os_stderr_tty(); | 24 | bool is_tty = os_stderr_tty(); |
| 25 | if (color == ErrColorOn || (color == ErrColorAuto && is_tty)) { | 25 | if (color == ErrColorOn || (color == ErrColorAuto && is_tty)) { |
| 26 | if (err_type == ErrTypeError) { | 26 | if (err_type == ErrTypeError) { |
| 27 | os_stderr_set_color(TermColorWhite); | 27 | os_stderr_set_color(TermColorBold); |
| 28 | fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col); | 28 | fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col); |
| 29 | os_stderr_set_color(TermColorRed); | 29 | os_stderr_set_color(TermColorRed); |
| 30 | fprintf(stderr, "error:"); | 30 | fprintf(stderr, "error:"); |
| 31 | os_stderr_set_color(TermColorWhite); | 31 | os_stderr_set_color(TermColorBold); |
| 32 | fprintf(stderr, " %s", text); | 32 | fprintf(stderr, " %s", text); |
| 33 | os_stderr_set_color(TermColorReset); | 33 | os_stderr_set_color(TermColorReset); |
| 34 | fprintf(stderr, "\n"); | 34 | fprintf(stderr, "\n"); |
| 35 | } else if (err_type == ErrTypeNote) { | 35 | } else if (err_type == ErrTypeNote) { |
| 36 | os_stderr_set_color(TermColorWhite); | 36 | os_stderr_set_color(TermColorBold); |
| 37 | fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col); | 37 | fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col); |
| 38 | os_stderr_set_color(TermColorCyan); | 38 | os_stderr_set_color(TermColorCyan); |
| 39 | fprintf(stderr, "note:"); | 39 | fprintf(stderr, "note:"); |
| 40 | os_stderr_set_color(TermColorWhite); | 40 | os_stderr_set_color(TermColorBold); |
| 41 | fprintf(stderr, " %s", text); | 41 | fprintf(stderr, " %s", text); |
| 42 | os_stderr_set_color(TermColorReset); | 42 | os_stderr_set_color(TermColorReset); |
| 43 | fprintf(stderr, "\n"); | 43 | fprintf(stderr, "\n"); |
src/error.cpp+1| ... | @@ -26,6 +26,7 @@ const char *err_str(int err) { | ... | @@ -26,6 +26,7 @@ const char *err_str(int err) { |
| 26 | case ErrorExactDivRemainder: return "exact division had a remainder"; | 26 | case ErrorExactDivRemainder: return "exact division had a remainder"; |
| 27 | case ErrorNegativeDenominator: return "negative denominator"; | 27 | case ErrorNegativeDenominator: return "negative denominator"; |
| 28 | case ErrorShiftedOutOneBits: return "exact shift shifted out one bits"; | 28 | case ErrorShiftedOutOneBits: return "exact shift shifted out one bits"; |
| 29 | case ErrorCCompileErrors: return "C compile errors"; | ||
| 29 | } | 30 | } |
| 30 | return "(invalid error)"; | 31 | return "(invalid error)"; |
| 31 | } | 32 | } |
src/error.hpp+1| ... | @@ -26,6 +26,7 @@ enum Error { | ... | @@ -26,6 +26,7 @@ enum Error { |
| 26 | ErrorExactDivRemainder, | 26 | ErrorExactDivRemainder, |
| 27 | ErrorNegativeDenominator, | 27 | ErrorNegativeDenominator, |
| 28 | ErrorShiftedOutOneBits, | 28 | ErrorShiftedOutOneBits, |
| 29 | ErrorCCompileErrors, | ||
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 31 | const char *err_str(int err); | 32 | const char *err_str(int err); |
src/ir.cpp+346-295| ... | @@ -223,10 +223,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr * | ... | @@ -223,10 +223,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr * |
| 223 | return IrInstructionIdStructFieldPtr; | 223 | return IrInstructionIdStructFieldPtr; |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumFieldPtr *) { | ||
| 227 | return IrInstructionIdEnumFieldPtr; | ||
| 228 | } | ||
| 229 | |||
| 230 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionFieldPtr *) { | 226 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionFieldPtr *) { |
| 231 | return IrInstructionIdUnionFieldPtr; | 227 | return IrInstructionIdUnionFieldPtr; |
| 232 | } | 228 | } |
| ... | @@ -319,8 +315,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) { | ... | @@ -319,8 +315,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) { |
| 319 | return IrInstructionIdCtz; | 315 | return IrInstructionIdCtz; |
| 320 | } | 316 | } |
| 321 | 317 | ||
| 322 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTag *) { | 318 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionTag *) { |
| 323 | return IrInstructionIdEnumTag; | 319 | return IrInstructionIdUnionTag; |
| 324 | } | 320 | } |
| 325 | 321 | ||
| 326 | static constexpr IrInstructionId ir_instruction_id(IrInstructionImport *) { | 322 | static constexpr IrInstructionId ir_instruction_id(IrInstructionImport *) { |
| ... | @@ -479,10 +475,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) | ... | @@ -479,10 +475,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) |
| 479 | return IrInstructionIdTestComptime; | 475 | return IrInstructionIdTestComptime; |
| 480 | } | 476 | } |
| 481 | 477 | ||
| 482 | static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) { | ||
| 483 | return IrInstructionIdInitEnum; | ||
| 484 | } | ||
| 485 | |||
| 486 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) { | 478 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) { |
| 487 | return IrInstructionIdPtrCast; | 479 | return IrInstructionIdPtrCast; |
| 488 | } | 480 | } |
| ... | @@ -547,8 +539,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPanic *) { | ... | @@ -547,8 +539,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPanic *) { |
| 547 | return IrInstructionIdPanic; | 539 | return IrInstructionIdPanic; |
| 548 | } | 540 | } |
| 549 | 541 | ||
| 550 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTagName *) { | 542 | static constexpr IrInstructionId ir_instruction_id(IrInstructionTagName *) { |
| 551 | return IrInstructionIdEnumTagName; | 543 | return IrInstructionIdTagName; |
| 544 | } | ||
| 545 | |||
| 546 | static constexpr IrInstructionId ir_instruction_id(IrInstructionTagType *) { | ||
| 547 | return IrInstructionIdTagType; | ||
| 552 | } | 548 | } |
| 553 | 549 | ||
| 554 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr *) { | 550 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr *) { |
| ... | @@ -909,27 +905,6 @@ static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstructi | ... | @@ -909,27 +905,6 @@ static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstructi |
| 909 | return new_instruction; | 905 | return new_instruction; |
| 910 | } | 906 | } |
| 911 | 907 | ||
| 912 | static IrInstruction *ir_build_enum_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 913 | IrInstruction *enum_ptr, TypeEnumField *field) | ||
| 914 | { | ||
| 915 | IrInstructionEnumFieldPtr *instruction = ir_build_instruction<IrInstructionEnumFieldPtr>(irb, scope, source_node); | ||
| 916 | instruction->enum_ptr = enum_ptr; | ||
| 917 | instruction->field = field; | ||
| 918 | |||
| 919 | ir_ref_instruction(enum_ptr, irb->current_basic_block); | ||
| 920 | |||
| 921 | return &instruction->base; | ||
| 922 | } | ||
| 923 | |||
| 924 | static IrInstruction *ir_build_enum_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, | ||
| 925 | IrInstruction *enum_ptr, TypeEnumField *type_enum_field) | ||
| 926 | { | ||
| 927 | IrInstruction *new_instruction = ir_build_enum_field_ptr(irb, old_instruction->scope, | ||
| 928 | old_instruction->source_node, enum_ptr, type_enum_field); | ||
| 929 | ir_link_new_instruction(new_instruction, old_instruction); | ||
| 930 | return new_instruction; | ||
| 931 | } | ||
| 932 | |||
| 933 | static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | 908 | static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 934 | IrInstruction *union_ptr, TypeUnionField *field) | 909 | IrInstruction *union_ptr, TypeUnionField *field) |
| 935 | { | 910 | { |
| ... | @@ -1524,8 +1499,8 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -1524,8 +1499,8 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode |
| 1524 | return &instruction->base; | 1499 | return &instruction->base; |
| 1525 | } | 1500 | } |
| 1526 | 1501 | ||
| 1527 | static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { | 1502 | static IrInstruction *ir_build_union_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1528 | IrInstructionEnumTag *instruction = ir_build_instruction<IrInstructionEnumTag>(irb, scope, source_node); | 1503 | IrInstructionUnionTag *instruction = ir_build_instruction<IrInstructionUnionTag>(irb, scope, source_node); |
| 1529 | instruction->value = value; | 1504 | instruction->value = value; |
| 1530 | 1505 | ||
| 1531 | ir_ref_instruction(value, irb->current_basic_block); | 1506 | ir_ref_instruction(value, irb->current_basic_block); |
| ... | @@ -1533,13 +1508,6 @@ static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *s | ... | @@ -1533,13 +1508,6 @@ static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *s |
| 1533 | return &instruction->base; | 1508 | return &instruction->base; |
| 1534 | } | 1509 | } |
| 1535 | 1510 | ||
| 1536 | static IrInstruction *ir_build_enum_tag_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) { | ||
| 1537 | IrInstruction *new_instruction = ir_build_enum_tag(irb, old_instruction->scope, | ||
| 1538 | old_instruction->source_node, value); | ||
| 1539 | ir_link_new_instruction(new_instruction, old_instruction); | ||
| 1540 | return new_instruction; | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | static IrInstruction *ir_build_import(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { | 1511 | static IrInstruction *ir_build_import(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { |
| 1544 | IrInstructionImport *instruction = ir_build_instruction<IrInstructionImport>(irb, scope, source_node); | 1512 | IrInstructionImport *instruction = ir_build_instruction<IrInstructionImport>(irb, scope, source_node); |
| 1545 | instruction->name = name; | 1513 | instruction->name = name; |
| ... | @@ -2029,28 +1997,6 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -2029,28 +1997,6 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo |
| 2029 | return &instruction->base; | 1997 | return &instruction->base; |
| 2030 | } | 1998 | } |
| 2031 | 1999 | ||
| 2032 | static IrInstruction *ir_build_init_enum(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 2033 | TypeTableEntry *enum_type, TypeEnumField *field, IrInstruction *init_value) | ||
| 2034 | { | ||
| 2035 | IrInstructionInitEnum *instruction = ir_build_instruction<IrInstructionInitEnum>(irb, scope, source_node); | ||
| 2036 | instruction->enum_type = enum_type; | ||
| 2037 | instruction->field = field; | ||
| 2038 | instruction->init_value = init_value; | ||
| 2039 | |||
| 2040 | ir_ref_instruction(init_value, irb->current_basic_block); | ||
| 2041 | |||
| 2042 | return &instruction->base; | ||
| 2043 | } | ||
| 2044 | |||
| 2045 | static IrInstruction *ir_build_init_enum_from(IrBuilder *irb, IrInstruction *old_instruction, | ||
| 2046 | TypeTableEntry *enum_type, TypeEnumField *field, IrInstruction *init_value) | ||
| 2047 | { | ||
| 2048 | IrInstruction *new_instruction = ir_build_init_enum(irb, old_instruction->scope, old_instruction->source_node, | ||
| 2049 | enum_type, field, init_value); | ||
| 2050 | ir_link_new_instruction(new_instruction, old_instruction); | ||
| 2051 | return new_instruction; | ||
| 2052 | } | ||
| 2053 | |||
| 2054 | static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2000 | static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2055 | IrInstruction *dest_type, IrInstruction *ptr) | 2001 | IrInstruction *dest_type, IrInstruction *ptr) |
| 2056 | { | 2002 | { |
| ... | @@ -2259,10 +2205,21 @@ static IrInstruction *ir_build_panic(IrBuilder *irb, Scope *scope, AstNode *sour | ... | @@ -2259,10 +2205,21 @@ static IrInstruction *ir_build_panic(IrBuilder *irb, Scope *scope, AstNode *sour |
| 2259 | return &instruction->base; | 2205 | return &instruction->base; |
| 2260 | } | 2206 | } |
| 2261 | 2207 | ||
| 2262 | static IrInstruction *ir_build_enum_tag_name(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2208 | static IrInstruction *ir_build_tag_name(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2263 | IrInstruction *target) | 2209 | IrInstruction *target) |
| 2264 | { | 2210 | { |
| 2265 | IrInstructionEnumTagName *instruction = ir_build_instruction<IrInstructionEnumTagName>(irb, scope, source_node); | 2211 | IrInstructionTagName *instruction = ir_build_instruction<IrInstructionTagName>(irb, scope, source_node); |
| 2212 | instruction->target = target; | ||
| 2213 | |||
| 2214 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 2215 | |||
| 2216 | return &instruction->base; | ||
| 2217 | } | ||
| 2218 | |||
| 2219 | static IrInstruction *ir_build_tag_type(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 2220 | IrInstruction *target) | ||
| 2221 | { | ||
| 2222 | IrInstructionTagType *instruction = ir_build_instruction<IrInstructionTagType>(irb, scope, source_node); | ||
| 2266 | instruction->target = target; | 2223 | instruction->target = target; |
| 2267 | 2224 | ||
| 2268 | ir_ref_instruction(target, irb->current_basic_block); | 2225 | ir_ref_instruction(target, irb->current_basic_block); |
| ... | @@ -2466,13 +2423,6 @@ static IrInstruction *ir_instruction_structfieldptr_get_dep(IrInstructionStructF | ... | @@ -2466,13 +2423,6 @@ static IrInstruction *ir_instruction_structfieldptr_get_dep(IrInstructionStructF |
| 2466 | } | 2423 | } |
| 2467 | } | 2424 | } |
| 2468 | 2425 | ||
| 2469 | static IrInstruction *ir_instruction_enumfieldptr_get_dep(IrInstructionEnumFieldPtr *instruction, size_t index) { | ||
| 2470 | switch (index) { | ||
| 2471 | case 0: return instruction->enum_ptr; | ||
| 2472 | default: return nullptr; | ||
| 2473 | } | ||
| 2474 | } | ||
| 2475 | |||
| 2476 | static IrInstruction *ir_instruction_unionfieldptr_get_dep(IrInstructionUnionFieldPtr *instruction, size_t index) { | 2426 | static IrInstruction *ir_instruction_unionfieldptr_get_dep(IrInstructionUnionFieldPtr *instruction, size_t index) { |
| 2477 | switch (index) { | 2427 | switch (index) { |
| 2478 | case 0: return instruction->union_ptr; | 2428 | case 0: return instruction->union_ptr; |
| ... | @@ -2642,7 +2592,7 @@ static IrInstruction *ir_instruction_maybewrap_get_dep(IrInstructionMaybeWrap *i | ... | @@ -2642,7 +2592,7 @@ static IrInstruction *ir_instruction_maybewrap_get_dep(IrInstructionMaybeWrap *i |
| 2642 | } | 2592 | } |
| 2643 | } | 2593 | } |
| 2644 | 2594 | ||
| 2645 | static IrInstruction *ir_instruction_enumtag_get_dep(IrInstructionEnumTag *instruction, size_t index) { | 2595 | static IrInstruction *ir_instruction_uniontag_get_dep(IrInstructionUnionTag *instruction, size_t index) { |
| 2646 | switch (index) { | 2596 | switch (index) { |
| 2647 | case 0: return instruction->value; | 2597 | case 0: return instruction->value; |
| 2648 | default: return nullptr; | 2598 | default: return nullptr; |
| ... | @@ -2928,13 +2878,6 @@ static IrInstruction *ir_instruction_testcomptime_get_dep(IrInstructionTestCompt | ... | @@ -2928,13 +2878,6 @@ static IrInstruction *ir_instruction_testcomptime_get_dep(IrInstructionTestCompt |
| 2928 | } | 2878 | } |
| 2929 | } | 2879 | } |
| 2930 | 2880 | ||
| 2931 | static IrInstruction *ir_instruction_initenum_get_dep(IrInstructionInitEnum *instruction, size_t index) { | ||
| 2932 | switch (index) { | ||
| 2933 | case 0: return instruction->init_value; | ||
| 2934 | default: return nullptr; | ||
| 2935 | } | ||
| 2936 | } | ||
| 2937 | |||
| 2938 | static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instruction, | 2881 | static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instruction, |
| 2939 | size_t index) | 2882 | size_t index) |
| 2940 | { | 2883 | { |
| ... | @@ -3059,7 +3002,14 @@ static IrInstruction *ir_instruction_panic_get_dep(IrInstructionPanic *instructi | ... | @@ -3059,7 +3002,14 @@ static IrInstruction *ir_instruction_panic_get_dep(IrInstructionPanic *instructi |
| 3059 | } | 3002 | } |
| 3060 | } | 3003 | } |
| 3061 | 3004 | ||
| 3062 | static IrInstruction *ir_instruction_enumtagname_get_dep(IrInstructionEnumTagName *instruction, size_t index) { | 3005 | static IrInstruction *ir_instruction_enumtagname_get_dep(IrInstructionTagName *instruction, size_t index) { |
| 3006 | switch (index) { | ||
| 3007 | case 0: return instruction->target; | ||
| 3008 | default: return nullptr; | ||
| 3009 | } | ||
| 3010 | } | ||
| 3011 | |||
| 3012 | static IrInstruction *ir_instruction_enumtagtype_get_dep(IrInstructionTagType *instruction, size_t index) { | ||
| 3063 | switch (index) { | 3013 | switch (index) { |
| 3064 | case 0: return instruction->target; | 3014 | case 0: return instruction->target; |
| 3065 | default: return nullptr; | 3015 | default: return nullptr; |
| ... | @@ -3162,8 +3112,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3162,8 +3112,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3162 | return ir_instruction_fieldptr_get_dep((IrInstructionFieldPtr *) instruction, index); | 3112 | return ir_instruction_fieldptr_get_dep((IrInstructionFieldPtr *) instruction, index); |
| 3163 | case IrInstructionIdStructFieldPtr: | 3113 | case IrInstructionIdStructFieldPtr: |
| 3164 | return ir_instruction_structfieldptr_get_dep((IrInstructionStructFieldPtr *) instruction, index); | 3114 | return ir_instruction_structfieldptr_get_dep((IrInstructionStructFieldPtr *) instruction, index); |
| 3165 | case IrInstructionIdEnumFieldPtr: | ||
| 3166 | return ir_instruction_enumfieldptr_get_dep((IrInstructionEnumFieldPtr *) instruction, index); | ||
| 3167 | case IrInstructionIdUnionFieldPtr: | 3115 | case IrInstructionIdUnionFieldPtr: |
| 3168 | return ir_instruction_unionfieldptr_get_dep((IrInstructionUnionFieldPtr *) instruction, index); | 3116 | return ir_instruction_unionfieldptr_get_dep((IrInstructionUnionFieldPtr *) instruction, index); |
| 3169 | case IrInstructionIdElemPtr: | 3117 | case IrInstructionIdElemPtr: |
| ... | @@ -3212,8 +3160,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3212,8 +3160,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3212 | return ir_instruction_unwrapmaybe_get_dep((IrInstructionUnwrapMaybe *) instruction, index); | 3160 | return ir_instruction_unwrapmaybe_get_dep((IrInstructionUnwrapMaybe *) instruction, index); |
| 3213 | case IrInstructionIdMaybeWrap: | 3161 | case IrInstructionIdMaybeWrap: |
| 3214 | return ir_instruction_maybewrap_get_dep((IrInstructionMaybeWrap *) instruction, index); | 3162 | return ir_instruction_maybewrap_get_dep((IrInstructionMaybeWrap *) instruction, index); |
| 3215 | case IrInstructionIdEnumTag: | 3163 | case IrInstructionIdUnionTag: |
| 3216 | return ir_instruction_enumtag_get_dep((IrInstructionEnumTag *) instruction, index); | 3164 | return ir_instruction_uniontag_get_dep((IrInstructionUnionTag *) instruction, index); |
| 3217 | case IrInstructionIdClz: | 3165 | case IrInstructionIdClz: |
| 3218 | return ir_instruction_clz_get_dep((IrInstructionClz *) instruction, index); | 3166 | return ir_instruction_clz_get_dep((IrInstructionClz *) instruction, index); |
| 3219 | case IrInstructionIdCtz: | 3167 | case IrInstructionIdCtz: |
| ... | @@ -3290,8 +3238,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3290,8 +3238,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3290 | return ir_instruction_fnproto_get_dep((IrInstructionFnProto *) instruction, index); | 3238 | return ir_instruction_fnproto_get_dep((IrInstructionFnProto *) instruction, index); |
| 3291 | case IrInstructionIdTestComptime: | 3239 | case IrInstructionIdTestComptime: |
| 3292 | return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index); | 3240 | return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index); |
| 3293 | case IrInstructionIdInitEnum: | ||
| 3294 | return ir_instruction_initenum_get_dep((IrInstructionInitEnum *) instruction, index); | ||
| 3295 | case IrInstructionIdPtrCast: | 3241 | case IrInstructionIdPtrCast: |
| 3296 | return ir_instruction_ptrcast_get_dep((IrInstructionPtrCast *) instruction, index); | 3242 | return ir_instruction_ptrcast_get_dep((IrInstructionPtrCast *) instruction, index); |
| 3297 | case IrInstructionIdBitCast: | 3243 | case IrInstructionIdBitCast: |
| ... | @@ -3324,8 +3270,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3324,8 +3270,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3324 | return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index); | 3270 | return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index); |
| 3325 | case IrInstructionIdPanic: | 3271 | case IrInstructionIdPanic: |
| 3326 | return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index); | 3272 | return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index); |
| 3327 | case IrInstructionIdEnumTagName: | 3273 | case IrInstructionIdTagName: |
| 3328 | return ir_instruction_enumtagname_get_dep((IrInstructionEnumTagName *) instruction, index); | 3274 | return ir_instruction_enumtagname_get_dep((IrInstructionTagName *) instruction, index); |
| 3275 | case IrInstructionIdTagType: | ||
| 3276 | return ir_instruction_enumtagtype_get_dep((IrInstructionTagType *) instruction, index); | ||
| 3329 | case IrInstructionIdFieldParentPtr: | 3277 | case IrInstructionIdFieldParentPtr: |
| 3330 | return ir_instruction_fieldparentptr_get_dep((IrInstructionFieldParentPtr *) instruction, index); | 3278 | return ir_instruction_fieldparentptr_get_dep((IrInstructionFieldParentPtr *) instruction, index); |
| 3331 | case IrInstructionIdOffsetOf: | 3279 | case IrInstructionIdOffsetOf: |
| ... | @@ -4671,15 +4619,24 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4671,15 +4619,24 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4671 | 4619 | ||
| 4672 | return ir_build_ptr_to_int(irb, scope, node, arg0_value); | 4620 | return ir_build_ptr_to_int(irb, scope, node, arg0_value); |
| 4673 | } | 4621 | } |
| 4674 | case BuiltinFnIdEnumTagName: | 4622 | case BuiltinFnIdTagName: |
| 4623 | { | ||
| 4624 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4625 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 4626 | if (arg0_value == irb->codegen->invalid_instruction) | ||
| 4627 | return arg0_value; | ||
| 4628 | |||
| 4629 | IrInstruction *actual_tag = ir_build_union_tag(irb, scope, node, arg0_value); | ||
| 4630 | return ir_build_tag_name(irb, scope, node, actual_tag); | ||
| 4631 | } | ||
| 4632 | case BuiltinFnIdTagType: | ||
| 4675 | { | 4633 | { |
| 4676 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | 4634 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 4677 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | 4635 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 4678 | if (arg0_value == irb->codegen->invalid_instruction) | 4636 | if (arg0_value == irb->codegen->invalid_instruction) |
| 4679 | return arg0_value; | 4637 | return arg0_value; |
| 4680 | 4638 | ||
| 4681 | IrInstruction *actual_tag = ir_build_enum_tag(irb, scope, node, arg0_value); | 4639 | return ir_build_tag_type(irb, scope, node, arg0_value); |
| 4682 | return ir_build_enum_tag_name(irb, scope, node, actual_tag); | ||
| 4683 | } | 4640 | } |
| 4684 | case BuiltinFnIdFieldParentPtr: | 4641 | case BuiltinFnIdFieldParentPtr: |
| 4685 | { | 4642 | { |
| ... | @@ -8348,13 +8305,28 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour | ... | @@ -8348,13 +8305,28 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour |
| 8348 | { | 8305 | { |
| 8349 | assert(wanted_type->id == TypeTableEntryIdInt); | 8306 | assert(wanted_type->id == TypeTableEntryIdInt); |
| 8350 | 8307 | ||
| 8308 | TypeTableEntry *actual_type = target->value.type; | ||
| 8309 | ensure_complete_type(ira->codegen, actual_type); | ||
| 8310 | if (type_is_invalid(actual_type)) | ||
| 8311 | return ira->codegen->invalid_instruction; | ||
| 8312 | |||
| 8313 | if (wanted_type != actual_type->data.enumeration.tag_int_type) { | ||
| 8314 | ir_add_error(ira, source_instr, | ||
| 8315 | buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'", | ||
| 8316 | buf_ptr(&wanted_type->name), | ||
| 8317 | buf_ptr(&actual_type->data.enumeration.tag_int_type->name))); | ||
| 8318 | return ira->codegen->invalid_instruction; | ||
| 8319 | } | ||
| 8320 | |||
| 8321 | assert(actual_type->id == TypeTableEntryIdEnum); | ||
| 8322 | |||
| 8351 | if (instr_is_comptime(target)) { | 8323 | if (instr_is_comptime(target)) { |
| 8352 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | 8324 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 8353 | if (!val) | 8325 | if (!val) |
| 8354 | return ira->codegen->invalid_instruction; | 8326 | return ira->codegen->invalid_instruction; |
| 8355 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 8327 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, |
| 8356 | source_instr->source_node, wanted_type); | 8328 | source_instr->source_node, wanted_type); |
| 8357 | init_const_unsigned_negative(&result->value, wanted_type, val->data.x_enum.tag, false); | 8329 | init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag); |
| 8358 | return result; | 8330 | return result; |
| 8359 | } | 8331 | } |
| 8360 | 8332 | ||
| ... | @@ -8364,6 +8336,31 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour | ... | @@ -8364,6 +8336,31 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour |
| 8364 | return result; | 8336 | return result; |
| 8365 | } | 8337 | } |
| 8366 | 8338 | ||
| 8339 | static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 8340 | IrInstruction *target, TypeTableEntry *wanted_type) | ||
| 8341 | { | ||
| 8342 | assert(target->value.type->id == TypeTableEntryIdUnion); | ||
| 8343 | assert(wanted_type->id == TypeTableEntryIdEnum); | ||
| 8344 | assert(wanted_type == target->value.type->data.unionation.tag_type); | ||
| 8345 | |||
| 8346 | if (instr_is_comptime(target)) { | ||
| 8347 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | ||
| 8348 | if (!val) | ||
| 8349 | return ira->codegen->invalid_instruction; | ||
| 8350 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | ||
| 8351 | source_instr->source_node, wanted_type); | ||
| 8352 | result->value.special = ConstValSpecialStatic; | ||
| 8353 | result->value.type = wanted_type; | ||
| 8354 | bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag); | ||
| 8355 | return result; | ||
| 8356 | } | ||
| 8357 | |||
| 8358 | IrInstruction *result = ir_build_union_tag(&ira->new_irb, source_instr->scope, | ||
| 8359 | source_instr->source_node, target); | ||
| 8360 | result->value.type = wanted_type; | ||
| 8361 | return result; | ||
| 8362 | } | ||
| 8363 | |||
| 8367 | static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr, | 8364 | static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr, |
| 8368 | IrInstruction *target, TypeTableEntry *wanted_type) | 8365 | IrInstruction *target, TypeTableEntry *wanted_type) |
| 8369 | { | 8366 | { |
| ... | @@ -8419,6 +8416,22 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour | ... | @@ -8419,6 +8416,22 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 8419 | { | 8416 | { |
| 8420 | assert(wanted_type->id == TypeTableEntryIdEnum); | 8417 | assert(wanted_type->id == TypeTableEntryIdEnum); |
| 8421 | 8418 | ||
| 8419 | TypeTableEntry *actual_type = target->value.type; | ||
| 8420 | |||
| 8421 | ensure_complete_type(ira->codegen, wanted_type); | ||
| 8422 | if (type_is_invalid(wanted_type)) | ||
| 8423 | return ira->codegen->invalid_instruction; | ||
| 8424 | |||
| 8425 | if (actual_type != wanted_type->data.enumeration.tag_int_type) { | ||
| 8426 | ir_add_error(ira, source_instr, | ||
| 8427 | buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'", | ||
| 8428 | buf_ptr(&actual_type->name), | ||
| 8429 | buf_ptr(&wanted_type->data.enumeration.tag_int_type->name))); | ||
| 8430 | return ira->codegen->invalid_instruction; | ||
| 8431 | } | ||
| 8432 | |||
| 8433 | assert(actual_type->id == TypeTableEntryIdInt); | ||
| 8434 | |||
| 8422 | if (instr_is_comptime(target)) { | 8435 | if (instr_is_comptime(target)) { |
| 8423 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | 8436 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 8424 | if (!val) | 8437 | if (!val) |
| ... | @@ -8436,7 +8449,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour | ... | @@ -8436,7 +8449,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 8436 | 8449 | ||
| 8437 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 8450 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, |
| 8438 | source_instr->source_node, wanted_type); | 8451 | source_instr->source_node, wanted_type); |
| 8439 | result->value.data.x_enum.tag = bigint_as_unsigned(&val->data.x_bigint); | 8452 | bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint); |
| 8440 | return result; | 8453 | return result; |
| 8441 | } | 8454 | } |
| 8442 | 8455 | ||
| ... | @@ -8874,21 +8887,26 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -8874,21 +8887,26 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 8874 | } | 8887 | } |
| 8875 | 8888 | ||
| 8876 | // explicit cast from integer to enum type with no payload | 8889 | // explicit cast from integer to enum type with no payload |
| 8877 | if (actual_type->id == TypeTableEntryIdInt && | 8890 | if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) { |
| 8878 | wanted_type->id == TypeTableEntryIdEnum && | ||
| 8879 | wanted_type->data.enumeration.gen_field_count == 0) | ||
| 8880 | { | ||
| 8881 | return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type); | 8891 | return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type); |
| 8882 | } | 8892 | } |
| 8883 | 8893 | ||
| 8884 | // explicit cast from enum type with no payload to integer | 8894 | // explicit cast from enum type with no payload to integer |
| 8885 | if (wanted_type->id == TypeTableEntryIdInt && | 8895 | if (wanted_type->id == TypeTableEntryIdInt && actual_type->id == TypeTableEntryIdEnum) { |
| 8886 | actual_type->id == TypeTableEntryIdEnum && | ||
| 8887 | actual_type->data.enumeration.gen_field_count == 0) | ||
| 8888 | { | ||
| 8889 | return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type); | 8896 | return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type); |
| 8890 | } | 8897 | } |
| 8891 | 8898 | ||
| 8899 | // explicit cast from union to the enum type of the union | ||
| 8900 | if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) { | ||
| 8901 | type_ensure_zero_bits_known(ira->codegen, actual_type); | ||
| 8902 | if (type_is_invalid(actual_type)) | ||
| 8903 | return ira->codegen->invalid_instruction; | ||
| 8904 | |||
| 8905 | if (actual_type->data.unionation.tag_type == wanted_type) { | ||
| 8906 | return ir_analyze_union_to_tag(ira, source_instr, value, wanted_type); | ||
| 8907 | } | ||
| 8908 | } | ||
| 8909 | |||
| 8892 | // explicit cast from undefined to anything | 8910 | // explicit cast from undefined to anything |
| 8893 | if (actual_type->id == TypeTableEntryIdUndefLit) { | 8911 | if (actual_type->id == TypeTableEntryIdUndefLit) { |
| 8894 | return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type); | 8912 | return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type); |
| ... | @@ -9095,7 +9113,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic | ... | @@ -9095,7 +9113,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic |
| 9095 | if (!const_val) | 9113 | if (!const_val) |
| 9096 | return false; | 9114 | return false; |
| 9097 | 9115 | ||
| 9098 | *out = (AtomicOrder)const_val->data.x_enum.tag; | 9116 | *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum_tag); |
| 9099 | return true; | 9117 | return true; |
| 9100 | } | 9118 | } |
| 9101 | 9119 | ||
| ... | @@ -9115,7 +9133,27 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob | ... | @@ -9115,7 +9133,27 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob |
| 9115 | if (!const_val) | 9133 | if (!const_val) |
| 9116 | return false; | 9134 | return false; |
| 9117 | 9135 | ||
| 9118 | *out = (GlobalLinkageId)const_val->data.x_enum.tag; | 9136 | *out = (GlobalLinkageId)bigint_as_unsigned(&const_val->data.x_enum_tag); |
| 9137 | return true; | ||
| 9138 | } | ||
| 9139 | |||
| 9140 | static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMode *out) { | ||
| 9141 | if (type_is_invalid(value->value.type)) | ||
| 9142 | return false; | ||
| 9143 | |||
| 9144 | ConstExprValue *float_mode_val = get_builtin_value(ira->codegen, "FloatMode"); | ||
| 9145 | assert(float_mode_val->type->id == TypeTableEntryIdMetaType); | ||
| 9146 | TypeTableEntry *float_mode_type = float_mode_val->data.x_type; | ||
| 9147 | |||
| 9148 | IrInstruction *casted_value = ir_implicit_cast(ira, value, float_mode_type); | ||
| 9149 | if (type_is_invalid(casted_value->value.type)) | ||
| 9150 | return false; | ||
| 9151 | |||
| 9152 | ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad); | ||
| 9153 | if (!const_val) | ||
| 9154 | return false; | ||
| 9155 | |||
| 9156 | *out = (FloatMode)bigint_as_unsigned(&const_val->data.x_enum_tag); | ||
| 9119 | return true; | 9157 | return true; |
| 9120 | } | 9158 | } |
| 9121 | 9159 | ||
| ... | @@ -9327,7 +9365,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -9327,7 +9365,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 9327 | break; | 9365 | break; |
| 9328 | 9366 | ||
| 9329 | case TypeTableEntryIdEnum: | 9367 | case TypeTableEntryIdEnum: |
| 9330 | if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) { | 9368 | if (!is_equality_cmp) { |
| 9331 | ir_add_error_node(ira, source_node, | 9369 | ir_add_error_node(ira, source_node, |
| 9332 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); | 9370 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| 9333 | return ira->codegen->builtin_types.entry_invalid; | 9371 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -9346,9 +9384,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -9346,9 +9384,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 9346 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); | 9384 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| 9347 | return ira->codegen->builtin_types.entry_invalid; | 9385 | return ira->codegen->builtin_types.entry_invalid; |
| 9348 | 9386 | ||
| 9349 | case TypeTableEntryIdEnumTag: | ||
| 9350 | zig_panic("TODO implement comparison for enum tag type"); | ||
| 9351 | |||
| 9352 | case TypeTableEntryIdVar: | 9387 | case TypeTableEntryIdVar: |
| 9353 | zig_unreachable(); | 9388 | zig_unreachable(); |
| 9354 | } | 9389 | } |
| ... | @@ -10097,7 +10132,6 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { | ... | @@ -10097,7 +10132,6 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { |
| 10097 | case TypeTableEntryIdVoid: | 10132 | case TypeTableEntryIdVoid: |
| 10098 | case TypeTableEntryIdPureError: | 10133 | case TypeTableEntryIdPureError: |
| 10099 | case TypeTableEntryIdFn: | 10134 | case TypeTableEntryIdFn: |
| 10100 | case TypeTableEntryIdEnumTag: | ||
| 10101 | return VarClassRequiredAny; | 10135 | return VarClassRequiredAny; |
| 10102 | case TypeTableEntryIdNumLitFloat: | 10136 | case TypeTableEntryIdNumLitFloat: |
| 10103 | case TypeTableEntryIdNumLitInt: | 10137 | case TypeTableEntryIdNumLitInt: |
| ... | @@ -10840,7 +10874,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct | ... | @@ -10840,7 +10874,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct |
| 10840 | case TypeTableEntryIdUnion: | 10874 | case TypeTableEntryIdUnion: |
| 10841 | case TypeTableEntryIdFn: | 10875 | case TypeTableEntryIdFn: |
| 10842 | case TypeTableEntryIdBoundFn: | 10876 | case TypeTableEntryIdBoundFn: |
| 10843 | case TypeTableEntryIdEnumTag: | ||
| 10844 | { | 10877 | { |
| 10845 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base); | 10878 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base); |
| 10846 | TypeTableEntry *result_type = get_error_type(ira->codegen, meta_type); | 10879 | TypeTableEntry *result_type = get_error_type(ira->codegen, meta_type); |
| ... | @@ -10928,7 +10961,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op | ... | @@ -10928,7 +10961,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op |
| 10928 | case TypeTableEntryIdNamespace: | 10961 | case TypeTableEntryIdNamespace: |
| 10929 | case TypeTableEntryIdBlock: | 10962 | case TypeTableEntryIdBlock: |
| 10930 | case TypeTableEntryIdBoundFn: | 10963 | case TypeTableEntryIdBoundFn: |
| 10931 | case TypeTableEntryIdEnumTag: | ||
| 10932 | case TypeTableEntryIdArgTuple: | 10964 | case TypeTableEntryIdArgTuple: |
| 10933 | { | 10965 | { |
| 10934 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base); | 10966 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base); |
| ... | @@ -11154,8 +11186,8 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP | ... | @@ -11154,8 +11186,8 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 11154 | } | 11186 | } |
| 11155 | 11187 | ||
| 11156 | if (new_incoming_blocks.length == 0) { | 11188 | if (new_incoming_blocks.length == 0) { |
| 11157 | ir_build_const_from(ira, &phi_instruction->base); | 11189 | ir_build_unreachable_from(&ira->new_irb, &phi_instruction->base); |
| 11158 | return ira->codegen->builtin_types.entry_void; | 11190 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); |
| 11159 | } | 11191 | } |
| 11160 | 11192 | ||
| 11161 | if (new_incoming_blocks.length == 1) { | 11193 | if (new_incoming_blocks.length == 1) { |
| ... | @@ -11589,15 +11621,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -11589,15 +11621,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 11589 | field_ptr_instruction, container_ptr, container_type); | 11621 | field_ptr_instruction, container_ptr, container_type); |
| 11590 | } | 11622 | } |
| 11591 | } else if (bare_type->id == TypeTableEntryIdEnum) { | 11623 | } else if (bare_type->id == TypeTableEntryIdEnum) { |
| 11592 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); | 11624 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 11593 | if (field) { | 11625 | field_ptr_instruction, container_ptr, container_type); |
| 11594 | ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | ||
| 11595 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, | ||
| 11596 | get_abi_alignment(ira->codegen, field->type_entry), 0, 0); | ||
| 11597 | } else { | ||
| 11598 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | ||
| 11599 | field_ptr_instruction, container_ptr, container_type); | ||
| 11600 | } | ||
| 11601 | } else if (bare_type->id == TypeTableEntryIdUnion) { | 11626 | } else if (bare_type->id == TypeTableEntryIdUnion) { |
| 11602 | TypeUnionField *field = find_union_type_field(bare_type, field_name); | 11627 | TypeUnionField *field = find_union_type_field(bare_type, field_name); |
| 11603 | if (field) { | 11628 | if (field) { |
| ... | @@ -11768,20 +11793,27 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -11768,20 +11793,27 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 11768 | 11793 | ||
| 11769 | TypeEnumField *field = find_enum_type_field(child_type, field_name); | 11794 | TypeEnumField *field = find_enum_type_field(child_type, field_name); |
| 11770 | if (field) { | 11795 | if (field) { |
| 11771 | if (field->type_entry->id == TypeTableEntryIdVoid) { | 11796 | bool ptr_is_const = true; |
| 11772 | bool ptr_is_const = true; | 11797 | bool ptr_is_volatile = false; |
| 11773 | bool ptr_is_volatile = false; | 11798 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 11774 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 11799 | create_const_enum(child_type, &field->value), child_type, |
| 11775 | create_const_enum_tag(child_type, field->value), child_type, | 11800 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 11776 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | 11801 | } |
| 11777 | } else { | 11802 | } else if (child_type->id == TypeTableEntryIdUnion && |
| 11778 | bool ptr_is_const = true; | 11803 | (child_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr || |
| 11779 | bool ptr_is_volatile = false; | 11804 | child_type->data.unionation.decl_node->data.container_decl.auto_enum)) |
| 11780 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 11805 | { |
| 11781 | create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false), | 11806 | ensure_complete_type(ira->codegen, child_type); |
| 11782 | child_type->data.enumeration.tag_type, | 11807 | if (type_is_invalid(child_type)) |
| 11808 | return ira->codegen->builtin_types.entry_invalid; | ||
| 11809 | TypeUnionField *field = find_union_type_field(child_type, field_name); | ||
| 11810 | if (field) { | ||
| 11811 | TypeTableEntry *enum_type = child_type->data.unionation.tag_type; | ||
| 11812 | bool ptr_is_const = true; | ||
| 11813 | bool ptr_is_volatile = false; | ||
| 11814 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | ||
| 11815 | create_const_enum(enum_type, &field->enum_field->value), enum_type, | ||
| 11783 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | 11816 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 11784 | } | ||
| 11785 | } | 11817 | } |
| 11786 | } | 11818 | } |
| 11787 | ScopeDecls *container_scope = get_container_scope(child_type); | 11819 | ScopeDecls *container_scope = get_container_scope(child_type); |
| ... | @@ -12090,7 +12122,6 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi | ... | @@ -12090,7 +12122,6 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi |
| 12090 | case TypeTableEntryIdEnum: | 12122 | case TypeTableEntryIdEnum: |
| 12091 | case TypeTableEntryIdUnion: | 12123 | case TypeTableEntryIdUnion: |
| 12092 | case TypeTableEntryIdFn: | 12124 | case TypeTableEntryIdFn: |
| 12093 | case TypeTableEntryIdEnumTag: | ||
| 12094 | case TypeTableEntryIdArgTuple: | 12125 | case TypeTableEntryIdArgTuple: |
| 12095 | case TypeTableEntryIdOpaque: | 12126 | case TypeTableEntryIdOpaque: |
| 12096 | { | 12127 | { |
| ... | @@ -12367,21 +12398,11 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, | ... | @@ -12367,21 +12398,11 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, |
| 12367 | return ira->codegen->builtin_types.entry_invalid; | 12398 | return ira->codegen->builtin_types.entry_invalid; |
| 12368 | } | 12399 | } |
| 12369 | 12400 | ||
| 12370 | ConstExprValue *float_mode_val = get_builtin_value(ira->codegen, "FloatMode"); | ||
| 12371 | assert(float_mode_val->type->id == TypeTableEntryIdMetaType); | ||
| 12372 | TypeTableEntry *float_mode_enum_type = float_mode_val->data.x_type; | ||
| 12373 | |||
| 12374 | IrInstruction *float_mode_value = instruction->mode_value->other; | 12401 | IrInstruction *float_mode_value = instruction->mode_value->other; |
| 12375 | if (type_is_invalid(float_mode_value->value.type)) | ||
| 12376 | return ira->codegen->builtin_types.entry_invalid; | ||
| 12377 | IrInstruction *casted_value = ir_implicit_cast(ira, float_mode_value, float_mode_enum_type); | ||
| 12378 | if (type_is_invalid(casted_value->value.type)) | ||
| 12379 | return ira->codegen->builtin_types.entry_invalid; | ||
| 12380 | ConstExprValue *mode_val = ir_resolve_const(ira, casted_value, UndefBad); | ||
| 12381 | if (!mode_val) | ||
| 12382 | return ira->codegen->builtin_types.entry_invalid; | ||
| 12383 | 12402 | ||
| 12384 | bool want_fast_math = (mode_val->data.x_enum.tag == FloatModeOptimized); | 12403 | FloatMode float_mode_scalar; |
| 12404 | if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar)) | ||
| 12405 | return ira->codegen->builtin_types.entry_invalid; | ||
| 12385 | 12406 | ||
| 12386 | AstNode *source_node = instruction->base.source_node; | 12407 | AstNode *source_node = instruction->base.source_node; |
| 12387 | if (*fast_math_set_node_ptr) { | 12408 | if (*fast_math_set_node_ptr) { |
| ... | @@ -12391,7 +12412,7 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, | ... | @@ -12391,7 +12412,7 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, |
| 12391 | return ira->codegen->builtin_types.entry_invalid; | 12412 | return ira->codegen->builtin_types.entry_invalid; |
| 12392 | } | 12413 | } |
| 12393 | *fast_math_set_node_ptr = source_node; | 12414 | *fast_math_set_node_ptr = source_node; |
| 12394 | *fast_math_off_ptr = !want_fast_math; | 12415 | *fast_math_off_ptr = (float_mode_scalar == FloatModeStrict); |
| 12395 | 12416 | ||
| 12396 | ir_build_const_from(ira, &instruction->base); | 12417 | ir_build_const_from(ira, &instruction->base); |
| 12397 | return ira->codegen->builtin_types.entry_void; | 12418 | return ira->codegen->builtin_types.entry_void; |
| ... | @@ -12448,7 +12469,6 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, | ... | @@ -12448,7 +12469,6 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 12448 | case TypeTableEntryIdFn: | 12469 | case TypeTableEntryIdFn: |
| 12449 | case TypeTableEntryIdNamespace: | 12470 | case TypeTableEntryIdNamespace: |
| 12450 | case TypeTableEntryIdBoundFn: | 12471 | case TypeTableEntryIdBoundFn: |
| 12451 | case TypeTableEntryIdEnumTag: | ||
| 12452 | { | 12472 | { |
| 12453 | type_ensure_zero_bits_known(ira->codegen, child_type); | 12473 | type_ensure_zero_bits_known(ira->codegen, child_type); |
| 12454 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type, | 12474 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| ... | @@ -12557,7 +12577,6 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, | ... | @@ -12557,7 +12577,6 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 12557 | case TypeTableEntryIdFn: | 12577 | case TypeTableEntryIdFn: |
| 12558 | case TypeTableEntryIdNamespace: | 12578 | case TypeTableEntryIdNamespace: |
| 12559 | case TypeTableEntryIdBoundFn: | 12579 | case TypeTableEntryIdBoundFn: |
| 12560 | case TypeTableEntryIdEnumTag: | ||
| 12561 | { | 12580 | { |
| 12562 | TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size); | 12581 | TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size); |
| 12563 | ConstExprValue *out_val = ir_build_const_from(ira, &array_type_instruction->base); | 12582 | ConstExprValue *out_val = ir_build_const_from(ira, &array_type_instruction->base); |
| ... | @@ -12608,7 +12627,6 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, | ... | @@ -12608,7 +12627,6 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 12608 | case TypeTableEntryIdPureError: | 12627 | case TypeTableEntryIdPureError: |
| 12609 | case TypeTableEntryIdEnum: | 12628 | case TypeTableEntryIdEnum: |
| 12610 | case TypeTableEntryIdUnion: | 12629 | case TypeTableEntryIdUnion: |
| 12611 | case TypeTableEntryIdEnumTag: | ||
| 12612 | case TypeTableEntryIdFn: | 12630 | case TypeTableEntryIdFn: |
| 12613 | { | 12631 | { |
| 12614 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); | 12632 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); |
| ... | @@ -12761,17 +12779,22 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC | ... | @@ -12761,17 +12779,22 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC |
| 12761 | } | 12779 | } |
| 12762 | } | 12780 | } |
| 12763 | 12781 | ||
| 12764 | static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) { | 12782 | static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) { |
| 12765 | if (type_is_invalid(value->value.type)) | 12783 | if (type_is_invalid(value->value.type)) |
| 12766 | return ira->codegen->invalid_instruction; | 12784 | return ira->codegen->invalid_instruction; |
| 12767 | 12785 | ||
| 12768 | if (value->value.type->id != TypeTableEntryIdEnum) { | 12786 | if (value->value.type->id == TypeTableEntryIdEnum) { |
| 12787 | return value; | ||
| 12788 | } | ||
| 12789 | |||
| 12790 | if (value->value.type->id != TypeTableEntryIdUnion) { | ||
| 12769 | ir_add_error(ira, source_instr, | 12791 | ir_add_error(ira, source_instr, |
| 12770 | buf_sprintf("expected enum type, found '%s'", buf_ptr(&value->value.type->name))); | 12792 | buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value.type->name))); |
| 12771 | return ira->codegen->invalid_instruction; | 12793 | return ira->codegen->invalid_instruction; |
| 12772 | } | 12794 | } |
| 12773 | 12795 | ||
| 12774 | TypeTableEntry *tag_type = value->value.type->data.enumeration.tag_type; | 12796 | TypeTableEntry *tag_type = value->value.type->data.unionation.tag_type; |
| 12797 | assert(tag_type->id == TypeTableEntryIdEnum); | ||
| 12775 | 12798 | ||
| 12776 | if (instr_is_comptime(value)) { | 12799 | if (instr_is_comptime(value)) { |
| 12777 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | 12800 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| ... | @@ -12782,11 +12805,11 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -12782,11 +12805,11 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ |
| 12782 | source_instr->scope, source_instr->source_node); | 12805 | source_instr->scope, source_instr->source_node); |
| 12783 | const_instruction->base.value.type = tag_type; | 12806 | const_instruction->base.value.type = tag_type; |
| 12784 | const_instruction->base.value.special = ConstValSpecialStatic; | 12807 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 12785 | bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, val->data.x_enum.tag); | 12808 | bigint_init_bigint(&const_instruction->base.value.data.x_enum_tag, &val->data.x_union.tag); |
| 12786 | return &const_instruction->base; | 12809 | return &const_instruction->base; |
| 12787 | } | 12810 | } |
| 12788 | 12811 | ||
| 12789 | IrInstruction *result = ir_build_enum_tag(&ira->new_irb, source_instr->scope, source_instr->source_node, value); | 12812 | IrInstruction *result = ir_build_union_tag(&ira->new_irb, source_instr->scope, source_instr->source_node, value); |
| 12790 | result->value.type = tag_type; | 12813 | result->value.type = tag_type; |
| 12791 | return result; | 12814 | return result; |
| 12792 | } | 12815 | } |
| ... | @@ -12817,7 +12840,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, | ... | @@ -12817,7 +12840,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 12817 | return ir_unreach_error(ira); | 12840 | return ir_unreach_error(ira); |
| 12818 | 12841 | ||
| 12819 | if (case_value->value.type->id == TypeTableEntryIdEnum) { | 12842 | if (case_value->value.type->id == TypeTableEntryIdEnum) { |
| 12820 | case_value = ir_analyze_enum_tag(ira, &switch_br_instruction->base, case_value); | 12843 | case_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, case_value); |
| 12821 | if (type_is_invalid(case_value->value.type)) | 12844 | if (type_is_invalid(case_value->value.type)) |
| 12822 | return ir_unreach_error(ira); | 12845 | return ir_unreach_error(ira); |
| 12823 | } | 12846 | } |
| ... | @@ -12864,7 +12887,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, | ... | @@ -12864,7 +12887,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 12864 | continue; | 12887 | continue; |
| 12865 | 12888 | ||
| 12866 | if (new_value->value.type->id == TypeTableEntryIdEnum) { | 12889 | if (new_value->value.type->id == TypeTableEntryIdEnum) { |
| 12867 | new_value = ir_analyze_enum_tag(ira, &switch_br_instruction->base, new_value); | 12890 | new_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, new_value); |
| 12868 | if (type_is_invalid(new_value->value.type)) | 12891 | if (type_is_invalid(new_value->value.type)) |
| 12869 | continue; | 12892 | continue; |
| 12870 | } | 12893 | } |
| ... | @@ -12946,34 +12969,57 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -12946,34 +12969,57 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 12946 | 12969 | ||
| 12947 | ir_build_load_ptr_from(&ira->new_irb, &switch_target_instruction->base, target_value_ptr); | 12970 | ir_build_load_ptr_from(&ira->new_irb, &switch_target_instruction->base, target_value_ptr); |
| 12948 | return target_type; | 12971 | return target_type; |
| 12949 | case TypeTableEntryIdEnum: | 12972 | case TypeTableEntryIdUnion: { |
| 12973 | AstNode *decl_node = target_type->data.unionation.decl_node; | ||
| 12974 | if (!decl_node->data.container_decl.auto_enum && | ||
| 12975 | decl_node->data.container_decl.init_arg_expr == nullptr) | ||
| 12950 | { | 12976 | { |
| 12951 | TypeTableEntry *tag_type = target_type->data.enumeration.tag_type; | 12977 | ErrorMsg *msg = ir_add_error(ira, target_value_ptr, |
| 12952 | assert(tag_type != nullptr); | 12978 | buf_sprintf("switch on union which has no attached enum")); |
| 12953 | if (pointee_val) { | 12979 | add_error_note(ira->codegen, msg, decl_node, |
| 12954 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); | 12980 | buf_sprintf("consider 'union(enum)' here")); |
| 12955 | bigint_init_unsigned(&out_val->data.x_bigint, pointee_val->data.x_enum.tag); | 12981 | return ira->codegen->builtin_types.entry_invalid; |
| 12956 | return tag_type; | 12982 | } |
| 12957 | } | 12983 | TypeTableEntry *tag_type = target_type->data.unionation.tag_type; |
| 12958 | 12984 | assert(tag_type != nullptr); | |
| 12959 | IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, | 12985 | if (pointee_val) { |
| 12960 | switch_target_instruction->base.source_node, target_value_ptr); | 12986 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); |
| 12961 | enum_value->value.type = target_type; | 12987 | bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_union.tag); |
| 12962 | ir_build_enum_tag_from(&ira->new_irb, &switch_target_instruction->base, enum_value); | ||
| 12963 | return tag_type; | 12988 | return tag_type; |
| 12964 | } | 12989 | } |
| 12990 | |||
| 12991 | IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, | ||
| 12992 | switch_target_instruction->base.source_node, target_value_ptr); | ||
| 12993 | union_value->value.type = target_type; | ||
| 12994 | |||
| 12995 | IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope, | ||
| 12996 | switch_target_instruction->base.source_node, union_value); | ||
| 12997 | union_tag_inst->value.type = tag_type; | ||
| 12998 | ir_link_new_instruction(union_tag_inst, &switch_target_instruction->base); | ||
| 12999 | return tag_type; | ||
| 13000 | } | ||
| 13001 | case TypeTableEntryIdEnum: { | ||
| 13002 | if (pointee_val) { | ||
| 13003 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); | ||
| 13004 | bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_enum_tag); | ||
| 13005 | return target_type; | ||
| 13006 | } | ||
| 13007 | |||
| 13008 | IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, | ||
| 13009 | switch_target_instruction->base.source_node, target_value_ptr); | ||
| 13010 | enum_value->value.type = target_type; | ||
| 13011 | ir_link_new_instruction(enum_value, &switch_target_instruction->base); | ||
| 13012 | return target_type; | ||
| 13013 | } | ||
| 12965 | case TypeTableEntryIdErrorUnion: | 13014 | case TypeTableEntryIdErrorUnion: |
| 12966 | // see https://github.com/andrewrk/zig/issues/83 | 13015 | // see https://github.com/andrewrk/zig/issues/632 |
| 12967 | zig_panic("TODO switch on error union"); | 13016 | zig_panic("TODO switch on error union"); |
| 12968 | case TypeTableEntryIdEnumTag: | ||
| 12969 | zig_panic("TODO switch on enum tag type"); | ||
| 12970 | case TypeTableEntryIdUnreachable: | 13017 | case TypeTableEntryIdUnreachable: |
| 12971 | case TypeTableEntryIdArray: | 13018 | case TypeTableEntryIdArray: |
| 12972 | case TypeTableEntryIdStruct: | 13019 | case TypeTableEntryIdStruct: |
| 12973 | case TypeTableEntryIdUndefLit: | 13020 | case TypeTableEntryIdUndefLit: |
| 12974 | case TypeTableEntryIdNullLit: | 13021 | case TypeTableEntryIdNullLit: |
| 12975 | case TypeTableEntryIdMaybe: | 13022 | case TypeTableEntryIdMaybe: |
| 12976 | case TypeTableEntryIdUnion: | ||
| 12977 | case TypeTableEntryIdBlock: | 13023 | case TypeTableEntryIdBlock: |
| 12978 | case TypeTableEntryIdBoundFn: | 13024 | case TypeTableEntryIdBoundFn: |
| 12979 | case TypeTableEntryIdArgTuple: | 13025 | case TypeTableEntryIdArgTuple: |
| ... | @@ -12996,19 +13042,13 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr | ... | @@ -12996,19 +13042,13 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr |
| 12996 | 13042 | ||
| 12997 | assert(target_value_ptr->value.type->id == TypeTableEntryIdPointer); | 13043 | assert(target_value_ptr->value.type->id == TypeTableEntryIdPointer); |
| 12998 | TypeTableEntry *target_type = target_value_ptr->value.type->data.pointer.child_type; | 13044 | TypeTableEntry *target_type = target_value_ptr->value.type->data.pointer.child_type; |
| 12999 | if (target_type->id == TypeTableEntryIdEnum) { | 13045 | if (target_type->id == TypeTableEntryIdUnion) { |
| 13000 | ConstExprValue *prong_val = ir_resolve_const(ira, prong_value, UndefBad); | 13046 | ConstExprValue *prong_val = ir_resolve_const(ira, prong_value, UndefBad); |
| 13001 | if (!prong_val) | 13047 | if (!prong_val) |
| 13002 | return ira->codegen->builtin_types.entry_invalid; | 13048 | return ira->codegen->builtin_types.entry_invalid; |
| 13003 | 13049 | ||
| 13004 | TypeEnumField *field; | 13050 | assert(prong_value->value.type->id == TypeTableEntryIdEnum); |
| 13005 | if (prong_value->value.type->id == TypeTableEntryIdEnumTag) { | 13051 | TypeUnionField *field = find_union_field_by_tag(target_type, &prong_val->data.x_enum_tag); |
| 13006 | field = &target_type->data.enumeration.fields[bigint_as_unsigned(&prong_val->data.x_bigint)]; | ||
| 13007 | } else if (prong_value->value.type->id == TypeTableEntryIdEnum) { | ||
| 13008 | field = &target_type->data.enumeration.fields[prong_val->data.x_enum.tag]; | ||
| 13009 | } else { | ||
| 13010 | zig_unreachable(); | ||
| 13011 | } | ||
| 13012 | 13052 | ||
| 13013 | if (instr_is_comptime(target_value_ptr)) { | 13053 | if (instr_is_comptime(target_value_ptr)) { |
| 13014 | ConstExprValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad); | 13054 | ConstExprValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad); |
| ... | @@ -13019,11 +13059,11 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr | ... | @@ -13019,11 +13059,11 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr |
| 13019 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 13059 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 13020 | out_val->data.x_ptr.special = ConstPtrSpecialRef; | 13060 | out_val->data.x_ptr.special = ConstPtrSpecialRef; |
| 13021 | out_val->data.x_ptr.mut = target_val_ptr->data.x_ptr.mut; | 13061 | out_val->data.x_ptr.mut = target_val_ptr->data.x_ptr.mut; |
| 13022 | out_val->data.x_ptr.data.ref.pointee = pointee_val->data.x_enum.payload; | 13062 | out_val->data.x_ptr.data.ref.pointee = pointee_val->data.x_union.payload; |
| 13023 | return get_pointer_to_type(ira->codegen, field->type_entry, target_val_ptr->type->data.pointer.is_const); | 13063 | return get_pointer_to_type(ira->codegen, field->type_entry, target_val_ptr->type->data.pointer.is_const); |
| 13024 | } | 13064 | } |
| 13025 | 13065 | ||
| 13026 | ir_build_enum_field_ptr_from(&ira->new_irb, &instruction->base, target_value_ptr, field); | 13066 | ir_build_union_field_ptr_from(&ira->new_irb, &instruction->base, target_value_ptr, field); |
| 13027 | return get_pointer_to_type(ira->codegen, field->type_entry, | 13067 | return get_pointer_to_type(ira->codegen, field->type_entry, |
| 13028 | target_value_ptr->value.type->data.pointer.is_const); | 13068 | target_value_ptr->value.type->data.pointer.is_const); |
| 13029 | } else { | 13069 | } else { |
| ... | @@ -13033,10 +13073,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr | ... | @@ -13033,10 +13073,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr |
| 13033 | } | 13073 | } |
| 13034 | } | 13074 | } |
| 13035 | 13075 | ||
| 13036 | static TypeTableEntry *ir_analyze_instruction_enum_tag(IrAnalyze *ira, IrInstructionEnumTag *enum_tag_instruction) { | 13076 | static TypeTableEntry *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) { |
| 13037 | IrInstruction *value = enum_tag_instruction->value->other; | 13077 | IrInstruction *value = instruction->value->other; |
| 13038 | IrInstruction *new_instruction = ir_analyze_enum_tag(ira, &enum_tag_instruction->base, value); | 13078 | IrInstruction *new_instruction = ir_analyze_union_tag(ira, &instruction->base, value); |
| 13039 | ir_link_new_instruction(new_instruction, &enum_tag_instruction->base); | 13079 | ir_link_new_instruction(new_instruction, &instruction->base); |
| 13040 | return new_instruction->value.type; | 13080 | return new_instruction->value.type; |
| 13041 | } | 13081 | } |
| 13042 | 13082 | ||
| ... | @@ -13192,7 +13232,7 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir | ... | @@ -13192,7 +13232,7 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir |
| 13192 | 13232 | ||
| 13193 | ConstExprValue *out_val = ir_build_const_from(ira, instruction); | 13233 | ConstExprValue *out_val = ir_build_const_from(ira, instruction); |
| 13194 | out_val->data.x_union.payload = field_val; | 13234 | out_val->data.x_union.payload = field_val; |
| 13195 | out_val->data.x_union.tag = type_field->value; | 13235 | out_val->data.x_union.tag = type_field->enum_field->value; |
| 13196 | 13236 | ||
| 13197 | ConstParent *parent = get_const_val_parent(ira->codegen, field_val); | 13237 | ConstParent *parent = get_const_val_parent(ira->codegen, field_val); |
| 13198 | if (parent != nullptr) { | 13238 | if (parent != nullptr) { |
| ... | @@ -13439,46 +13479,9 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira | ... | @@ -13439,46 +13479,9 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira |
| 13439 | buf_ptr(&container_type->name))); | 13479 | buf_ptr(&container_type->name))); |
| 13440 | return ira->codegen->builtin_types.entry_invalid; | 13480 | return ira->codegen->builtin_types.entry_invalid; |
| 13441 | } | 13481 | } |
| 13442 | } else if (container_type_value->value.type->id == TypeTableEntryIdEnumTag) { | ||
| 13443 | if (elem_count != 1) { | ||
| 13444 | ir_add_error(ira, &instruction->base, buf_sprintf("enum initialization requires exactly one element")); | ||
| 13445 | return ira->codegen->builtin_types.entry_invalid; | ||
| 13446 | } | ||
| 13447 | ConstExprValue *tag_value = ir_resolve_const(ira, container_type_value, UndefBad); | ||
| 13448 | if (!tag_value) | ||
| 13449 | return ira->codegen->builtin_types.entry_invalid; | ||
| 13450 | |||
| 13451 | TypeTableEntry *enum_type = container_type_value->value.type->data.enum_tag.enum_type; | ||
| 13452 | |||
| 13453 | uint64_t tag_uint = bigint_as_unsigned(&tag_value->data.x_bigint); | ||
| 13454 | TypeEnumField *field = &enum_type->data.enumeration.fields[tag_uint]; | ||
| 13455 | TypeTableEntry *this_field_type = field->type_entry; | ||
| 13456 | |||
| 13457 | IrInstruction *init_value = instruction->items[0]->other; | ||
| 13458 | if (type_is_invalid(init_value->value.type)) | ||
| 13459 | return ira->codegen->builtin_types.entry_invalid; | ||
| 13460 | |||
| 13461 | IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, this_field_type); | ||
| 13462 | if (casted_init_value == ira->codegen->invalid_instruction) | ||
| 13463 | return ira->codegen->builtin_types.entry_invalid; | ||
| 13464 | |||
| 13465 | if (instr_is_comptime(casted_init_value)) { | ||
| 13466 | ConstExprValue *init_val = ir_resolve_const(ira, casted_init_value, UndefOk); | ||
| 13467 | if (!init_val) | ||
| 13468 | return ira->codegen->builtin_types.entry_invalid; | ||
| 13469 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 13470 | out_val->data.x_enum.tag = tag_uint; | ||
| 13471 | out_val->data.x_enum.payload = init_val; | ||
| 13472 | return enum_type; | ||
| 13473 | } | ||
| 13474 | |||
| 13475 | IrInstruction *new_instruction = ir_build_init_enum_from(&ira->new_irb, &instruction->base, | ||
| 13476 | enum_type, field, casted_init_value); | ||
| 13477 | ir_add_alloca(ira, new_instruction, enum_type); | ||
| 13478 | return enum_type; | ||
| 13479 | } else { | 13482 | } else { |
| 13480 | ir_add_error(ira, container_type_value, | 13483 | ir_add_error(ira, container_type_value, |
| 13481 | buf_sprintf("expected type, found '%s'", buf_ptr(&container_type_value->value.type->name))); | 13484 | buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name))); |
| 13482 | return ira->codegen->builtin_types.entry_invalid; | 13485 | return ira->codegen->builtin_types.entry_invalid; |
| 13483 | } | 13486 | } |
| 13484 | } | 13487 | } |
| ... | @@ -13521,8 +13524,8 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -13521,8 +13524,8 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ |
| 13521 | eval_min_max_value(ira->codegen, target_type, out_val, is_max); | 13524 | eval_min_max_value(ira->codegen, target_type, out_val, is_max); |
| 13522 | return target_type; | 13525 | return target_type; |
| 13523 | } | 13526 | } |
| 13524 | case TypeTableEntryIdEnumTag: | 13527 | case TypeTableEntryIdEnum: |
| 13525 | zig_panic("TODO min/max value for enum tag type"); | 13528 | zig_panic("TODO min/max value for enum type"); |
| 13526 | case TypeTableEntryIdVar: | 13529 | case TypeTableEntryIdVar: |
| 13527 | case TypeTableEntryIdMetaType: | 13530 | case TypeTableEntryIdMetaType: |
| 13528 | case TypeTableEntryIdUnreachable: | 13531 | case TypeTableEntryIdUnreachable: |
| ... | @@ -13536,7 +13539,6 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -13536,7 +13539,6 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ |
| 13536 | case TypeTableEntryIdMaybe: | 13539 | case TypeTableEntryIdMaybe: |
| 13537 | case TypeTableEntryIdErrorUnion: | 13540 | case TypeTableEntryIdErrorUnion: |
| 13538 | case TypeTableEntryIdPureError: | 13541 | case TypeTableEntryIdPureError: |
| 13539 | case TypeTableEntryIdEnum: | ||
| 13540 | case TypeTableEntryIdUnion: | 13542 | case TypeTableEntryIdUnion: |
| 13541 | case TypeTableEntryIdFn: | 13543 | case TypeTableEntryIdFn: |
| 13542 | case TypeTableEntryIdNamespace: | 13544 | case TypeTableEntryIdNamespace: |
| ... | @@ -13639,29 +13641,27 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc | ... | @@ -13639,29 +13641,27 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc |
| 13639 | return str_type; | 13641 | return str_type; |
| 13640 | } | 13642 | } |
| 13641 | 13643 | ||
| 13642 | static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructionEnumTagName *instruction) { | 13644 | static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructionTagName *instruction) { |
| 13643 | IrInstruction *target = instruction->target->other; | 13645 | IrInstruction *target = instruction->target->other; |
| 13644 | if (type_is_invalid(target->value.type)) | 13646 | if (type_is_invalid(target->value.type)) |
| 13645 | return ira->codegen->builtin_types.entry_invalid; | 13647 | return ira->codegen->builtin_types.entry_invalid; |
| 13646 | 13648 | ||
| 13647 | assert(target->value.type->id == TypeTableEntryIdEnumTag); | 13649 | assert(target->value.type->id == TypeTableEntryIdEnum); |
| 13648 | 13650 | ||
| 13649 | if (instr_is_comptime(target)) { | 13651 | if (instr_is_comptime(target)) { |
| 13650 | TypeTableEntry *enum_type = target->value.type->data.enum_tag.enum_type; | 13652 | TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint); |
| 13651 | uint64_t tag_value = bigint_as_unsigned(&target->value.data.x_bigint); | ||
| 13652 | TypeEnumField *field = &enum_type->data.enumeration.fields[tag_value]; | ||
| 13653 | ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name); | 13653 | ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name); |
| 13654 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 13654 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 13655 | init_const_slice(ira->codegen, out_val, array_val, 0, buf_len(field->name), true); | 13655 | init_const_slice(ira->codegen, out_val, array_val, 0, buf_len(field->name), true); |
| 13656 | return out_val->type; | 13656 | return out_val->type; |
| 13657 | } | 13657 | } |
| 13658 | 13658 | ||
| 13659 | if (!target->value.type->data.enum_tag.generate_name_table) { | 13659 | if (!target->value.type->data.enumeration.generate_name_table) { |
| 13660 | target->value.type->data.enum_tag.generate_name_table = true; | 13660 | target->value.type->data.enumeration.generate_name_table = true; |
| 13661 | ira->codegen->name_table_enums.append(target->value.type); | 13661 | ira->codegen->name_table_enums.append(target->value.type); |
| 13662 | } | 13662 | } |
| 13663 | 13663 | ||
| 13664 | IrInstruction *result = ir_build_enum_tag_name(&ira->new_irb, instruction->base.scope, | 13664 | IrInstruction *result = ir_build_tag_name(&ira->new_irb, instruction->base.scope, |
| 13665 | instruction->base.source_node, target); | 13665 | instruction->base.source_node, target); |
| 13666 | ir_link_new_instruction(result, &instruction->base); | 13666 | ir_link_new_instruction(result, &instruction->base); |
| 13667 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | 13667 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); |
| ... | @@ -13806,7 +13806,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira, | ... | @@ -13806,7 +13806,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira, |
| 13806 | TypeTableEntry *result_type = var_value->data.x_type; | 13806 | TypeTableEntry *result_type = var_value->data.x_type; |
| 13807 | 13807 | ||
| 13808 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 13808 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 13809 | out_val->data.x_enum.tag = type_id_index(type_entry->id); | 13809 | bigint_init_unsigned(&out_val->data.x_enum_tag, type_id_index(type_entry->id)); |
| 13810 | return result_type; | 13810 | return result_type; |
| 13811 | } | 13811 | } |
| 13812 | 13812 | ||
| ... | @@ -13870,7 +13870,10 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc | ... | @@ -13870,7 +13870,10 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc |
| 13870 | 13870 | ||
| 13871 | int err; | 13871 | int err; |
| 13872 | if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) { | 13872 | if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) { |
| 13873 | zig_panic("unable to parse C file: %s\n", err_str(err)); | 13873 | if (err != ErrorCCompileErrors) { |
| 13874 | ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); | ||
| 13875 | return ira->codegen->builtin_types.entry_invalid; | ||
| 13876 | } | ||
| 13874 | } | 13877 | } |
| 13875 | 13878 | ||
| 13876 | if (errors.length > 0) { | 13879 | if (errors.length > 0) { |
| ... | @@ -14632,14 +14635,14 @@ static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInst | ... | @@ -14632,14 +14635,14 @@ static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInst |
| 14632 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 14635 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 14633 | out_val->data.x_type = field->type_entry; | 14636 | out_val->data.x_type = field->type_entry; |
| 14634 | return ira->codegen->builtin_types.entry_type; | 14637 | return ira->codegen->builtin_types.entry_type; |
| 14635 | } else if (container_type->id == TypeTableEntryIdEnum) { | 14638 | } else if (container_type->id == TypeTableEntryIdUnion) { |
| 14636 | if (member_index >= container_type->data.enumeration.src_field_count) { | 14639 | if (member_index >= container_type->data.unionation.src_field_count) { |
| 14637 | ir_add_error(ira, index_value, | 14640 | ir_add_error(ira, index_value, |
| 14638 | buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", | 14641 | buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", |
| 14639 | member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count)); | 14642 | member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count)); |
| 14640 | return ira->codegen->builtin_types.entry_invalid; | 14643 | return ira->codegen->builtin_types.entry_invalid; |
| 14641 | } | 14644 | } |
| 14642 | TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; | 14645 | TypeUnionField *field = &container_type->data.unionation.fields[member_index]; |
| 14643 | 14646 | ||
| 14644 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 14647 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 14645 | out_val->data.x_type = field->type_entry; | 14648 | out_val->data.x_type = field->type_entry; |
| ... | @@ -14683,6 +14686,18 @@ static TypeTableEntry *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInst | ... | @@ -14683,6 +14686,18 @@ static TypeTableEntry *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInst |
| 14683 | } | 14686 | } |
| 14684 | TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; | 14687 | TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; |
| 14685 | 14688 | ||
| 14689 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 14690 | init_const_str_lit(ira->codegen, out_val, field->name); | ||
| 14691 | return out_val->type; | ||
| 14692 | } else if (container_type->id == TypeTableEntryIdUnion) { | ||
| 14693 | if (member_index >= container_type->data.unionation.src_field_count) { | ||
| 14694 | ir_add_error(ira, index_value, | ||
| 14695 | buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", | ||
| 14696 | member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count)); | ||
| 14697 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14698 | } | ||
| 14699 | TypeUnionField *field = &container_type->data.unionation.fields[member_index]; | ||
| 14700 | |||
| 14686 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 14701 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 14687 | init_const_str_lit(ira->codegen, out_val, field->name); | 14702 | init_const_str_lit(ira->codegen, out_val, field->name); |
| 14688 | return out_val->type; | 14703 | return out_val->type; |
| ... | @@ -14753,7 +14768,6 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc | ... | @@ -14753,7 +14768,6 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc |
| 14753 | case TypeTableEntryIdErrorUnion: | 14768 | case TypeTableEntryIdErrorUnion: |
| 14754 | case TypeTableEntryIdPureError: | 14769 | case TypeTableEntryIdPureError: |
| 14755 | case TypeTableEntryIdEnum: | 14770 | case TypeTableEntryIdEnum: |
| 14756 | case TypeTableEntryIdEnumTag: | ||
| 14757 | case TypeTableEntryIdUnion: | 14771 | case TypeTableEntryIdUnion: |
| 14758 | case TypeTableEntryIdFn: | 14772 | case TypeTableEntryIdFn: |
| 14759 | { | 14773 | { |
| ... | @@ -15059,9 +15073,10 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira | ... | @@ -15059,9 +15073,10 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira |
| 15059 | if (type_is_invalid(switch_type)) | 15073 | if (type_is_invalid(switch_type)) |
| 15060 | return ira->codegen->builtin_types.entry_invalid; | 15074 | return ira->codegen->builtin_types.entry_invalid; |
| 15061 | 15075 | ||
| 15062 | if (switch_type->id == TypeTableEntryIdEnumTag) { | 15076 | if (switch_type->id == TypeTableEntryIdEnum) { |
| 15063 | TypeTableEntry *enum_type = switch_type->data.enum_tag.enum_type; | 15077 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {}; |
| 15064 | AstNode **field_prev_uses = allocate<AstNode *>(enum_type->data.enumeration.src_field_count); | 15078 | field_prev_uses.init(switch_type->data.enumeration.src_field_count); |
| 15079 | |||
| 15065 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { | 15080 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { |
| 15066 | IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; | 15081 | IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; |
| 15067 | 15082 | ||
| ... | @@ -15073,41 +15088,43 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira | ... | @@ -15073,41 +15088,43 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira |
| 15073 | if (type_is_invalid(end_value->value.type)) | 15088 | if (type_is_invalid(end_value->value.type)) |
| 15074 | return ira->codegen->builtin_types.entry_invalid; | 15089 | return ira->codegen->builtin_types.entry_invalid; |
| 15075 | 15090 | ||
| 15076 | size_t start_index; | 15091 | assert(start_value->value.type->id == TypeTableEntryIdEnum); |
| 15077 | size_t end_index; | 15092 | BigInt start_index; |
| 15078 | if (start_value->value.type->id == TypeTableEntryIdEnumTag) { | 15093 | bigint_init_bigint(&start_index, &start_value->value.data.x_enum_tag); |
| 15079 | start_index = bigint_as_unsigned(&start_value->value.data.x_bigint); | ||
| 15080 | } else if (start_value->value.type->id == TypeTableEntryIdEnum) { | ||
| 15081 | start_index = start_value->value.data.x_enum.tag; | ||
| 15082 | } else { | ||
| 15083 | zig_unreachable(); | ||
| 15084 | } | ||
| 15085 | if (end_value->value.type->id == TypeTableEntryIdEnumTag) { | ||
| 15086 | end_index = bigint_as_unsigned(&end_value->value.data.x_bigint); | ||
| 15087 | } else if (end_value->value.type->id == TypeTableEntryIdEnum) { | ||
| 15088 | end_index = end_value->value.data.x_enum.tag; | ||
| 15089 | } else { | ||
| 15090 | zig_unreachable(); | ||
| 15091 | } | ||
| 15092 | 15094 | ||
| 15093 | for (size_t field_index = start_index; field_index <= end_index; field_index += 1) { | 15095 | assert(end_value->value.type->id == TypeTableEntryIdEnum); |
| 15094 | AstNode *prev_node = field_prev_uses[field_index]; | 15096 | BigInt end_index; |
| 15095 | if (prev_node != nullptr) { | 15097 | bigint_init_bigint(&end_index, &end_value->value.data.x_enum_tag); |
| 15096 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_index]; | 15098 | |
| 15099 | BigInt field_index; | ||
| 15100 | bigint_init_bigint(&field_index, &start_index); | ||
| 15101 | for (;;) { | ||
| 15102 | Cmp cmp = bigint_cmp(&field_index, &end_index); | ||
| 15103 | if (cmp == CmpGT) { | ||
| 15104 | break; | ||
| 15105 | } | ||
| 15106 | auto entry = field_prev_uses.put_unique(field_index, start_value->source_node); | ||
| 15107 | if (entry) { | ||
| 15108 | AstNode *prev_node = entry->value; | ||
| 15109 | TypeEnumField *enum_field = find_enum_field_by_tag(switch_type, &field_index); | ||
| 15110 | assert(enum_field != nullptr); | ||
| 15097 | ErrorMsg *msg = ir_add_error(ira, start_value, | 15111 | ErrorMsg *msg = ir_add_error(ira, start_value, |
| 15098 | buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&enum_type->name), | 15112 | buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&switch_type->name), |
| 15099 | buf_ptr(type_enum_field->name))); | 15113 | buf_ptr(enum_field->name))); |
| 15100 | add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here")); | 15114 | add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here")); |
| 15101 | } | 15115 | } |
| 15102 | field_prev_uses[field_index] = start_value->source_node; | 15116 | bigint_incr(&field_index); |
| 15103 | } | 15117 | } |
| 15104 | } | 15118 | } |
| 15105 | if (!instruction->have_else_prong) { | 15119 | if (!instruction->have_else_prong) { |
| 15106 | for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { | 15120 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { |
| 15107 | if (field_prev_uses[i] == nullptr) { | 15121 | TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; |
| 15122 | |||
| 15123 | auto entry = field_prev_uses.maybe_get(enum_field->value); | ||
| 15124 | if (!entry) { | ||
| 15108 | ir_add_error(ira, &instruction->base, | 15125 | ir_add_error(ira, &instruction->base, |
| 15109 | buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&enum_type->name), | 15126 | buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&switch_type->name), |
| 15110 | buf_ptr(enum_type->data.enumeration.fields[i].name))); | 15127 | buf_ptr(enum_field->name))); |
| 15111 | } | 15128 | } |
| 15112 | } | 15129 | } |
| 15113 | } | 15130 | } |
| ... | @@ -15402,8 +15419,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -15402,8 +15419,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 15402 | zig_panic("TODO buf_write_value_bytes pure error type"); | 15419 | zig_panic("TODO buf_write_value_bytes pure error type"); |
| 15403 | case TypeTableEntryIdEnum: | 15420 | case TypeTableEntryIdEnum: |
| 15404 | zig_panic("TODO buf_write_value_bytes enum type"); | 15421 | zig_panic("TODO buf_write_value_bytes enum type"); |
| 15405 | case TypeTableEntryIdEnumTag: | ||
| 15406 | zig_panic("TODO buf_write_value_bytes enum tag type"); | ||
| 15407 | case TypeTableEntryIdFn: | 15422 | case TypeTableEntryIdFn: |
| 15408 | zig_panic("TODO buf_write_value_bytes fn type"); | 15423 | zig_panic("TODO buf_write_value_bytes fn type"); |
| 15409 | case TypeTableEntryIdUnion: | 15424 | case TypeTableEntryIdUnion: |
| ... | @@ -15462,8 +15477,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -15462,8 +15477,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 15462 | zig_panic("TODO buf_read_value_bytes pure error type"); | 15477 | zig_panic("TODO buf_read_value_bytes pure error type"); |
| 15463 | case TypeTableEntryIdEnum: | 15478 | case TypeTableEntryIdEnum: |
| 15464 | zig_panic("TODO buf_read_value_bytes enum type"); | 15479 | zig_panic("TODO buf_read_value_bytes enum type"); |
| 15465 | case TypeTableEntryIdEnumTag: | ||
| 15466 | zig_panic("TODO buf_read_value_bytes enum tag type"); | ||
| 15467 | case TypeTableEntryIdFn: | 15480 | case TypeTableEntryIdFn: |
| 15468 | zig_panic("TODO buf_read_value_bytes fn type"); | 15481 | zig_panic("TODO buf_read_value_bytes fn type"); |
| 15469 | case TypeTableEntryIdUnion: | 15482 | case TypeTableEntryIdUnion: |
| ... | @@ -15828,6 +15841,45 @@ static TypeTableEntry *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruc | ... | @@ -15828,6 +15841,45 @@ static TypeTableEntry *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruc |
| 15828 | return ira->codegen->builtin_types.entry_type; | 15841 | return ira->codegen->builtin_types.entry_type; |
| 15829 | } | 15842 | } |
| 15830 | 15843 | ||
| 15844 | static TypeTableEntry *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstructionTagType *instruction) { | ||
| 15845 | IrInstruction *target_inst = instruction->target->other; | ||
| 15846 | TypeTableEntry *enum_type = ir_resolve_type(ira, target_inst); | ||
| 15847 | if (type_is_invalid(enum_type)) | ||
| 15848 | return ira->codegen->builtin_types.entry_invalid; | ||
| 15849 | |||
| 15850 | if (enum_type->id == TypeTableEntryIdEnum) { | ||
| 15851 | ensure_complete_type(ira->codegen, enum_type); | ||
| 15852 | if (type_is_invalid(enum_type)) | ||
| 15853 | return ira->codegen->builtin_types.entry_invalid; | ||
| 15854 | |||
| 15855 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 15856 | out_val->data.x_type = enum_type->data.enumeration.tag_int_type; | ||
| 15857 | return ira->codegen->builtin_types.entry_type; | ||
| 15858 | } else if (enum_type->id == TypeTableEntryIdUnion) { | ||
| 15859 | ensure_complete_type(ira->codegen, enum_type); | ||
| 15860 | if (type_is_invalid(enum_type)) | ||
| 15861 | return ira->codegen->builtin_types.entry_invalid; | ||
| 15862 | |||
| 15863 | AstNode *decl_node = enum_type->data.unionation.decl_node; | ||
| 15864 | if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) { | ||
| 15865 | assert(enum_type->data.unionation.tag_type != nullptr); | ||
| 15866 | |||
| 15867 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 15868 | out_val->data.x_type = enum_type->data.unionation.tag_type; | ||
| 15869 | return ira->codegen->builtin_types.entry_type; | ||
| 15870 | } else { | ||
| 15871 | ErrorMsg *msg = ir_add_error(ira, target_inst, buf_sprintf("union '%s' has no tag", | ||
| 15872 | buf_ptr(&enum_type->name))); | ||
| 15873 | add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here")); | ||
| 15874 | return ira->codegen->builtin_types.entry_invalid; | ||
| 15875 | } | ||
| 15876 | } else { | ||
| 15877 | ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'", | ||
| 15878 | buf_ptr(&enum_type->name))); | ||
| 15879 | return ira->codegen->builtin_types.entry_invalid; | ||
| 15880 | } | ||
| 15881 | } | ||
| 15882 | |||
| 15831 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 15883 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 15832 | switch (instruction->id) { | 15884 | switch (instruction->id) { |
| 15833 | case IrInstructionIdInvalid: | 15885 | case IrInstructionIdInvalid: |
| ... | @@ -15838,9 +15890,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -15838,9 +15890,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15838 | case IrInstructionIdStructInit: | 15890 | case IrInstructionIdStructInit: |
| 15839 | case IrInstructionIdUnionInit: | 15891 | case IrInstructionIdUnionInit: |
| 15840 | case IrInstructionIdStructFieldPtr: | 15892 | case IrInstructionIdStructFieldPtr: |
| 15841 | case IrInstructionIdEnumFieldPtr: | ||
| 15842 | case IrInstructionIdUnionFieldPtr: | 15893 | case IrInstructionIdUnionFieldPtr: |
| 15843 | case IrInstructionIdInitEnum: | ||
| 15844 | case IrInstructionIdMaybeWrap: | 15894 | case IrInstructionIdMaybeWrap: |
| 15845 | case IrInstructionIdErrWrapCode: | 15895 | case IrInstructionIdErrWrapCode: |
| 15846 | case IrInstructionIdErrWrapPayload: | 15896 | case IrInstructionIdErrWrapPayload: |
| ... | @@ -15912,8 +15962,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -15912,8 +15962,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15912 | return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction); | 15962 | return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction); |
| 15913 | case IrInstructionIdSwitchVar: | 15963 | case IrInstructionIdSwitchVar: |
| 15914 | return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction); | 15964 | return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction); |
| 15915 | case IrInstructionIdEnumTag: | 15965 | case IrInstructionIdUnionTag: |
| 15916 | return ir_analyze_instruction_enum_tag(ira, (IrInstructionEnumTag *)instruction); | 15966 | return ir_analyze_instruction_union_tag(ira, (IrInstructionUnionTag *)instruction); |
| 15917 | case IrInstructionIdImport: | 15967 | case IrInstructionIdImport: |
| 15918 | return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction); | 15968 | return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction); |
| 15919 | case IrInstructionIdArrayLen: | 15969 | case IrInstructionIdArrayLen: |
| ... | @@ -16006,8 +16056,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -16006,8 +16056,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 16006 | return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction); | 16056 | return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction); |
| 16007 | case IrInstructionIdPtrToInt: | 16057 | case IrInstructionIdPtrToInt: |
| 16008 | return ir_analyze_instruction_ptr_to_int(ira, (IrInstructionPtrToInt *)instruction); | 16058 | return ir_analyze_instruction_ptr_to_int(ira, (IrInstructionPtrToInt *)instruction); |
| 16009 | case IrInstructionIdEnumTagName: | 16059 | case IrInstructionIdTagName: |
| 16010 | return ir_analyze_instruction_enum_tag_name(ira, (IrInstructionEnumTagName *)instruction); | 16060 | return ir_analyze_instruction_enum_tag_name(ira, (IrInstructionTagName *)instruction); |
| 16011 | case IrInstructionIdFieldParentPtr: | 16061 | case IrInstructionIdFieldParentPtr: |
| 16012 | return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction); | 16062 | return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction); |
| 16013 | case IrInstructionIdOffsetOf: | 16063 | case IrInstructionIdOffsetOf: |
| ... | @@ -16026,6 +16076,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -16026,6 +16076,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 16026 | return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction); | 16076 | return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction); |
| 16027 | case IrInstructionIdArgType: | 16077 | case IrInstructionIdArgType: |
| 16028 | return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction); | 16078 | return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction); |
| 16079 | case IrInstructionIdTagType: | ||
| 16080 | return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction); | ||
| 16029 | } | 16081 | } |
| 16030 | zig_unreachable(); | 16082 | zig_unreachable(); |
| 16031 | } | 16083 | } |
| ... | @@ -16158,7 +16210,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -16158,7 +16210,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 16158 | case IrInstructionIdPtrTypeChild: | 16210 | case IrInstructionIdPtrTypeChild: |
| 16159 | case IrInstructionIdArrayLen: | 16211 | case IrInstructionIdArrayLen: |
| 16160 | case IrInstructionIdStructFieldPtr: | 16212 | case IrInstructionIdStructFieldPtr: |
| 16161 | case IrInstructionIdEnumFieldPtr: | ||
| 16162 | case IrInstructionIdUnionFieldPtr: | 16213 | case IrInstructionIdUnionFieldPtr: |
| 16163 | case IrInstructionIdArrayType: | 16214 | case IrInstructionIdArrayType: |
| 16164 | case IrInstructionIdSliceType: | 16215 | case IrInstructionIdSliceType: |
| ... | @@ -16169,7 +16220,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -16169,7 +16220,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 16169 | case IrInstructionIdCtz: | 16220 | case IrInstructionIdCtz: |
| 16170 | case IrInstructionIdSwitchVar: | 16221 | case IrInstructionIdSwitchVar: |
| 16171 | case IrInstructionIdSwitchTarget: | 16222 | case IrInstructionIdSwitchTarget: |
| 16172 | case IrInstructionIdEnumTag: | 16223 | case IrInstructionIdUnionTag: |
| 16173 | case IrInstructionIdRef: | 16224 | case IrInstructionIdRef: |
| 16174 | case IrInstructionIdMinValue: | 16225 | case IrInstructionIdMinValue: |
| 16175 | case IrInstructionIdMaxValue: | 16226 | case IrInstructionIdMaxValue: |
| ... | @@ -16191,7 +16242,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -16191,7 +16242,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 16191 | case IrInstructionIdErrWrapPayload: | 16242 | case IrInstructionIdErrWrapPayload: |
| 16192 | case IrInstructionIdFnProto: | 16243 | case IrInstructionIdFnProto: |
| 16193 | case IrInstructionIdTestComptime: | 16244 | case IrInstructionIdTestComptime: |
| 16194 | case IrInstructionIdInitEnum: | ||
| 16195 | case IrInstructionIdPtrCast: | 16245 | case IrInstructionIdPtrCast: |
| 16196 | case IrInstructionIdBitCast: | 16246 | case IrInstructionIdBitCast: |
| 16197 | case IrInstructionIdWidenOrShorten: | 16247 | case IrInstructionIdWidenOrShorten: |
| ... | @@ -16204,13 +16254,14 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -16204,13 +16254,14 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 16204 | case IrInstructionIdDeclRef: | 16254 | case IrInstructionIdDeclRef: |
| 16205 | case IrInstructionIdErrName: | 16255 | case IrInstructionIdErrName: |
| 16206 | case IrInstructionIdTypeName: | 16256 | case IrInstructionIdTypeName: |
| 16207 | case IrInstructionIdEnumTagName: | 16257 | case IrInstructionIdTagName: |
| 16208 | case IrInstructionIdFieldParentPtr: | 16258 | case IrInstructionIdFieldParentPtr: |
| 16209 | case IrInstructionIdOffsetOf: | 16259 | case IrInstructionIdOffsetOf: |
| 16210 | case IrInstructionIdTypeId: | 16260 | case IrInstructionIdTypeId: |
| 16211 | case IrInstructionIdAlignCast: | 16261 | case IrInstructionIdAlignCast: |
| 16212 | case IrInstructionIdOpaqueType: | 16262 | case IrInstructionIdOpaqueType: |
| 16213 | case IrInstructionIdArgType: | 16263 | case IrInstructionIdArgType: |
| 16264 | case IrInstructionIdTagType: | ||
| 16214 | return false; | 16265 | return false; |
| 16215 | case IrInstructionIdAsm: | 16266 | case IrInstructionIdAsm: |
| 16216 | { | 16267 | { |
src/ir_print.cpp+19-29| ... | @@ -291,7 +291,7 @@ static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruct | ... | @@ -291,7 +291,7 @@ static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruct |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) { | 293 | static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) { |
| 294 | Buf *field_name = instruction->field->name; | 294 | Buf *field_name = instruction->field->enum_field->name; |
| 295 | 295 | ||
| 296 | fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name)); | 296 | fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name)); |
| 297 | fprintf(irp->f, ".%s = ", buf_ptr(field_name)); | 297 | fprintf(irp->f, ".%s = ", buf_ptr(field_name)); |
| ... | @@ -361,17 +361,10 @@ static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr | ... | @@ -361,17 +361,10 @@ static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr |
| 361 | fprintf(irp->f, ")"); | 361 | fprintf(irp->f, ")"); |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | static void ir_print_enum_field_ptr(IrPrint *irp, IrInstructionEnumFieldPtr *instruction) { | ||
| 365 | fprintf(irp->f, "@EnumFieldPtr(&"); | ||
| 366 | ir_print_other_instruction(irp, instruction->enum_ptr); | ||
| 367 | fprintf(irp->f, ".%s", buf_ptr(instruction->field->name)); | ||
| 368 | fprintf(irp->f, ")"); | ||
| 369 | } | ||
| 370 | |||
| 371 | static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) { | 364 | static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) { |
| 372 | fprintf(irp->f, "@UnionFieldPtr(&"); | 365 | fprintf(irp->f, "@UnionFieldPtr(&"); |
| 373 | ir_print_other_instruction(irp, instruction->union_ptr); | 366 | ir_print_other_instruction(irp, instruction->union_ptr); |
| 374 | fprintf(irp->f, ".%s", buf_ptr(instruction->field->name)); | 367 | fprintf(irp->f, ".%s", buf_ptr(instruction->field->enum_field->name)); |
| 375 | fprintf(irp->f, ")"); | 368 | fprintf(irp->f, ")"); |
| 376 | } | 369 | } |
| 377 | 370 | ||
| ... | @@ -509,8 +502,8 @@ static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *inst | ... | @@ -509,8 +502,8 @@ static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *inst |
| 509 | ir_print_other_instruction(irp, instruction->target_value_ptr); | 502 | ir_print_other_instruction(irp, instruction->target_value_ptr); |
| 510 | } | 503 | } |
| 511 | 504 | ||
| 512 | static void ir_print_enum_tag(IrPrint *irp, IrInstructionEnumTag *instruction) { | 505 | static void ir_print_union_tag(IrPrint *irp, IrInstructionUnionTag *instruction) { |
| 513 | fprintf(irp->f, "enumtag "); | 506 | fprintf(irp->f, "uniontag "); |
| 514 | ir_print_other_instruction(irp, instruction->value); | 507 | ir_print_other_instruction(irp, instruction->value); |
| 515 | } | 508 | } |
| 516 | 509 | ||
| ... | @@ -799,12 +792,6 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst | ... | @@ -799,12 +792,6 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst |
| 799 | fprintf(irp->f, ")"); | 792 | fprintf(irp->f, ")"); |
| 800 | } | 793 | } |
| 801 | 794 | ||
| 802 | static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction) { | ||
| 803 | fprintf(irp->f, "%s.%s {", buf_ptr(&instruction->enum_type->name), buf_ptr(instruction->field->name)); | ||
| 804 | ir_print_other_instruction(irp, instruction->init_value); | ||
| 805 | fprintf(irp->f, "}"); | ||
| 806 | } | ||
| 807 | |||
| 808 | static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { | 795 | static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { |
| 809 | fprintf(irp->f, "@ptrCast("); | 796 | fprintf(irp->f, "@ptrCast("); |
| 810 | if (instruction->dest_type) { | 797 | if (instruction->dest_type) { |
| ... | @@ -885,8 +872,8 @@ static void ir_print_type_name(IrPrint *irp, IrInstructionTypeName *instruction) | ... | @@ -885,8 +872,8 @@ static void ir_print_type_name(IrPrint *irp, IrInstructionTypeName *instruction) |
| 885 | ir_print_other_instruction(irp, instruction->type_value); | 872 | ir_print_other_instruction(irp, instruction->type_value); |
| 886 | } | 873 | } |
| 887 | 874 | ||
| 888 | static void ir_print_enum_tag_name(IrPrint *irp, IrInstructionEnumTagName *instruction) { | 875 | static void ir_print_tag_name(IrPrint *irp, IrInstructionTagName *instruction) { |
| 889 | fprintf(irp->f, "enumtagname "); | 876 | fprintf(irp->f, "tagname "); |
| 890 | ir_print_other_instruction(irp, instruction->target); | 877 | ir_print_other_instruction(irp, instruction->target); |
| 891 | } | 878 | } |
| 892 | 879 | ||
| ... | @@ -994,6 +981,12 @@ static void ir_print_arg_type(IrPrint *irp, IrInstructionArgType *instruction) { | ... | @@ -994,6 +981,12 @@ static void ir_print_arg_type(IrPrint *irp, IrInstructionArgType *instruction) { |
| 994 | fprintf(irp->f, ")"); | 981 | fprintf(irp->f, ")"); |
| 995 | } | 982 | } |
| 996 | 983 | ||
| 984 | static void ir_print_enum_tag_type(IrPrint *irp, IrInstructionTagType *instruction) { | ||
| 985 | fprintf(irp->f, "@TagType("); | ||
| 986 | ir_print_other_instruction(irp, instruction->target); | ||
| 987 | fprintf(irp->f, ")"); | ||
| 988 | } | ||
| 989 | |||
| 997 | 990 | ||
| 998 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 991 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 999 | ir_print_prefix(irp, instruction); | 992 | ir_print_prefix(irp, instruction); |
| ... | @@ -1072,9 +1065,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1072,9 +1065,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1072 | case IrInstructionIdStructFieldPtr: | 1065 | case IrInstructionIdStructFieldPtr: |
| 1073 | ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction); | 1066 | ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction); |
| 1074 | break; | 1067 | break; |
| 1075 | case IrInstructionIdEnumFieldPtr: | ||
| 1076 | ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction); | ||
| 1077 | break; | ||
| 1078 | case IrInstructionIdUnionFieldPtr: | 1068 | case IrInstructionIdUnionFieldPtr: |
| 1079 | ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction); | 1069 | ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction); |
| 1080 | break; | 1070 | break; |
| ... | @@ -1117,8 +1107,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1117,8 +1107,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1117 | case IrInstructionIdSwitchTarget: | 1107 | case IrInstructionIdSwitchTarget: |
| 1118 | ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction); | 1108 | ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction); |
| 1119 | break; | 1109 | break; |
| 1120 | case IrInstructionIdEnumTag: | 1110 | case IrInstructionIdUnionTag: |
| 1121 | ir_print_enum_tag(irp, (IrInstructionEnumTag *)instruction); | 1111 | ir_print_union_tag(irp, (IrInstructionUnionTag *)instruction); |
| 1122 | break; | 1112 | break; |
| 1123 | case IrInstructionIdImport: | 1113 | case IrInstructionIdImport: |
| 1124 | ir_print_import(irp, (IrInstructionImport *)instruction); | 1114 | ir_print_import(irp, (IrInstructionImport *)instruction); |
| ... | @@ -1231,9 +1221,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1231,9 +1221,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1231 | case IrInstructionIdTestComptime: | 1221 | case IrInstructionIdTestComptime: |
| 1232 | ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); | 1222 | ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); |
| 1233 | break; | 1223 | break; |
| 1234 | case IrInstructionIdInitEnum: | ||
| 1235 | ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction); | ||
| 1236 | break; | ||
| 1237 | case IrInstructionIdPtrCast: | 1224 | case IrInstructionIdPtrCast: |
| 1238 | ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction); | 1225 | ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction); |
| 1239 | break; | 1226 | break; |
| ... | @@ -1267,8 +1254,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1267,8 +1254,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1267 | case IrInstructionIdTypeName: | 1254 | case IrInstructionIdTypeName: |
| 1268 | ir_print_type_name(irp, (IrInstructionTypeName *)instruction); | 1255 | ir_print_type_name(irp, (IrInstructionTypeName *)instruction); |
| 1269 | break; | 1256 | break; |
| 1270 | case IrInstructionIdEnumTagName: | 1257 | case IrInstructionIdTagName: |
| 1271 | ir_print_enum_tag_name(irp, (IrInstructionEnumTagName *)instruction); | 1258 | ir_print_tag_name(irp, (IrInstructionTagName *)instruction); |
| 1272 | break; | 1259 | break; |
| 1273 | case IrInstructionIdCanImplicitCast: | 1260 | case IrInstructionIdCanImplicitCast: |
| 1274 | ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction); | 1261 | ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction); |
| ... | @@ -1312,6 +1299,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1312,6 +1299,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1312 | case IrInstructionIdArgType: | 1299 | case IrInstructionIdArgType: |
| 1313 | ir_print_arg_type(irp, (IrInstructionArgType *)instruction); | 1300 | ir_print_arg_type(irp, (IrInstructionArgType *)instruction); |
| 1314 | break; | 1301 | break; |
| 1302 | case IrInstructionIdTagType: | ||
| 1303 | ir_print_enum_tag_type(irp, (IrInstructionTagType *)instruction); | ||
| 1304 | break; | ||
| 1315 | } | 1305 | } |
| 1316 | fprintf(irp->f, "\n"); | 1306 | fprintf(irp->f, "\n"); |
| 1317 | } | 1307 | } |
src/os.cpp+5| ... | @@ -931,6 +931,7 @@ int os_self_exe_path(Buf *out_path) { | ... | @@ -931,6 +931,7 @@ int os_self_exe_path(Buf *out_path) { |
| 931 | #define VT_GREEN "\x1b[32;1m" | 931 | #define VT_GREEN "\x1b[32;1m" |
| 932 | #define VT_CYAN "\x1b[36;1m" | 932 | #define VT_CYAN "\x1b[36;1m" |
| 933 | #define VT_WHITE "\x1b[37;1m" | 933 | #define VT_WHITE "\x1b[37;1m" |
| 934 | #define VT_BOLD "\x1b[0;1m" | ||
| 934 | #define VT_RESET "\x1b[0m" | 935 | #define VT_RESET "\x1b[0m" |
| 935 | 936 | ||
| 936 | static void set_color_posix(TermColor color) { | 937 | static void set_color_posix(TermColor color) { |
| ... | @@ -947,6 +948,9 @@ static void set_color_posix(TermColor color) { | ... | @@ -947,6 +948,9 @@ static void set_color_posix(TermColor color) { |
| 947 | case TermColorWhite: | 948 | case TermColorWhite: |
| 948 | fprintf(stderr, VT_WHITE); | 949 | fprintf(stderr, VT_WHITE); |
| 949 | break; | 950 | break; |
| 951 | case TermColorBold: | ||
| 952 | fprintf(stderr, VT_BOLD); | ||
| 953 | break; | ||
| 950 | case TermColorReset: | 954 | case TermColorReset: |
| 951 | fprintf(stderr, VT_RESET); | 955 | fprintf(stderr, VT_RESET); |
| 952 | break; | 956 | break; |
| ... | @@ -989,6 +993,7 @@ void os_stderr_set_color(TermColor color) { | ... | @@ -989,6 +993,7 @@ void os_stderr_set_color(TermColor color) { |
| 989 | SetConsoleTextAttribute(stderr_handle, FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); | 993 | SetConsoleTextAttribute(stderr_handle, FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); |
| 990 | break; | 994 | break; |
| 991 | case TermColorWhite: | 995 | case TermColorWhite: |
| 996 | case TermColorBold: | ||
| 992 | SetConsoleTextAttribute(stderr_handle, | 997 | SetConsoleTextAttribute(stderr_handle, |
| 993 | FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); | 998 | FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); |
| 994 | break; | 999 | break; |
src/os.hpp+1| ... | @@ -21,6 +21,7 @@ enum TermColor { | ... | @@ -21,6 +21,7 @@ enum TermColor { |
| 21 | TermColorGreen, | 21 | TermColorGreen, |
| 22 | TermColorCyan, | 22 | TermColorCyan, |
| 23 | TermColorWhite, | 23 | TermColorWhite, |
| 24 | TermColorBold, | ||
| 24 | TermColorReset, | 25 | TermColorReset, |
| 25 | }; | 26 | }; |
| 26 | 27 |
src/parser.cpp+48-20| ... | @@ -2377,9 +2377,11 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi | ... | @@ -2377,9 +2377,11 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi |
| 2377 | } | 2377 | } |
| 2378 | 2378 | ||
| 2379 | /* | 2379 | /* |
| 2380 | ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}" | 2380 | ContainerDecl = option("extern" | "packed") |
| 2381 | ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression))) | ||
| 2382 | "{" many(ContainerMember) "}" | ||
| 2381 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) | 2383 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) |
| 2382 | ContainerField = Symbol option(":" Expression) "," | 2384 | ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression "," |
| 2383 | */ | 2385 | */ |
| 2384 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) { | 2386 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 2385 | Token *first_token = &pc->tokens->at(*token_index); | 2387 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | @@ -2415,6 +2417,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, | ... | @@ -2415,6 +2417,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2415 | node->data.container_decl.layout = layout; | 2417 | node->data.container_decl.layout = layout; |
| 2416 | node->data.container_decl.kind = kind; | 2418 | node->data.container_decl.kind = kind; |
| 2417 | 2419 | ||
| 2420 | if (kind == ContainerKindUnion) { | ||
| 2421 | Token *lparen_token = &pc->tokens->at(*token_index); | ||
| 2422 | if (lparen_token->id == TokenIdLParen) { | ||
| 2423 | Token *enum_token = &pc->tokens->at(*token_index + 1); | ||
| 2424 | if (enum_token->id == TokenIdKeywordEnum) { | ||
| 2425 | Token *paren_token = &pc->tokens->at(*token_index + 2); | ||
| 2426 | if (paren_token->id == TokenIdLParen) { | ||
| 2427 | node->data.container_decl.auto_enum = true; | ||
| 2428 | *token_index += 2; | ||
| 2429 | node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, true); | ||
| 2430 | ast_eat_token(pc, token_index, TokenIdRParen); | ||
| 2431 | } else if (paren_token->id == TokenIdRParen) { | ||
| 2432 | node->data.container_decl.auto_enum = true; | ||
| 2433 | *token_index += 3; | ||
| 2434 | } | ||
| 2435 | } | ||
| 2436 | } | ||
| 2437 | } | ||
| 2438 | if (!node->data.container_decl.auto_enum) { | ||
| 2439 | node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false); | ||
| 2440 | } | ||
| 2441 | |||
| 2418 | ast_eat_token(pc, token_index, TokenIdLBrace); | 2442 | ast_eat_token(pc, token_index, TokenIdLBrace); |
| 2419 | 2443 | ||
| 2420 | for (;;) { | 2444 | for (;;) { |
| ... | @@ -2452,31 +2476,33 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, | ... | @@ -2452,31 +2476,33 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2452 | AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token); | 2476 | AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token); |
| 2453 | *token_index += 1; | 2477 | *token_index += 1; |
| 2454 | 2478 | ||
| 2479 | node->data.container_decl.fields.append(field_node); | ||
| 2455 | field_node->data.struct_field.visib_mod = visib_mod; | 2480 | field_node->data.struct_field.visib_mod = visib_mod; |
| 2456 | field_node->data.struct_field.name = token_buf(token); | 2481 | field_node->data.struct_field.name = token_buf(token); |
| 2457 | 2482 | ||
| 2458 | Token *token = &pc->tokens->at(*token_index); | 2483 | Token *colon_token = &pc->tokens->at(*token_index); |
| 2459 | if (token->id == TokenIdComma || token->id == TokenIdRBrace) { | 2484 | if (colon_token->id == TokenIdColon) { |
| 2460 | field_node->data.struct_field.type = ast_create_void_type_node(pc, token); | 2485 | *token_index += 1; |
| 2486 | field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true); | ||
| 2487 | } | ||
| 2488 | Token *eq_token = &pc->tokens->at(*token_index); | ||
| 2489 | if (eq_token->id == TokenIdEq) { | ||
| 2461 | *token_index += 1; | 2490 | *token_index += 1; |
| 2462 | node->data.container_decl.fields.append(field_node); | 2491 | field_node->data.struct_field.value = ast_parse_prefix_op_expr(pc, token_index, true); |
| 2492 | } | ||
| 2463 | 2493 | ||
| 2464 | if (token->id == TokenIdRBrace) { | 2494 | Token *next_token = &pc->tokens->at(*token_index); |
| 2465 | break; | 2495 | if (next_token->id == TokenIdComma) { |
| 2466 | } | 2496 | *token_index += 1; |
| 2467 | } else { | 2497 | continue; |
| 2468 | ast_eat_token(pc, token_index, TokenIdColon); | 2498 | } |
| 2469 | field_node->data.struct_field.type = ast_parse_expression(pc, token_index, true); | ||
| 2470 | node->data.container_decl.fields.append(field_node); | ||
| 2471 | 2499 | ||
| 2472 | Token *token = &pc->tokens->at(*token_index); | 2500 | if (next_token->id == TokenIdRBrace) { |
| 2473 | if (token->id == TokenIdRBrace) { | 2501 | *token_index += 1; |
| 2474 | *token_index += 1; | 2502 | break; |
| 2475 | break; | ||
| 2476 | } else { | ||
| 2477 | ast_eat_token(pc, token_index, TokenIdComma); | ||
| 2478 | } | ||
| 2479 | } | 2503 | } |
| 2504 | |||
| 2505 | ast_invalid_token_error(pc, next_token); | ||
| 2480 | } else { | 2506 | } else { |
| 2481 | ast_invalid_token_error(pc, token); | 2507 | ast_invalid_token_error(pc, token); |
| 2482 | } | 2508 | } |
| ... | @@ -2804,9 +2830,11 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2804,9 +2830,11 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2804 | case NodeTypeContainerDecl: | 2830 | case NodeTypeContainerDecl: |
| 2805 | visit_node_list(&node->data.container_decl.fields, visit, context); | 2831 | visit_node_list(&node->data.container_decl.fields, visit, context); |
| 2806 | visit_node_list(&node->data.container_decl.decls, visit, context); | 2832 | visit_node_list(&node->data.container_decl.decls, visit, context); |
| 2833 | visit_field(&node->data.container_decl.init_arg_expr, visit, context); | ||
| 2807 | break; | 2834 | break; |
| 2808 | case NodeTypeStructField: | 2835 | case NodeTypeStructField: |
| 2809 | visit_field(&node->data.struct_field.type, visit, context); | 2836 | visit_field(&node->data.struct_field.type, visit, context); |
| 2837 | visit_field(&node->data.struct_field.value, visit, context); | ||
| 2810 | break; | 2838 | break; |
| 2811 | case NodeTypeContainerInitExpr: | 2839 | case NodeTypeContainerInitExpr: |
| 2812 | visit_field(&node->data.container_init_expr.type, visit, context); | 2840 | visit_field(&node->data.container_init_expr.type, visit, context); |
src/translate_c.cpp+30-3| ... | @@ -651,6 +651,14 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) { | ... | @@ -651,6 +651,14 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) { |
| 651 | } | 651 | } |
| 652 | } | 652 | } |
| 653 | 653 | ||
| 654 | static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) { | ||
| 655 | const Type *c_type = qual_type_canon(qt); | ||
| 656 | if (c_type->getTypeClass() != Type::Builtin) | ||
| 657 | return false; | ||
| 658 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | ||
| 659 | return builtin_ty->getKind() == kind; | ||
| 660 | } | ||
| 661 | |||
| 654 | static bool c_is_float(Context *c, QualType qt) { | 662 | static bool c_is_float(Context *c, QualType qt) { |
| 655 | const Type *c_type = qt.getTypePtr(); | 663 | const Type *c_type = qt.getTypePtr(); |
| 656 | if (c_type->getTypeClass() != Type::Builtin) | 664 | if (c_type->getTypeClass() != Type::Builtin) |
| ... | @@ -978,11 +986,23 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou | ... | @@ -978,11 +986,23 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 978 | const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty); | 986 | const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty); |
| 979 | return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc); | 987 | return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc); |
| 980 | } | 988 | } |
| 989 | case Type::IncompleteArray: | ||
| 990 | { | ||
| 991 | const IncompleteArrayType *incomplete_array_ty = static_cast<const IncompleteArrayType *>(ty); | ||
| 992 | QualType child_qt = incomplete_array_ty->getElementType(); | ||
| 993 | AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc); | ||
| 994 | if (child_type_node == nullptr) { | ||
| 995 | emit_warning(c, source_loc, "unresolved array element type"); | ||
| 996 | return nullptr; | ||
| 997 | } | ||
| 998 | AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(), | ||
| 999 | child_qt.isVolatileQualified(), child_type_node); | ||
| 1000 | return pointer_node; | ||
| 1001 | } | ||
| 981 | case Type::BlockPointer: | 1002 | case Type::BlockPointer: |
| 982 | case Type::LValueReference: | 1003 | case Type::LValueReference: |
| 983 | case Type::RValueReference: | 1004 | case Type::RValueReference: |
| 984 | case Type::MemberPointer: | 1005 | case Type::MemberPointer: |
| 985 | case Type::IncompleteArray: | ||
| 986 | case Type::VariableArray: | 1006 | case Type::VariableArray: |
| 987 | case Type::DependentSizedArray: | 1007 | case Type::DependentSizedArray: |
| 988 | case Type::DependentSizedExtVector: | 1008 | case Type::DependentSizedExtVector: |
| ... | @@ -3417,7 +3437,14 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -3417,7 +3437,14 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3417 | AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl); | 3437 | AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl); |
| 3418 | enum_node->data.container_decl.kind = ContainerKindEnum; | 3438 | enum_node->data.container_decl.kind = ContainerKindEnum; |
| 3419 | enum_node->data.container_decl.layout = ContainerLayoutExtern; | 3439 | enum_node->data.container_decl.layout = ContainerLayoutExtern; |
| 3420 | enum_node->data.container_decl.init_arg_expr = tag_int_type; | 3440 | // TODO only emit this tag type if the enum tag type is not the default. |
| 3441 | // I don't know what the default is, need to figure out how clang is deciding. | ||
| 3442 | // it appears to at least be different across gcc/msvc | ||
| 3443 | if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) && | ||
| 3444 | !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int)) | ||
| 3445 | { | ||
| 3446 | enum_node->data.container_decl.init_arg_expr = tag_int_type; | ||
| 3447 | } | ||
| 3421 | 3448 | ||
| 3422 | enum_node->data.container_decl.fields.resize(field_count); | 3449 | enum_node->data.container_decl.fields.resize(field_count); |
| 3423 | uint32_t i = 0; | 3450 | uint32_t i = 0; |
| ... | @@ -4304,7 +4331,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch | ... | @@ -4304,7 +4331,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 4304 | } | 4331 | } |
| 4305 | } | 4332 | } |
| 4306 | 4333 | ||
| 4307 | return 0; | 4334 | return ErrorCCompileErrors; |
| 4308 | } | 4335 | } |
| 4309 | 4336 | ||
| 4310 | c->ctx = &ast_unit->getASTContext(); | 4337 | c->ctx = &ast_unit->getASTContext(); |
src/zig_llvm.cpp+1-1| ... | @@ -793,7 +793,7 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_ | ... | @@ -793,7 +793,7 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_ |
| 793 | zig_unreachable(); | 793 | zig_unreachable(); |
| 794 | 794 | ||
| 795 | case ZigLLVM_COFF: | 795 | case ZigLLVM_COFF: |
| 796 | return lld::coff::link(array_ref_args, false); | 796 | return lld::coff::link(array_ref_args, false, diag); |
| 797 | 797 | ||
| 798 | case ZigLLVM_ELF: | 798 | case ZigLLVM_ELF: |
| 799 | return lld::elf::link(array_ref_args, false, diag); | 799 | return lld::elf::link(array_ref_args, false, diag); |
std/buffer.zig+6| ... | @@ -4,6 +4,8 @@ const Allocator = mem.Allocator; | ... | @@ -4,6 +4,8 @@ const Allocator = mem.Allocator; |
| 4 | const assert = debug.assert; | 4 | const assert = debug.assert; |
| 5 | const ArrayList = @import("array_list.zig").ArrayList; | 5 | const ArrayList = @import("array_list.zig").ArrayList; |
| 6 | 6 | ||
| 7 | const fmt = @import("fmt/index.zig"); | ||
| 8 | |||
| 7 | /// A buffer that allocates memory and maintains a null byte at the end. | 9 | /// A buffer that allocates memory and maintains a null byte at the end. |
| 8 | pub const Buffer = struct { | 10 | pub const Buffer = struct { |
| 9 | list: ArrayList(u8), | 11 | list: ArrayList(u8), |
| ... | @@ -96,6 +98,10 @@ pub const Buffer = struct { | ... | @@ -96,6 +98,10 @@ pub const Buffer = struct { |
| 96 | mem.copy(u8, self.list.toSlice()[old_len..], m); | 98 | mem.copy(u8, self.list.toSlice()[old_len..], m); |
| 97 | } | 99 | } |
| 98 | 100 | ||
| 101 | pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) -> %void { | ||
| 102 | return fmt.format(self, append, format, args); | ||
| 103 | } | ||
| 104 | |||
| 99 | pub fn appendByte(self: &Buffer, byte: u8) -> %void { | 105 | pub fn appendByte(self: &Buffer, byte: u8) -> %void { |
| 100 | return self.appendByteNTimes(byte, 1); | 106 | return self.appendByteNTimes(byte, 1); |
| 101 | } | 107 | } |
std/build.zig+21-21| ... | @@ -69,8 +69,8 @@ pub const Builder = struct { | ... | @@ -69,8 +69,8 @@ pub const Builder = struct { |
| 69 | used: bool, | 69 | used: bool, |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| 72 | const UserValue = enum { | 72 | const UserValue = union(enum) { |
| 73 | Flag, | 73 | Flag: void, |
| 74 | Scalar: []const u8, | 74 | Scalar: []const u8, |
| 75 | List: ArrayList([]const u8), | 75 | List: ArrayList([]const u8), |
| 76 | }; | 76 | }; |
| ... | @@ -450,7 +450,7 @@ pub const Builder = struct { | ... | @@ -450,7 +450,7 @@ pub const Builder = struct { |
| 450 | pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool { | 450 | pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool { |
| 451 | if (%%self.user_input_options.put(name, UserInputOption { | 451 | if (%%self.user_input_options.put(name, UserInputOption { |
| 452 | .name = name, | 452 | .name = name, |
| 453 | .value = UserValue.Scalar { value }, | 453 | .value = UserValue { .Scalar = value }, |
| 454 | .used = false, | 454 | .used = false, |
| 455 | })) |*prev_value| { | 455 | })) |*prev_value| { |
| 456 | // option already exists | 456 | // option already exists |
| ... | @@ -462,7 +462,7 @@ pub const Builder = struct { | ... | @@ -462,7 +462,7 @@ pub const Builder = struct { |
| 462 | %%list.append(value); | 462 | %%list.append(value); |
| 463 | _ = %%self.user_input_options.put(name, UserInputOption { | 463 | _ = %%self.user_input_options.put(name, UserInputOption { |
| 464 | .name = name, | 464 | .name = name, |
| 465 | .value = UserValue.List { list }, | 465 | .value = UserValue { .List = list }, |
| 466 | .used = false, | 466 | .used = false, |
| 467 | }); | 467 | }); |
| 468 | }, | 468 | }, |
| ... | @@ -471,7 +471,7 @@ pub const Builder = struct { | ... | @@ -471,7 +471,7 @@ pub const Builder = struct { |
| 471 | %%list.append(value); | 471 | %%list.append(value); |
| 472 | _ = %%self.user_input_options.put(name, UserInputOption { | 472 | _ = %%self.user_input_options.put(name, UserInputOption { |
| 473 | .name = name, | 473 | .name = name, |
| 474 | .value = UserValue.List { *list }, | 474 | .value = UserValue { .List = *list }, |
| 475 | .used = false, | 475 | .used = false, |
| 476 | }); | 476 | }); |
| 477 | }, | 477 | }, |
| ... | @@ -487,7 +487,7 @@ pub const Builder = struct { | ... | @@ -487,7 +487,7 @@ pub const Builder = struct { |
| 487 | pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool { | 487 | pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool { |
| 488 | if (%%self.user_input_options.put(name, UserInputOption { | 488 | if (%%self.user_input_options.put(name, UserInputOption { |
| 489 | .name = name, | 489 | .name = name, |
| 490 | .value = UserValue.Flag, | 490 | .value = UserValue {.Flag = {} }, |
| 491 | .used = false, | 491 | .used = false, |
| 492 | })) |*prev_value| { | 492 | })) |*prev_value| { |
| 493 | switch (prev_value.value) { | 493 | switch (prev_value.value) { |
| ... | @@ -685,8 +685,8 @@ const CrossTarget = struct { | ... | @@ -685,8 +685,8 @@ const CrossTarget = struct { |
| 685 | environ: builtin.Environ, | 685 | environ: builtin.Environ, |
| 686 | }; | 686 | }; |
| 687 | 687 | ||
| 688 | const Target = enum { | 688 | const Target = union(enum) { |
| 689 | Native, | 689 | Native: void, |
| 690 | Cross: CrossTarget, | 690 | Cross: CrossTarget, |
| 691 | 691 | ||
| 692 | pub fn oFileExt(self: &const Target) -> []const u8 { | 692 | pub fn oFileExt(self: &const Target) -> []const u8 { |
| ... | @@ -844,7 +844,7 @@ pub const LibExeObjStep = struct { | ... | @@ -844,7 +844,7 @@ pub const LibExeObjStep = struct { |
| 844 | .kind = kind, | 844 | .kind = kind, |
| 845 | .root_src = root_src, | 845 | .root_src = root_src, |
| 846 | .name = name, | 846 | .name = name, |
| 847 | .target = Target.Native, | 847 | .target = Target { .Native = {} }, |
| 848 | .linker_script = null, | 848 | .linker_script = null, |
| 849 | .link_libs = BufSet.init(builder.allocator), | 849 | .link_libs = BufSet.init(builder.allocator), |
| 850 | .frameworks = BufSet.init(builder.allocator), | 850 | .frameworks = BufSet.init(builder.allocator), |
| ... | @@ -879,7 +879,7 @@ pub const LibExeObjStep = struct { | ... | @@ -879,7 +879,7 @@ pub const LibExeObjStep = struct { |
| 879 | .kind = kind, | 879 | .kind = kind, |
| 880 | .version = *version, | 880 | .version = *version, |
| 881 | .static = static, | 881 | .static = static, |
| 882 | .target = Target.Native, | 882 | .target = Target { .Native = {} }, |
| 883 | .cflags = ArrayList([]const u8).init(builder.allocator), | 883 | .cflags = ArrayList([]const u8).init(builder.allocator), |
| 884 | .source_files = ArrayList([]const u8).init(builder.allocator), | 884 | .source_files = ArrayList([]const u8).init(builder.allocator), |
| 885 | .object_files = ArrayList([]const u8).init(builder.allocator), | 885 | .object_files = ArrayList([]const u8).init(builder.allocator), |
| ... | @@ -948,8 +948,8 @@ pub const LibExeObjStep = struct { | ... | @@ -948,8 +948,8 @@ pub const LibExeObjStep = struct { |
| 948 | pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, | 948 | pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, |
| 949 | target_environ: builtin.Environ) | 949 | target_environ: builtin.Environ) |
| 950 | { | 950 | { |
| 951 | self.target = Target.Cross { | 951 | self.target = Target { |
| 952 | CrossTarget { | 952 | .Cross = CrossTarget { |
| 953 | .arch = target_arch, | 953 | .arch = target_arch, |
| 954 | .os = target_os, | 954 | .os = target_os, |
| 955 | .environ = target_environ, | 955 | .environ = target_environ, |
| ... | @@ -1186,13 +1186,13 @@ pub const LibExeObjStep = struct { | ... | @@ -1186,13 +1186,13 @@ pub const LibExeObjStep = struct { |
| 1186 | Target.Native => {}, | 1186 | Target.Native => {}, |
| 1187 | Target.Cross => |cross_target| { | 1187 | Target.Cross => |cross_target| { |
| 1188 | %%zig_args.append("--target-arch"); | 1188 | %%zig_args.append("--target-arch"); |
| 1189 | %%zig_args.append(@enumTagName(cross_target.arch)); | 1189 | %%zig_args.append(@tagName(cross_target.arch)); |
| 1190 | 1190 | ||
| 1191 | %%zig_args.append("--target-os"); | 1191 | %%zig_args.append("--target-os"); |
| 1192 | %%zig_args.append(@enumTagName(cross_target.os)); | 1192 | %%zig_args.append(@tagName(cross_target.os)); |
| 1193 | 1193 | ||
| 1194 | %%zig_args.append("--target-environ"); | 1194 | %%zig_args.append("--target-environ"); |
| 1195 | %%zig_args.append(@enumTagName(cross_target.environ)); | 1195 | %%zig_args.append(@tagName(cross_target.environ)); |
| 1196 | }, | 1196 | }, |
| 1197 | } | 1197 | } |
| 1198 | 1198 | ||
| ... | @@ -1553,7 +1553,7 @@ pub const TestStep = struct { | ... | @@ -1553,7 +1553,7 @@ pub const TestStep = struct { |
| 1553 | .name_prefix = "", | 1553 | .name_prefix = "", |
| 1554 | .filter = null, | 1554 | .filter = null, |
| 1555 | .link_libs = BufSet.init(builder.allocator), | 1555 | .link_libs = BufSet.init(builder.allocator), |
| 1556 | .target = Target.Native, | 1556 | .target = Target { .Native = {} }, |
| 1557 | .exec_cmd_args = null, | 1557 | .exec_cmd_args = null, |
| 1558 | } | 1558 | } |
| 1559 | } | 1559 | } |
| ... | @@ -1581,8 +1581,8 @@ pub const TestStep = struct { | ... | @@ -1581,8 +1581,8 @@ pub const TestStep = struct { |
| 1581 | pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, | 1581 | pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, |
| 1582 | target_environ: builtin.Environ) | 1582 | target_environ: builtin.Environ) |
| 1583 | { | 1583 | { |
| 1584 | self.target = Target.Cross { | 1584 | self.target = Target { |
| 1585 | CrossTarget { | 1585 | .Cross = CrossTarget { |
| 1586 | .arch = target_arch, | 1586 | .arch = target_arch, |
| 1587 | .os = target_os, | 1587 | .os = target_os, |
| 1588 | .environ = target_environ, | 1588 | .environ = target_environ, |
| ... | @@ -1620,13 +1620,13 @@ pub const TestStep = struct { | ... | @@ -1620,13 +1620,13 @@ pub const TestStep = struct { |
| 1620 | Target.Native => {}, | 1620 | Target.Native => {}, |
| 1621 | Target.Cross => |cross_target| { | 1621 | Target.Cross => |cross_target| { |
| 1622 | %%zig_args.append("--target-arch"); | 1622 | %%zig_args.append("--target-arch"); |
| 1623 | %%zig_args.append(@enumTagName(cross_target.arch)); | 1623 | %%zig_args.append(@tagName(cross_target.arch)); |
| 1624 | 1624 | ||
| 1625 | %%zig_args.append("--target-os"); | 1625 | %%zig_args.append("--target-os"); |
| 1626 | %%zig_args.append(@enumTagName(cross_target.os)); | 1626 | %%zig_args.append(@tagName(cross_target.os)); |
| 1627 | 1627 | ||
| 1628 | %%zig_args.append("--target-environ"); | 1628 | %%zig_args.append("--target-environ"); |
| 1629 | %%zig_args.append(@enumTagName(cross_target.environ)); | 1629 | %%zig_args.append(@tagName(cross_target.environ)); |
| 1630 | }, | 1630 | }, |
| 1631 | } | 1631 | } |
| 1632 | 1632 |
std/debug.zig+22-24| ... | @@ -280,7 +280,7 @@ const AbbrevAttr = struct { | ... | @@ -280,7 +280,7 @@ const AbbrevAttr = struct { |
| 280 | form_id: u64, | 280 | form_id: u64, |
| 281 | }; | 281 | }; |
| 282 | 282 | ||
| 283 | const FormValue = enum { | 283 | const FormValue = union(enum) { |
| 284 | Address: u64, | 284 | Address: u64, |
| 285 | Block: []u8, | 285 | Block: []u8, |
| 286 | Const: Constant, | 286 | Const: Constant, |
| ... | @@ -303,7 +303,7 @@ const Constant = struct { | ... | @@ -303,7 +303,7 @@ const Constant = struct { |
| 303 | return error.InvalidDebugInfo; | 303 | return error.InvalidDebugInfo; |
| 304 | if (self.signed) | 304 | if (self.signed) |
| 305 | return error.InvalidDebugInfo; | 305 | return error.InvalidDebugInfo; |
| 306 | return mem.readInt(self.payload, u64, false); | 306 | return mem.readInt(self.payload, u64, builtin.Endian.Little); |
| 307 | } | 307 | } |
| 308 | }; | 308 | }; |
| 309 | 309 | ||
| ... | @@ -475,16 +475,16 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usiz | ... | @@ -475,16 +475,16 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usiz |
| 475 | 475 | ||
| 476 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | 476 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { |
| 477 | const buf = %return readAllocBytes(allocator, in_stream, size); | 477 | const buf = %return readAllocBytes(allocator, in_stream, size); |
| 478 | return FormValue.Block { buf }; | 478 | return FormValue { .Block = buf }; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | 481 | fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { |
| 482 | const block_len = %return in_stream.readVarInt(false, usize, size); | 482 | const block_len = %return in_stream.readVarInt(builtin.Endian.Little, usize, size); |
| 483 | return parseFormValueBlockLen(allocator, in_stream, block_len); | 483 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 484 | } | 484 | } |
| 485 | 485 | ||
| 486 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue { | 486 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue { |
| 487 | FormValue.Const { Constant { | 487 | FormValue { .Const = Constant { |
| 488 | .signed = signed, | 488 | .signed = signed, |
| 489 | .payload = %return readAllocBytes(allocator, in_stream, size), | 489 | .payload = %return readAllocBytes(allocator, in_stream, size), |
| 490 | }} | 490 | }} |
| ... | @@ -510,7 +510,7 @@ fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 { | ... | @@ -510,7 +510,7 @@ fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 { |
| 510 | 510 | ||
| 511 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | 511 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { |
| 512 | const buf = %return readAllocBytes(allocator, in_stream, size); | 512 | const buf = %return readAllocBytes(allocator, in_stream, size); |
| 513 | return FormValue.Ref { buf }; | 513 | return FormValue { .Ref = buf }; |
| 514 | } | 514 | } |
| 515 | 515 | ||
| 516 | fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue { | 516 | fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue { |
| ... | @@ -520,7 +520,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptim | ... | @@ -520,7 +520,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptim |
| 520 | 520 | ||
| 521 | fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue { | 521 | fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue { |
| 522 | return switch (form_id) { | 522 | return switch (form_id) { |
| 523 | DW.FORM_addr => FormValue.Address { %return parseFormValueTargetAddrSize(in_stream) }, | 523 | DW.FORM_addr => FormValue { .Address = %return parseFormValueTargetAddrSize(in_stream) }, |
| 524 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), | 524 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), |
| 525 | DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), | 525 | DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), |
| 526 | DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4), | 526 | DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4), |
| ... | @@ -540,13 +540,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u | ... | @@ -540,13 +540,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u |
| 540 | DW.FORM_exprloc => { | 540 | DW.FORM_exprloc => { |
| 541 | const size = %return readULeb128(in_stream); | 541 | const size = %return readULeb128(in_stream); |
| 542 | const buf = %return readAllocBytes(allocator, in_stream, size); | 542 | const buf = %return readAllocBytes(allocator, in_stream, size); |
| 543 | return FormValue.ExprLoc { buf }; | 543 | return FormValue { .ExprLoc = buf }; |
| 544 | }, | ||
| 545 | DW.FORM_flag => FormValue.Flag { (%return in_stream.readByte()) != 0 }, | ||
| 546 | DW.FORM_flag_present => FormValue.Flag { true }, | ||
| 547 | DW.FORM_sec_offset => FormValue.SecOffset { | ||
| 548 | %return parseFormValueDwarfOffsetSize(in_stream, is_64) | ||
| 549 | }, | 544 | }, |
| 545 | DW.FORM_flag => FormValue { .Flag = (%return in_stream.readByte()) != 0 }, | ||
| 546 | DW.FORM_flag_present => FormValue { .Flag = true }, | ||
| 547 | DW.FORM_sec_offset => FormValue { .SecOffset = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | ||
| 550 | 548 | ||
| 551 | DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8), | 549 | DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8), |
| 552 | DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16), | 550 | DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16), |
| ... | @@ -557,11 +555,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u | ... | @@ -557,11 +555,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u |
| 557 | parseFormValueRefLen(allocator, in_stream, ref_len) | 555 | parseFormValueRefLen(allocator, in_stream, ref_len) |
| 558 | }, | 556 | }, |
| 559 | 557 | ||
| 560 | DW.FORM_ref_addr => FormValue.RefAddr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | 558 | DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 561 | DW.FORM_ref_sig8 => FormValue.RefSig8 { %return in_stream.readIntLe(u64) }, | 559 | DW.FORM_ref_sig8 => FormValue { .RefSig8 = %return in_stream.readIntLe(u64) }, |
| 562 | 560 | ||
| 563 | DW.FORM_string => FormValue.String { %return readStringRaw(allocator, in_stream) }, | 561 | DW.FORM_string => FormValue { .String = %return readStringRaw(allocator, in_stream) }, |
| 564 | DW.FORM_strp => FormValue.StrPtr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | 562 | DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 565 | DW.FORM_indirect => { | 563 | DW.FORM_indirect => { |
| 566 | const child_form_id = %return readULeb128(in_stream); | 564 | const child_form_id = %return readULeb128(in_stream); |
| 567 | parseFormValue(allocator, in_stream, child_form_id, is_64) | 565 | parseFormValue(allocator, in_stream, child_form_id, is_64) |
| ... | @@ -671,10 +669,10 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe | ... | @@ -671,10 +669,10 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 671 | continue; | 669 | continue; |
| 672 | } | 670 | } |
| 673 | 671 | ||
| 674 | const version = %return in_stream.readInt(st.elf.is_big_endian, u16); | 672 | const version = %return in_stream.readInt(st.elf.endian, u16); |
| 675 | if (version != 2) return error.InvalidDebugInfo; | 673 | if (version != 2) return error.InvalidDebugInfo; |
| 676 | 674 | ||
| 677 | const prologue_length = %return in_stream.readInt(st.elf.is_big_endian, u32); | 675 | const prologue_length = %return in_stream.readInt(st.elf.endian, u32); |
| 678 | const prog_start_offset = (%return in_file.getPos()) + prologue_length; | 676 | const prog_start_offset = (%return in_file.getPos()) + prologue_length; |
| 679 | 677 | ||
| 680 | const minimum_instruction_length = %return in_stream.readByte(); | 678 | const minimum_instruction_length = %return in_stream.readByte(); |
| ... | @@ -741,7 +739,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe | ... | @@ -741,7 +739,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 741 | return error.MissingDebugInfo; | 739 | return error.MissingDebugInfo; |
| 742 | }, | 740 | }, |
| 743 | DW.LNE_set_address => { | 741 | DW.LNE_set_address => { |
| 744 | const addr = %return in_stream.readInt(st.elf.is_big_endian, usize); | 742 | const addr = %return in_stream.readInt(st.elf.endian, usize); |
| 745 | prog.address = addr; | 743 | prog.address = addr; |
| 746 | }, | 744 | }, |
| 747 | DW.LNE_define_file => { | 745 | DW.LNE_define_file => { |
| ... | @@ -803,7 +801,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe | ... | @@ -803,7 +801,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 803 | prog.address += inc_addr; | 801 | prog.address += inc_addr; |
| 804 | }, | 802 | }, |
| 805 | DW.LNS_fixed_advance_pc => { | 803 | DW.LNS_fixed_advance_pc => { |
| 806 | const arg = %return in_stream.readInt(st.elf.is_big_endian, u16); | 804 | const arg = %return in_stream.readInt(st.elf.endian, u16); |
| 807 | prog.address += arg; | 805 | prog.address += arg; |
| 808 | }, | 806 | }, |
| 809 | DW.LNS_set_prologue_end => { | 807 | DW.LNS_set_prologue_end => { |
| ... | @@ -841,13 +839,13 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { | ... | @@ -841,13 +839,13 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { |
| 841 | return; | 839 | return; |
| 842 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | 840 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 843 | 841 | ||
| 844 | const version = %return in_stream.readInt(st.elf.is_big_endian, u16); | 842 | const version = %return in_stream.readInt(st.elf.endian, u16); |
| 845 | if (version < 2 or version > 5) return error.InvalidDebugInfo; | 843 | if (version < 2 or version > 5) return error.InvalidDebugInfo; |
| 846 | 844 | ||
| 847 | const debug_abbrev_offset = if (is_64) { | 845 | const debug_abbrev_offset = if (is_64) { |
| 848 | %return in_stream.readInt(st.elf.is_big_endian, u64) | 846 | %return in_stream.readInt(st.elf.endian, u64) |
| 849 | } else { | 847 | } else { |
| 850 | %return in_stream.readInt(st.elf.is_big_endian, u32) | 848 | %return in_stream.readInt(st.elf.endian, u32) |
| 851 | }; | 849 | }; |
| 852 | 850 | ||
| 853 | const address_size = %return in_stream.readByte(); | 851 | const address_size = %return in_stream.readByte(); |
std/elf.zig+40-39| ... | @@ -1,3 +1,4 @@ | ... | @@ -1,3 +1,4 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 1 | const std = @import("index.zig"); | 2 | const std = @import("index.zig"); |
| 2 | const io = std.io; | 3 | const io = std.io; |
| 3 | const math = std.math; | 4 | const math = std.math; |
| ... | @@ -67,7 +68,7 @@ pub const Elf = struct { | ... | @@ -67,7 +68,7 @@ pub const Elf = struct { |
| 67 | in_file: &io.File, | 68 | in_file: &io.File, |
| 68 | auto_close_stream: bool, | 69 | auto_close_stream: bool, |
| 69 | is_64: bool, | 70 | is_64: bool, |
| 70 | is_big_endian: bool, | 71 | endian: builtin.Endian, |
| 71 | file_type: FileType, | 72 | file_type: FileType, |
| 72 | arch: Arch, | 73 | arch: Arch, |
| 73 | entry_addr: u64, | 74 | entry_addr: u64, |
| ... | @@ -105,9 +106,9 @@ pub const Elf = struct { | ... | @@ -105,9 +106,9 @@ pub const Elf = struct { |
| 105 | else => return error.InvalidFormat, | 106 | else => return error.InvalidFormat, |
| 106 | }; | 107 | }; |
| 107 | 108 | ||
| 108 | elf.is_big_endian = switch (%return in.readByte()) { | 109 | elf.endian = switch (%return in.readByte()) { |
| 109 | 1 => false, | 110 | 1 => builtin.Endian.Little, |
| 110 | 2 => true, | 111 | 2 => builtin.Endian.Big, |
| 111 | else => return error.InvalidFormat, | 112 | else => return error.InvalidFormat, |
| 112 | }; | 113 | }; |
| 113 | 114 | ||
| ... | @@ -117,7 +118,7 @@ pub const Elf = struct { | ... | @@ -117,7 +118,7 @@ pub const Elf = struct { |
| 117 | // skip over padding | 118 | // skip over padding |
| 118 | %return elf.in_file.seekForward(9); | 119 | %return elf.in_file.seekForward(9); |
| 119 | 120 | ||
| 120 | elf.file_type = switch (%return in.readInt(elf.is_big_endian, u16)) { | 121 | elf.file_type = switch (%return in.readInt(elf.endian, u16)) { |
| 121 | 1 => FileType.Relocatable, | 122 | 1 => FileType.Relocatable, |
| 122 | 2 => FileType.Executable, | 123 | 2 => FileType.Executable, |
| 123 | 3 => FileType.Shared, | 124 | 3 => FileType.Shared, |
| ... | @@ -125,7 +126,7 @@ pub const Elf = struct { | ... | @@ -125,7 +126,7 @@ pub const Elf = struct { |
| 125 | else => return error.InvalidFormat, | 126 | else => return error.InvalidFormat, |
| 126 | }; | 127 | }; |
| 127 | 128 | ||
| 128 | elf.arch = switch (%return in.readInt(elf.is_big_endian, u16)) { | 129 | elf.arch = switch (%return in.readInt(elf.endian, u16)) { |
| 129 | 0x02 => Arch.Sparc, | 130 | 0x02 => Arch.Sparc, |
| 130 | 0x03 => Arch.x86, | 131 | 0x03 => Arch.x86, |
| 131 | 0x08 => Arch.Mips, | 132 | 0x08 => Arch.Mips, |
| ... | @@ -138,34 +139,34 @@ pub const Elf = struct { | ... | @@ -138,34 +139,34 @@ pub const Elf = struct { |
| 138 | else => return error.InvalidFormat, | 139 | else => return error.InvalidFormat, |
| 139 | }; | 140 | }; |
| 140 | 141 | ||
| 141 | const elf_version = %return in.readInt(elf.is_big_endian, u32); | 142 | const elf_version = %return in.readInt(elf.endian, u32); |
| 142 | if (elf_version != 1) return error.InvalidFormat; | 143 | if (elf_version != 1) return error.InvalidFormat; |
| 143 | 144 | ||
| 144 | if (elf.is_64) { | 145 | if (elf.is_64) { |
| 145 | elf.entry_addr = %return in.readInt(elf.is_big_endian, u64); | 146 | elf.entry_addr = %return in.readInt(elf.endian, u64); |
| 146 | elf.program_header_offset = %return in.readInt(elf.is_big_endian, u64); | 147 | elf.program_header_offset = %return in.readInt(elf.endian, u64); |
| 147 | elf.section_header_offset = %return in.readInt(elf.is_big_endian, u64); | 148 | elf.section_header_offset = %return in.readInt(elf.endian, u64); |
| 148 | } else { | 149 | } else { |
| 149 | elf.entry_addr = u64(%return in.readInt(elf.is_big_endian, u32)); | 150 | elf.entry_addr = u64(%return in.readInt(elf.endian, u32)); |
| 150 | elf.program_header_offset = u64(%return in.readInt(elf.is_big_endian, u32)); | 151 | elf.program_header_offset = u64(%return in.readInt(elf.endian, u32)); |
| 151 | elf.section_header_offset = u64(%return in.readInt(elf.is_big_endian, u32)); | 152 | elf.section_header_offset = u64(%return in.readInt(elf.endian, u32)); |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | // skip over flags | 155 | // skip over flags |
| 155 | %return elf.in_file.seekForward(4); | 156 | %return elf.in_file.seekForward(4); |
| 156 | 157 | ||
| 157 | const header_size = %return in.readInt(elf.is_big_endian, u16); | 158 | const header_size = %return in.readInt(elf.endian, u16); |
| 158 | if ((elf.is_64 and header_size != 64) or | 159 | if ((elf.is_64 and header_size != 64) or |
| 159 | (!elf.is_64 and header_size != 52)) | 160 | (!elf.is_64 and header_size != 52)) |
| 160 | { | 161 | { |
| 161 | return error.InvalidFormat; | 162 | return error.InvalidFormat; |
| 162 | } | 163 | } |
| 163 | 164 | ||
| 164 | const ph_entry_size = %return in.readInt(elf.is_big_endian, u16); | 165 | const ph_entry_size = %return in.readInt(elf.endian, u16); |
| 165 | const ph_entry_count = %return in.readInt(elf.is_big_endian, u16); | 166 | const ph_entry_count = %return in.readInt(elf.endian, u16); |
| 166 | const sh_entry_size = %return in.readInt(elf.is_big_endian, u16); | 167 | const sh_entry_size = %return in.readInt(elf.endian, u16); |
| 167 | const sh_entry_count = %return in.readInt(elf.is_big_endian, u16); | 168 | const sh_entry_count = %return in.readInt(elf.endian, u16); |
| 168 | elf.string_section_index = u64(%return in.readInt(elf.is_big_endian, u16)); | 169 | elf.string_section_index = u64(%return in.readInt(elf.endian, u16)); |
| 169 | 170 | ||
| 170 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; | 171 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; |
| 171 | 172 | ||
| ... | @@ -188,32 +189,32 @@ pub const Elf = struct { | ... | @@ -188,32 +189,32 @@ pub const Elf = struct { |
| 188 | if (sh_entry_size != 64) return error.InvalidFormat; | 189 | if (sh_entry_size != 64) return error.InvalidFormat; |
| 189 | 190 | ||
| 190 | for (elf.section_headers) |*section| { | 191 | for (elf.section_headers) |*section| { |
| 191 | section.name = %return in.readInt(elf.is_big_endian, u32); | 192 | section.name = %return in.readInt(elf.endian, u32); |
| 192 | section.sh_type = %return in.readInt(elf.is_big_endian, u32); | 193 | section.sh_type = %return in.readInt(elf.endian, u32); |
| 193 | section.flags = %return in.readInt(elf.is_big_endian, u64); | 194 | section.flags = %return in.readInt(elf.endian, u64); |
| 194 | section.addr = %return in.readInt(elf.is_big_endian, u64); | 195 | section.addr = %return in.readInt(elf.endian, u64); |
| 195 | section.offset = %return in.readInt(elf.is_big_endian, u64); | 196 | section.offset = %return in.readInt(elf.endian, u64); |
| 196 | section.size = %return in.readInt(elf.is_big_endian, u64); | 197 | section.size = %return in.readInt(elf.endian, u64); |
| 197 | section.link = %return in.readInt(elf.is_big_endian, u32); | 198 | section.link = %return in.readInt(elf.endian, u32); |
| 198 | section.info = %return in.readInt(elf.is_big_endian, u32); | 199 | section.info = %return in.readInt(elf.endian, u32); |
| 199 | section.addr_align = %return in.readInt(elf.is_big_endian, u64); | 200 | section.addr_align = %return in.readInt(elf.endian, u64); |
| 200 | section.ent_size = %return in.readInt(elf.is_big_endian, u64); | 201 | section.ent_size = %return in.readInt(elf.endian, u64); |
| 201 | } | 202 | } |
| 202 | } else { | 203 | } else { |
| 203 | if (sh_entry_size != 40) return error.InvalidFormat; | 204 | if (sh_entry_size != 40) return error.InvalidFormat; |
| 204 | 205 | ||
| 205 | for (elf.section_headers) |*section| { | 206 | for (elf.section_headers) |*section| { |
| 206 | // TODO (multiple occurences) allow implicit cast from %u32 -> %u64 ? | 207 | // TODO (multiple occurences) allow implicit cast from %u32 -> %u64 ? |
| 207 | section.name = %return in.readInt(elf.is_big_endian, u32); | 208 | section.name = %return in.readInt(elf.endian, u32); |
| 208 | section.sh_type = %return in.readInt(elf.is_big_endian, u32); | 209 | section.sh_type = %return in.readInt(elf.endian, u32); |
| 209 | section.flags = u64(%return in.readInt(elf.is_big_endian, u32)); | 210 | section.flags = u64(%return in.readInt(elf.endian, u32)); |
| 210 | section.addr = u64(%return in.readInt(elf.is_big_endian, u32)); | 211 | section.addr = u64(%return in.readInt(elf.endian, u32)); |
| 211 | section.offset = u64(%return in.readInt(elf.is_big_endian, u32)); | 212 | section.offset = u64(%return in.readInt(elf.endian, u32)); |
| 212 | section.size = u64(%return in.readInt(elf.is_big_endian, u32)); | 213 | section.size = u64(%return in.readInt(elf.endian, u32)); |
| 213 | section.link = %return in.readInt(elf.is_big_endian, u32); | 214 | section.link = %return in.readInt(elf.endian, u32); |
| 214 | section.info = %return in.readInt(elf.is_big_endian, u32); | 215 | section.info = %return in.readInt(elf.endian, u32); |
| 215 | section.addr_align = u64(%return in.readInt(elf.is_big_endian, u32)); | 216 | section.addr_align = u64(%return in.readInt(elf.endian, u32)); |
| 216 | section.ent_size = u64(%return in.readInt(elf.is_big_endian, u32)); | 217 | section.ent_size = u64(%return in.readInt(elf.endian, u32)); |
| 217 | } | 218 | } |
| 218 | } | 219 | } |
| 219 | 220 |
std/endian.zig+2-2| ... | @@ -9,8 +9,8 @@ pub fn swapIfBe(comptime T: type, x: T) -> T { | ... | @@ -9,8 +9,8 @@ pub fn swapIfBe(comptime T: type, x: T) -> T { |
| 9 | swapIf(true, T, x) | 9 | swapIf(true, T, x) |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | pub fn swapIf(is_be: bool, comptime T: type, x: T) -> T { | 12 | pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T { |
| 13 | if (builtin.is_big_endian == is_be) swap(T, x) else x | 13 | if (builtin.endian == endian) swap(T, x) else x |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | pub fn swap(comptime T: type, x: T) -> T { | 16 | pub fn swap(comptime T: type, x: T) -> T { |
std/io.zig+7-7| ... | @@ -259,7 +259,7 @@ pub const File = struct { | ... | @@ -259,7 +259,7 @@ pub const File = struct { |
| 259 | if (err > 0) { | 259 | if (err > 0) { |
| 260 | return switch (err) { | 260 | return switch (err) { |
| 261 | system.EBADF => error.BadFd, | 261 | system.EBADF => error.BadFd, |
| 262 | system.ENOMEM => error.OutOfMemory, | 262 | system.ENOMEM => error.SystemResources, |
| 263 | else => os.unexpectedErrorPosix(err), | 263 | else => os.unexpectedErrorPosix(err), |
| 264 | } | 264 | } |
| 265 | } | 265 | } |
| ... | @@ -441,26 +441,26 @@ pub const InStream = struct { | ... | @@ -441,26 +441,26 @@ pub const InStream = struct { |
| 441 | } | 441 | } |
| 442 | 442 | ||
| 443 | pub fn readIntLe(self: &InStream, comptime T: type) -> %T { | 443 | pub fn readIntLe(self: &InStream, comptime T: type) -> %T { |
| 444 | return self.readInt(false, T); | 444 | return self.readInt(builtin.Endian.Little, T); |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | pub fn readIntBe(self: &InStream, comptime T: type) -> %T { | 447 | pub fn readIntBe(self: &InStream, comptime T: type) -> %T { |
| 448 | return self.readInt(true, T); | 448 | return self.readInt(builtin.Endian.Big, T); |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | pub fn readInt(self: &InStream, is_be: bool, comptime T: type) -> %T { | 451 | pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) -> %T { |
| 452 | var bytes: [@sizeOf(T)]u8 = undefined; | 452 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 453 | %return self.readNoEof(bytes[0..]); | 453 | %return self.readNoEof(bytes[0..]); |
| 454 | return mem.readInt(bytes, T, is_be); | 454 | return mem.readInt(bytes, T, endian); |
| 455 | } | 455 | } |
| 456 | 456 | ||
| 457 | pub fn readVarInt(self: &InStream, is_be: bool, comptime T: type, size: usize) -> %T { | 457 | pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) -> %T { |
| 458 | assert(size <= @sizeOf(T)); | 458 | assert(size <= @sizeOf(T)); |
| 459 | assert(size <= 8); | 459 | assert(size <= 8); |
| 460 | var input_buf: [8]u8 = undefined; | 460 | var input_buf: [8]u8 = undefined; |
| 461 | const input_slice = input_buf[0..size]; | 461 | const input_slice = input_buf[0..size]; |
| 462 | %return self.readNoEof(input_slice); | 462 | %return self.readNoEof(input_slice); |
| 463 | return mem.readInt(input_slice, T, is_be); | 463 | return mem.readInt(input_slice, T, endian); |
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | 466 |
std/mem.zig+79-32| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const debug = @import("debug.zig"); | 1 | const debug = @import("debug.zig"); |
| 2 | const assert = debug.assert; | 2 | const assert = debug.assert; |
| 3 | const math = @import("math/index.zig"); | 3 | const math = @import("math/index.zig"); |
| 4 | const builtin = @import("builtin"); | ||
| 4 | 5 | ||
| 5 | pub const Cmp = math.Cmp; | 6 | pub const Cmp = math.Cmp; |
| 6 | 7 | ||
| ... | @@ -180,43 +181,78 @@ test "mem.indexOf" { | ... | @@ -180,43 +181,78 @@ test "mem.indexOf" { |
| 180 | /// Reads an integer from memory with size equal to bytes.len. | 181 | /// Reads an integer from memory with size equal to bytes.len. |
| 181 | /// T specifies the return type, which must be large enough to store | 182 | /// T specifies the return type, which must be large enough to store |
| 182 | /// the result. | 183 | /// the result. |
| 183 | pub fn readInt(bytes: []const u8, comptime T: type, big_endian: bool) -> T { | 184 | /// See also ::readIntBE or ::readIntLE. |
| 185 | pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) -> T { | ||
| 184 | if (T.bit_count == 8) { | 186 | if (T.bit_count == 8) { |
| 185 | return bytes[0]; | 187 | return bytes[0]; |
| 186 | } | 188 | } |
| 187 | var result: T = 0; | 189 | var result: T = 0; |
| 188 | if (big_endian) { | 190 | switch (endian) { |
| 189 | for (bytes) |b| { | 191 | builtin.Endian.Big => { |
| 190 | result = (result << 8) | b; | 192 | for (bytes) |b| { |
| 191 | } | 193 | result = (result << 8) | b; |
| 192 | } else { | 194 | } |
| 193 | const ShiftType = math.Log2Int(T); | 195 | }, |
| 194 | for (bytes) |b, index| { | 196 | builtin.Endian.Little => { |
| 195 | result = result | (T(b) << ShiftType(index * 8)); | 197 | const ShiftType = math.Log2Int(T); |
| 196 | } | 198 | for (bytes) |b, index| { |
| 199 | result = result | (T(b) << ShiftType(index * 8)); | ||
| 200 | } | ||
| 201 | }, | ||
| 197 | } | 202 | } |
| 198 | return result; | 203 | return result; |
| 199 | } | 204 | } |
| 200 | 205 | ||
| 206 | /// Reads a big-endian int of type T from bytes. | ||
| 207 | /// bytes.len must be exactly @sizeOf(T). | ||
| 208 | pub fn readIntBE(comptime T: type, bytes: []const u8) -> T { | ||
| 209 | if (T.is_signed) { | ||
| 210 | return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes)); | ||
| 211 | } | ||
| 212 | assert(bytes.len == @sizeOf(T)); | ||
| 213 | var result: T = 0; | ||
| 214 | {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) { | ||
| 215 | result = (result << 8) | T(bytes[i]); | ||
| 216 | }} | ||
| 217 | return result; | ||
| 218 | } | ||
| 219 | |||
| 220 | /// Reads a little-endian int of type T from bytes. | ||
| 221 | /// bytes.len must be exactly @sizeOf(T). | ||
| 222 | pub fn readIntLE(comptime T: type, bytes: []const u8) -> T { | ||
| 223 | if (T.is_signed) { | ||
| 224 | return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes)); | ||
| 225 | } | ||
| 226 | assert(bytes.len == @sizeOf(T)); | ||
| 227 | var result: T = 0; | ||
| 228 | {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) { | ||
| 229 | result |= T(bytes[i]) << i * 8; | ||
| 230 | }} | ||
| 231 | return result; | ||
| 232 | } | ||
| 233 | |||
| 201 | /// Writes an integer to memory with size equal to bytes.len. Pads with zeroes | 234 | /// Writes an integer to memory with size equal to bytes.len. Pads with zeroes |
| 202 | /// to fill the entire buffer provided. | 235 | /// to fill the entire buffer provided. |
| 203 | /// value must be an integer. | 236 | /// value must be an integer. |
| 204 | pub fn writeInt(buf: []u8, value: var, big_endian: bool) { | 237 | pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) { |
| 205 | const uint = @IntType(false, @typeOf(value).bit_count); | 238 | const uint = @IntType(false, @typeOf(value).bit_count); |
| 206 | var bits = @truncate(uint, value); | 239 | var bits = @truncate(uint, value); |
| 207 | if (big_endian) { | 240 | switch (endian) { |
| 208 | var index: usize = buf.len; | 241 | builtin.Endian.Big => { |
| 209 | while (index != 0) { | 242 | var index: usize = buf.len; |
| 210 | index -= 1; | 243 | while (index != 0) { |
| 211 | 244 | index -= 1; | |
| 212 | buf[index] = @truncate(u8, bits); | 245 | |
| 213 | bits >>= 8; | 246 | buf[index] = @truncate(u8, bits); |
| 214 | } | 247 | bits >>= 8; |
| 215 | } else { | 248 | } |
| 216 | for (buf) |*b| { | 249 | }, |
| 217 | *b = @truncate(u8, bits); | 250 | builtin.Endian.Little => { |
| 218 | bits >>= 8; | 251 | for (buf) |*b| { |
| 219 | } | 252 | *b = @truncate(u8, bits); |
| 253 | bits >>= 8; | ||
| 254 | } | ||
| 255 | }, | ||
| 220 | } | 256 | } |
| 221 | assert(bits == 0); | 257 | assert(bits == 0); |
| 222 | } | 258 | } |
| ... | @@ -348,19 +384,30 @@ test "testReadInt" { | ... | @@ -348,19 +384,30 @@ test "testReadInt" { |
| 348 | fn testReadIntImpl() { | 384 | fn testReadIntImpl() { |
| 349 | { | 385 | { |
| 350 | const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 }; | 386 | const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 }; |
| 351 | assert(readInt(bytes, u32, true) == 0x12345678); | 387 | assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678); |
| 352 | assert(readInt(bytes, u32, false) == 0x78563412); | 388 | assert(readIntBE(u32, bytes) == 0x12345678); |
| 389 | assert(readIntBE(i32, bytes) == 0x12345678); | ||
| 390 | assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412); | ||
| 391 | assert(readIntLE(u32, bytes) == 0x78563412); | ||
| 392 | assert(readIntLE(i32, bytes) == 0x78563412); | ||
| 353 | } | 393 | } |
| 354 | { | 394 | { |
| 355 | const buf = []u8{0x00, 0x00, 0x12, 0x34}; | 395 | const buf = []u8{0x00, 0x00, 0x12, 0x34}; |
| 356 | const answer = readInt(buf, u64, true); | 396 | const answer = readInt(buf, u64, builtin.Endian.Big); |
| 357 | assert(answer == 0x00001234); | 397 | assert(answer == 0x00001234); |
| 358 | } | 398 | } |
| 359 | { | 399 | { |
| 360 | const buf = []u8{0x12, 0x34, 0x00, 0x00}; | 400 | const buf = []u8{0x12, 0x34, 0x00, 0x00}; |
| 361 | const answer = readInt(buf, u64, false); | 401 | const answer = readInt(buf, u64, builtin.Endian.Little); |
| 362 | assert(answer == 0x00003412); | 402 | assert(answer == 0x00003412); |
| 363 | } | 403 | } |
| 404 | { | ||
| 405 | const bytes = []u8{0xff, 0xfe}; | ||
| 406 | assert(readIntBE(u16, bytes) == 0xfffe); | ||
| 407 | assert(readIntBE(i16, bytes) == -0x0002); | ||
| 408 | assert(readIntLE(u16, bytes) == 0xfeff); | ||
| 409 | assert(readIntLE(i16, bytes) == -0x0101); | ||
| 410 | } | ||
| 364 | } | 411 | } |
| 365 | 412 | ||
| 366 | test "testWriteInt" { | 413 | test "testWriteInt" { |
| ... | @@ -370,16 +417,16 @@ test "testWriteInt" { | ... | @@ -370,16 +417,16 @@ test "testWriteInt" { |
| 370 | fn testWriteIntImpl() { | 417 | fn testWriteIntImpl() { |
| 371 | var bytes: [4]u8 = undefined; | 418 | var bytes: [4]u8 = undefined; |
| 372 | 419 | ||
| 373 | writeInt(bytes[0..], u32(0x12345678), true); | 420 | writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big); |
| 374 | assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 })); | 421 | assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 })); |
| 375 | 422 | ||
| 376 | writeInt(bytes[0..], u32(0x78563412), false); | 423 | writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little); |
| 377 | assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 })); | 424 | assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 })); |
| 378 | 425 | ||
| 379 | writeInt(bytes[0..], u16(0x1234), true); | 426 | writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big); |
| 380 | assert(eql(u8, bytes, []u8{ 0x00, 0x00, 0x12, 0x34 })); | 427 | assert(eql(u8, bytes, []u8{ 0x00, 0x00, 0x12, 0x34 })); |
| 381 | 428 | ||
| 382 | writeInt(bytes[0..], u16(0x1234), false); | 429 | writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little); |
| 383 | assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 })); | 430 | assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 })); |
| 384 | } | 431 | } |
| 385 | 432 |
std/os/child_process.zig+9-9| ... | @@ -58,7 +58,7 @@ pub const ChildProcess = struct { | ... | @@ -58,7 +58,7 @@ pub const ChildProcess = struct { |
| 58 | err_pipe: if (is_windows) void else [2]i32, | 58 | err_pipe: if (is_windows) void else [2]i32, |
| 59 | llnode: if (is_windows) void else LinkedList(&ChildProcess).Node, | 59 | llnode: if (is_windows) void else LinkedList(&ChildProcess).Node, |
| 60 | 60 | ||
| 61 | pub const Term = enum { | 61 | pub const Term = union(enum) { |
| 62 | Exited: i32, | 62 | Exited: i32, |
| 63 | Signal: i32, | 63 | Signal: i32, |
| 64 | Stopped: i32, | 64 | Stopped: i32, |
| ... | @@ -213,9 +213,9 @@ pub const ChildProcess = struct { | ... | @@ -213,9 +213,9 @@ pub const ChildProcess = struct { |
| 213 | self.term = (%Term)({ | 213 | self.term = (%Term)({ |
| 214 | var exit_code: windows.DWORD = undefined; | 214 | var exit_code: windows.DWORD = undefined; |
| 215 | if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) { | 215 | if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) { |
| 216 | Term.Unknown{0} | 216 | Term { .Unknown = 0 } |
| 217 | } else { | 217 | } else { |
| 218 | Term.Exited {@bitCast(i32, exit_code)} | 218 | Term { .Exited = @bitCast(i32, exit_code)} |
| 219 | } | 219 | } |
| 220 | }); | 220 | }); |
| 221 | 221 | ||
| ... | @@ -281,13 +281,13 @@ pub const ChildProcess = struct { | ... | @@ -281,13 +281,13 @@ pub const ChildProcess = struct { |
| 281 | 281 | ||
| 282 | fn statusToTerm(status: i32) -> Term { | 282 | fn statusToTerm(status: i32) -> Term { |
| 283 | return if (posix.WIFEXITED(status)) { | 283 | return if (posix.WIFEXITED(status)) { |
| 284 | Term.Exited { posix.WEXITSTATUS(status) } | 284 | Term { .Exited = posix.WEXITSTATUS(status) } |
| 285 | } else if (posix.WIFSIGNALED(status)) { | 285 | } else if (posix.WIFSIGNALED(status)) { |
| 286 | Term.Signal { posix.WTERMSIG(status) } | 286 | Term { .Signal = posix.WTERMSIG(status) } |
| 287 | } else if (posix.WIFSTOPPED(status)) { | 287 | } else if (posix.WIFSTOPPED(status)) { |
| 288 | Term.Stopped { posix.WSTOPSIG(status) } | 288 | Term { .Stopped = posix.WSTOPSIG(status) } |
| 289 | } else { | 289 | } else { |
| 290 | Term.Unknown { status } | 290 | Term { .Unknown = status } |
| 291 | }; | 291 | }; |
| 292 | } | 292 | } |
| 293 | 293 | ||
| ... | @@ -722,14 +722,14 @@ const ErrInt = @IntType(false, @sizeOf(error) * 8); | ... | @@ -722,14 +722,14 @@ const ErrInt = @IntType(false, @sizeOf(error) * 8); |
| 722 | 722 | ||
| 723 | fn writeIntFd(fd: i32, value: ErrInt) -> %void { | 723 | fn writeIntFd(fd: i32, value: ErrInt) -> %void { |
| 724 | var bytes: [@sizeOf(ErrInt)]u8 = undefined; | 724 | var bytes: [@sizeOf(ErrInt)]u8 = undefined; |
| 725 | mem.writeInt(bytes[0..], value, true); | 725 | mem.writeInt(bytes[0..], value, builtin.endian); |
| 726 | os.posixWrite(fd, bytes[0..]) %% return error.SystemResources; | 726 | os.posixWrite(fd, bytes[0..]) %% return error.SystemResources; |
| 727 | } | 727 | } |
| 728 | 728 | ||
| 729 | fn readIntFd(fd: i32) -> %ErrInt { | 729 | fn readIntFd(fd: i32) -> %ErrInt { |
| 730 | var bytes: [@sizeOf(ErrInt)]u8 = undefined; | 730 | var bytes: [@sizeOf(ErrInt)]u8 = undefined; |
| 731 | os.posixRead(fd, bytes[0..]) %% return error.SystemResources; | 731 | os.posixRead(fd, bytes[0..]) %% return error.SystemResources; |
| 732 | return mem.readInt(bytes[0..], ErrInt, true); | 732 | return mem.readInt(bytes[0..], ErrInt, builtin.endian); |
| 733 | } | 733 | } |
| 734 | 734 | ||
| 735 | extern fn sigchld_handler(_: i32) { | 735 | extern fn sigchld_handler(_: i32) { |
std/os/index.zig+3-2| ... | @@ -939,6 +939,7 @@ start_over: | ... | @@ -939,6 +939,7 @@ start_over: |
| 939 | } | 939 | } |
| 940 | 940 | ||
| 941 | pub const Dir = struct { | 941 | pub const Dir = struct { |
| 942 | // See man getdents | ||
| 942 | fd: i32, | 943 | fd: i32, |
| 943 | allocator: &Allocator, | 944 | allocator: &Allocator, |
| 944 | buf: []u8, | 945 | buf: []u8, |
| ... | @@ -981,7 +982,7 @@ pub const Dir = struct { | ... | @@ -981,7 +982,7 @@ pub const Dir = struct { |
| 981 | 982 | ||
| 982 | pub fn close(self: &Dir) { | 983 | pub fn close(self: &Dir) { |
| 983 | self.allocator.free(self.buf); | 984 | self.allocator.free(self.buf); |
| 984 | close(self.fd); | 985 | os.close(self.fd); |
| 985 | } | 986 | } |
| 986 | 987 | ||
| 987 | /// Memory such as file names referenced in this returned entry becomes invalid | 988 | /// Memory such as file names referenced in this returned entry becomes invalid |
| ... | @@ -1013,7 +1014,7 @@ pub const Dir = struct { | ... | @@ -1013,7 +1014,7 @@ pub const Dir = struct { |
| 1013 | break; | 1014 | break; |
| 1014 | } | 1015 | } |
| 1015 | } | 1016 | } |
| 1016 | const linux_entry = @ptrCast(&LinuxEntry, &self.buf[self.index]); | 1017 | const linux_entry = @ptrCast(& align(1) LinuxEntry, &self.buf[self.index]); |
| 1017 | const next_index = self.index + linux_entry.d_reclen; | 1018 | const next_index = self.index + linux_entry.d_reclen; |
| 1018 | self.index = next_index; | 1019 | self.index = next_index; |
| 1019 | 1020 |
std/os/path.zig+1-1| ... | @@ -1016,7 +1016,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { | ... | @@ -1016,7 +1016,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 1016 | 1016 | ||
| 1017 | return os.readLink(allocator, proc_path); | 1017 | return os.readLink(allocator, proc_path); |
| 1018 | }, | 1018 | }, |
| 1019 | else => @compileError("TODO implement os.path.real for " ++ @enumTagName(builtin.os)), | 1019 | else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)), |
| 1020 | } | 1020 | } |
| 1021 | } | 1021 | } |
| 1022 | 1022 |
std/rand.zig+3-3| ... | @@ -50,12 +50,12 @@ pub const Rand = struct { | ... | @@ -50,12 +50,12 @@ pub const Rand = struct { |
| 50 | pub fn fillBytes(r: &Rand, buf: []u8) { | 50 | pub fn fillBytes(r: &Rand, buf: []u8) { |
| 51 | var bytes_left = buf.len; | 51 | var bytes_left = buf.len; |
| 52 | while (bytes_left >= @sizeOf(usize)) { | 52 | while (bytes_left >= @sizeOf(usize)) { |
| 53 | mem.writeInt(buf[buf.len - bytes_left..], r.rng.get(), false); | 53 | mem.writeInt(buf[buf.len - bytes_left..], r.rng.get(), builtin.Endian.Little); |
| 54 | bytes_left -= @sizeOf(usize); | 54 | bytes_left -= @sizeOf(usize); |
| 55 | } | 55 | } |
| 56 | if (bytes_left > 0) { | 56 | if (bytes_left > 0) { |
| 57 | var rand_val_array: [@sizeOf(usize)]u8 = undefined; | 57 | var rand_val_array: [@sizeOf(usize)]u8 = undefined; |
| 58 | mem.writeInt(rand_val_array[0..], r.rng.get(), false); | 58 | mem.writeInt(rand_val_array[0..], r.rng.get(), builtin.Endian.Little); |
| 59 | while (bytes_left > 0) { | 59 | while (bytes_left > 0) { |
| 60 | buf[buf.len - bytes_left] = rand_val_array[@sizeOf(usize) - bytes_left]; | 60 | buf[buf.len - bytes_left] = rand_val_array[@sizeOf(usize) - bytes_left]; |
| 61 | bytes_left -= 1; | 61 | bytes_left -= 1; |
| ... | @@ -98,7 +98,7 @@ pub const Rand = struct { | ... | @@ -98,7 +98,7 @@ pub const Rand = struct { |
| 98 | 98 | ||
| 99 | while (true) { | 99 | while (true) { |
| 100 | r.fillBytes(rand_val_array[0..]); | 100 | r.fillBytes(rand_val_array[0..]); |
| 101 | const rand_val = mem.readInt(rand_val_array, T, false); | 101 | const rand_val = mem.readInt(rand_val_array, T, builtin.Endian.Little); |
| 102 | if (rand_val < upper_bound) { | 102 | if (rand_val < upper_bound) { |
| 103 | return start + (rand_val % total_range); | 103 | return start + (rand_val % total_range); |
| 104 | } | 104 | } |
std/sort.zig+70| ... | @@ -4,6 +4,19 @@ const math = @import("math/index.zig"); | ... | @@ -4,6 +4,19 @@ const math = @import("math/index.zig"); |
| 4 | 4 | ||
| 5 | pub const Cmp = math.Cmp; | 5 | pub const Cmp = math.Cmp; |
| 6 | 6 | ||
| 7 | /// Stable sort using O(1) space. Currently implemented as insertion sort. | ||
| 8 | pub fn sort_stable(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) { | ||
| 9 | {var i: usize = 1; while (i < array.len) : (i += 1) { | ||
| 10 | const x = array[i]; | ||
| 11 | var j: usize = i; | ||
| 12 | while (j > 0 and cmp(array[j - 1], x) == Cmp.Greater) : (j -= 1) { | ||
| 13 | array[j] = array[j - 1]; | ||
| 14 | } | ||
| 15 | array[j] = x; | ||
| 16 | }} | ||
| 17 | } | ||
| 18 | |||
| 19 | /// Unstable sort using O(n) stack space. Currently implemented as quicksort. | ||
| 7 | pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) { | 20 | pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) { |
| 8 | if (array.len > 0) { | 21 | if (array.len > 0) { |
| 9 | quicksort(T, array, 0, array.len - 1, cmp); | 22 | quicksort(T, array, 0, array.len - 1, cmp); |
| ... | @@ -58,6 +71,63 @@ fn reverse(was: Cmp) -> Cmp { | ... | @@ -58,6 +71,63 @@ fn reverse(was: Cmp) -> Cmp { |
| 58 | // --------------------------------------- | 71 | // --------------------------------------- |
| 59 | // tests | 72 | // tests |
| 60 | 73 | ||
| 74 | test "stable sort" { | ||
| 75 | testStableSort(); | ||
| 76 | // TODO: uncomment this after https://github.com/zig-lang/zig/issues/639 | ||
| 77 | //comptime testStableSort(); | ||
| 78 | } | ||
| 79 | fn testStableSort() { | ||
| 80 | var expected = []IdAndValue { | ||
| 81 | IdAndValue{.id = 0, .value = 0}, | ||
| 82 | IdAndValue{.id = 1, .value = 0}, | ||
| 83 | IdAndValue{.id = 2, .value = 0}, | ||
| 84 | IdAndValue{.id = 0, .value = 1}, | ||
| 85 | IdAndValue{.id = 1, .value = 1}, | ||
| 86 | IdAndValue{.id = 2, .value = 1}, | ||
| 87 | IdAndValue{.id = 0, .value = 2}, | ||
| 88 | IdAndValue{.id = 1, .value = 2}, | ||
| 89 | IdAndValue{.id = 2, .value = 2}, | ||
| 90 | }; | ||
| 91 | var cases = [][9]IdAndValue { | ||
| 92 | []IdAndValue { | ||
| 93 | IdAndValue{.id = 0, .value = 0}, | ||
| 94 | IdAndValue{.id = 0, .value = 1}, | ||
| 95 | IdAndValue{.id = 0, .value = 2}, | ||
| 96 | IdAndValue{.id = 1, .value = 0}, | ||
| 97 | IdAndValue{.id = 1, .value = 1}, | ||
| 98 | IdAndValue{.id = 1, .value = 2}, | ||
| 99 | IdAndValue{.id = 2, .value = 0}, | ||
| 100 | IdAndValue{.id = 2, .value = 1}, | ||
| 101 | IdAndValue{.id = 2, .value = 2}, | ||
| 102 | }, | ||
| 103 | []IdAndValue { | ||
| 104 | IdAndValue{.id = 0, .value = 2}, | ||
| 105 | IdAndValue{.id = 0, .value = 1}, | ||
| 106 | IdAndValue{.id = 0, .value = 0}, | ||
| 107 | IdAndValue{.id = 1, .value = 2}, | ||
| 108 | IdAndValue{.id = 1, .value = 1}, | ||
| 109 | IdAndValue{.id = 1, .value = 0}, | ||
| 110 | IdAndValue{.id = 2, .value = 2}, | ||
| 111 | IdAndValue{.id = 2, .value = 1}, | ||
| 112 | IdAndValue{.id = 2, .value = 0}, | ||
| 113 | }, | ||
| 114 | }; | ||
| 115 | for (cases) |*case| { | ||
| 116 | sort_stable(IdAndValue, (*case)[0..], cmpByValue); | ||
| 117 | for (*case) |item, i| { | ||
| 118 | assert(item.id == expected[i].id); | ||
| 119 | assert(item.value == expected[i].value); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } | ||
| 123 | const IdAndValue = struct { | ||
| 124 | id: i32, | ||
| 125 | value: i32, | ||
| 126 | }; | ||
| 127 | fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) -> Cmp { | ||
| 128 | return i32asc(a.value, b.value); | ||
| 129 | } | ||
| 130 | |||
| 61 | test "testSort" { | 131 | test "testSort" { |
| 62 | const u8cases = [][]const []const u8 { | 132 | const u8cases = [][]const []const u8 { |
| 63 | [][]const u8{"", ""}, | 133 | [][]const u8{"", ""}, |
std/special/compiler_rt/udivmod.zig+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | const builtin = @import("builtin"); | 1 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 2 | const is_test = builtin.is_test; |
| 3 | 3 | ||
| 4 | const low = if (builtin.is_big_endian) 1 else 0; | 4 | const low = switch (builtin.endian) { builtin.Endian.Big => 1, builtin.Endian.Little => 0 }; |
| 5 | const high = 1 - low; | 5 | const high = 1 - low; |
| 6 | 6 | ||
| 7 | pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?&DoubleInt) -> DoubleInt { | 7 | pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?&DoubleInt) -> DoubleInt { |
test/cases/bugs/394.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const E = enum { A: [9]u8, B: u64, }; | 1 | const E = union(enum) { A: [9]u8, B: u64, }; |
| 2 | const S = struct { x: u8, y: E, }; | 2 | const S = struct { x: u8, y: E, }; |
| 3 | 3 | ||
| 4 | const assert = @import("std").debug.assert; | 4 | const assert = @import("std").debug.assert; |
| 5 | 5 | ||
| 6 | test "bug 394 fixed" { | 6 | test "bug 394 fixed" { |
| 7 | const x = S { .x = 3, .y = E.B {1} }; | 7 | const x = S { .x = 3, .y = E {.B = 1 } }; |
| 8 | assert(x.x == 3); | 8 | assert(x.x == 3); |
| 9 | } | 9 | } |
test/cases/enum.zig+171-17| ... | @@ -2,8 +2,8 @@ const assert = @import("std").debug.assert; | ... | @@ -2,8 +2,8 @@ const assert = @import("std").debug.assert; |
| 2 | const mem = @import("std").mem; | 2 | const mem = @import("std").mem; |
| 3 | 3 | ||
| 4 | test "enum type" { | 4 | test "enum type" { |
| 5 | const foo1 = Foo.One {13}; | 5 | const foo1 = Foo{ .One = 13}; |
| 6 | const foo2 = Foo.Two { Point { .x = 1234, .y = 5678, }}; | 6 | const foo2 = Foo{. Two = Point { .x = 1234, .y = 5678, }}; |
| 7 | const bar = Bar.B; | 7 | const bar = Bar.B; |
| 8 | 8 | ||
| 9 | assert(bar == Bar.B); | 9 | assert(bar == Bar.B); |
| ... | @@ -24,12 +24,12 @@ const Point = struct { | ... | @@ -24,12 +24,12 @@ const Point = struct { |
| 24 | x: u64, | 24 | x: u64, |
| 25 | y: u64, | 25 | y: u64, |
| 26 | }; | 26 | }; |
| 27 | const Foo = enum { | 27 | const Foo = union(enum) { |
| 28 | One: i32, | 28 | One: i32, |
| 29 | Two: Point, | 29 | Two: Point, |
| 30 | Three: void, | 30 | Three: void, |
| 31 | }; | 31 | }; |
| 32 | const FooNoVoid = enum { | 32 | const FooNoVoid = union(enum) { |
| 33 | One: i32, | 33 | One: i32, |
| 34 | Two: Point, | 34 | Two: Point, |
| 35 | }; | 35 | }; |
| ... | @@ -41,13 +41,13 @@ const Bar = enum { | ... | @@ -41,13 +41,13 @@ const Bar = enum { |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | fn returnAnInt(x: i32) -> Foo { | 43 | fn returnAnInt(x: i32) -> Foo { |
| 44 | Foo.One { x } | 44 | Foo { .One = x } |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | 47 | ||
| 48 | test "constant enum with payload" { | 48 | test "constant enum with payload" { |
| 49 | var empty = AnEnumWithPayload.Empty; | 49 | var empty = AnEnumWithPayload {.Empty = {}}; |
| 50 | var full = AnEnumWithPayload.Full {13}; | 50 | var full = AnEnumWithPayload {.Full = 13}; |
| 51 | shouldBeEmpty(empty); | 51 | shouldBeEmpty(empty); |
| 52 | shouldBeNotEmpty(full); | 52 | shouldBeNotEmpty(full); |
| 53 | } | 53 | } |
| ... | @@ -66,8 +66,8 @@ fn shouldBeNotEmpty(x: &const AnEnumWithPayload) { | ... | @@ -66,8 +66,8 @@ fn shouldBeNotEmpty(x: &const AnEnumWithPayload) { |
| 66 | } | 66 | } |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | const AnEnumWithPayload = enum { | 69 | const AnEnumWithPayload = union(enum) { |
| 70 | Empty, | 70 | Empty: void, |
| 71 | Full: i32, | 71 | Full: i32, |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| ... | @@ -89,8 +89,8 @@ test "enum to int" { | ... | @@ -89,8 +89,8 @@ test "enum to int" { |
| 89 | shouldEqual(Number.Four, 4); | 89 | shouldEqual(Number.Four, 4); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | fn shouldEqual(n: Number, expected: usize) { | 92 | fn shouldEqual(n: Number, expected: u3) { |
| 93 | assert(usize(n) == expected); | 93 | assert(u3(n) == expected); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | 96 | ||
| ... | @@ -98,7 +98,7 @@ test "int to enum" { | ... | @@ -98,7 +98,7 @@ test "int to enum" { |
| 98 | testIntToEnumEval(3); | 98 | testIntToEnumEval(3); |
| 99 | } | 99 | } |
| 100 | fn testIntToEnumEval(x: i32) { | 100 | fn testIntToEnumEval(x: i32) { |
| 101 | assert(IntToEnumNumber(x) == IntToEnumNumber.Three); | 101 | assert(IntToEnumNumber(u3(x)) == IntToEnumNumber.Three); |
| 102 | } | 102 | } |
| 103 | const IntToEnumNumber = enum { | 103 | const IntToEnumNumber = enum { |
| 104 | Zero, | 104 | Zero, |
| ... | @@ -109,13 +109,13 @@ const IntToEnumNumber = enum { | ... | @@ -109,13 +109,13 @@ const IntToEnumNumber = enum { |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | 111 | ||
| 112 | test "@enumTagName" { | 112 | test "@tagName" { |
| 113 | assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | 113 | assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); |
| 114 | comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | 114 | comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | fn testEnumTagNameBare(n: BareNumber) -> []const u8 { | 117 | fn testEnumTagNameBare(n: BareNumber) -> []const u8 { |
| 118 | return @enumTagName(n); | 118 | return @tagName(n); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | const BareNumber = enum { | 121 | const BareNumber = enum { |
| ... | @@ -132,12 +132,11 @@ test "enum alignment" { | ... | @@ -132,12 +132,11 @@ test "enum alignment" { |
| 132 | } | 132 | } |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | const AlignTestEnum = enum { | 135 | const AlignTestEnum = union(enum) { |
| 136 | A: [9]u8, | 136 | A: [9]u8, |
| 137 | B: u64, | 137 | B: u64, |
| 138 | }; | 138 | }; |
| 139 | 139 | ||
| 140 | const ValueCount0 = enum {}; | ||
| 141 | const ValueCount1 = enum { I0 }; | 140 | const ValueCount1 = enum { I0 }; |
| 142 | const ValueCount2 = enum { I0, I1 }; | 141 | const ValueCount2 = enum { I0, I1 }; |
| 143 | const ValueCount256 = enum { | 142 | const ValueCount256 = enum { |
| ... | @@ -183,10 +182,165 @@ const ValueCount257 = enum { | ... | @@ -183,10 +182,165 @@ const ValueCount257 = enum { |
| 183 | 182 | ||
| 184 | test "enum sizes" { | 183 | test "enum sizes" { |
| 185 | comptime { | 184 | comptime { |
| 186 | assert(@sizeOf(ValueCount0) == 0); | ||
| 187 | assert(@sizeOf(ValueCount1) == 0); | 185 | assert(@sizeOf(ValueCount1) == 0); |
| 188 | assert(@sizeOf(ValueCount2) == 1); | 186 | assert(@sizeOf(ValueCount2) == 1); |
| 189 | assert(@sizeOf(ValueCount256) == 1); | 187 | assert(@sizeOf(ValueCount256) == 1); |
| 190 | assert(@sizeOf(ValueCount257) == 2); | 188 | assert(@sizeOf(ValueCount257) == 2); |
| 191 | } | 189 | } |
| 192 | } | 190 | } |
| 191 | |||
| 192 | const Small2 = enum (u2) { | ||
| 193 | One, | ||
| 194 | Two, | ||
| 195 | }; | ||
| 196 | const Small = enum (u2) { | ||
| 197 | One, | ||
| 198 | Two, | ||
| 199 | Three, | ||
| 200 | Four, | ||
| 201 | }; | ||
| 202 | |||
| 203 | test "set enum tag type" { | ||
| 204 | { | ||
| 205 | var x = Small.One; | ||
| 206 | x = Small.Two; | ||
| 207 | comptime assert(@TagType(Small) == u2); | ||
| 208 | } | ||
| 209 | { | ||
| 210 | var x = Small2.One; | ||
| 211 | x = Small2.Two; | ||
| 212 | comptime assert(@TagType(Small2) == u2); | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | |||
| 217 | const A = enum (u3) { | ||
| 218 | One, | ||
| 219 | Two, | ||
| 220 | Three, | ||
| 221 | Four, | ||
| 222 | One2, | ||
| 223 | Two2, | ||
| 224 | Three2, | ||
| 225 | Four2, | ||
| 226 | }; | ||
| 227 | |||
| 228 | const B = enum (u3) { | ||
| 229 | One3, | ||
| 230 | Two3, | ||
| 231 | Three3, | ||
| 232 | Four3, | ||
| 233 | One23, | ||
| 234 | Two23, | ||
| 235 | Three23, | ||
| 236 | Four23, | ||
| 237 | }; | ||
| 238 | |||
| 239 | const C = enum (u2) { | ||
| 240 | One4, | ||
| 241 | Two4, | ||
| 242 | Three4, | ||
| 243 | Four4, | ||
| 244 | }; | ||
| 245 | |||
| 246 | const BitFieldOfEnums = packed struct { | ||
| 247 | a: A, | ||
| 248 | b: B, | ||
| 249 | c: C, | ||
| 250 | }; | ||
| 251 | |||
| 252 | const bit_field_1 = BitFieldOfEnums { | ||
| 253 | .a = A.Two, | ||
| 254 | .b = B.Three3, | ||
| 255 | .c = C.Four4, | ||
| 256 | }; | ||
| 257 | |||
| 258 | test "bit field access with enum fields" { | ||
| 259 | var data = bit_field_1; | ||
| 260 | assert(getA(&data) == A.Two); | ||
| 261 | assert(getB(&data) == B.Three3); | ||
| 262 | assert(getC(&data) == C.Four4); | ||
| 263 | comptime assert(@sizeOf(BitFieldOfEnums) == 1); | ||
| 264 | |||
| 265 | data.b = B.Four3; | ||
| 266 | assert(data.b == B.Four3); | ||
| 267 | |||
| 268 | data.a = A.Three; | ||
| 269 | assert(data.a == A.Three); | ||
| 270 | assert(data.b == B.Four3); | ||
| 271 | } | ||
| 272 | |||
| 273 | fn getA(data: &const BitFieldOfEnums) -> A { | ||
| 274 | return data.a; | ||
| 275 | } | ||
| 276 | |||
| 277 | fn getB(data: &const BitFieldOfEnums) -> B { | ||
| 278 | return data.b; | ||
| 279 | } | ||
| 280 | |||
| 281 | fn getC(data: &const BitFieldOfEnums) -> C { | ||
| 282 | return data.c; | ||
| 283 | } | ||
| 284 | |||
| 285 | test "casting enum to its tag type" { | ||
| 286 | testCastEnumToTagType(Small2.Two); | ||
| 287 | comptime testCastEnumToTagType(Small2.Two); | ||
| 288 | } | ||
| 289 | |||
| 290 | fn testCastEnumToTagType(value: Small2) { | ||
| 291 | assert(u2(value) == 1); | ||
| 292 | } | ||
| 293 | |||
| 294 | const MultipleChoice = enum(u32) { | ||
| 295 | A = 20, | ||
| 296 | B = 40, | ||
| 297 | C = 60, | ||
| 298 | D = 1000, | ||
| 299 | }; | ||
| 300 | |||
| 301 | test "enum with specified tag values" { | ||
| 302 | testEnumWithSpecifiedTagValues(MultipleChoice.C); | ||
| 303 | comptime testEnumWithSpecifiedTagValues(MultipleChoice.C); | ||
| 304 | } | ||
| 305 | |||
| 306 | fn testEnumWithSpecifiedTagValues(x: MultipleChoice) { | ||
| 307 | assert(u32(x) == 60); | ||
| 308 | assert(1234 == switch (x) { | ||
| 309 | MultipleChoice.A => 1, | ||
| 310 | MultipleChoice.B => 2, | ||
| 311 | MultipleChoice.C => u32(1234), | ||
| 312 | MultipleChoice.D => 4, | ||
| 313 | }); | ||
| 314 | } | ||
| 315 | |||
| 316 | const MultipleChoice2 = enum(u32) { | ||
| 317 | Unspecified1, | ||
| 318 | A = 20, | ||
| 319 | Unspecified2, | ||
| 320 | B = 40, | ||
| 321 | Unspecified3, | ||
| 322 | C = 60, | ||
| 323 | Unspecified4, | ||
| 324 | D = 1000, | ||
| 325 | Unspecified5, | ||
| 326 | }; | ||
| 327 | |||
| 328 | test "enum with specified and unspecified tag values" { | ||
| 329 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | ||
| 330 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | ||
| 331 | } | ||
| 332 | |||
| 333 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) { | ||
| 334 | assert(u32(x) == 1000); | ||
| 335 | assert(1234 == switch (x) { | ||
| 336 | MultipleChoice2.A => 1, | ||
| 337 | MultipleChoice2.B => 2, | ||
| 338 | MultipleChoice2.C => 3, | ||
| 339 | MultipleChoice2.D => u32(1234), | ||
| 340 | MultipleChoice2.Unspecified1 => 5, | ||
| 341 | MultipleChoice2.Unspecified2 => 6, | ||
| 342 | MultipleChoice2.Unspecified3 => 7, | ||
| 343 | MultipleChoice2.Unspecified4 => 8, | ||
| 344 | MultipleChoice2.Unspecified5 => 9, | ||
| 345 | }); | ||
| 346 | } |
test/cases/enum_with_members.zig+3-3| ... | @@ -2,7 +2,7 @@ const assert = @import("std").debug.assert; | ... | @@ -2,7 +2,7 @@ const assert = @import("std").debug.assert; |
| 2 | const mem = @import("std").mem; | 2 | const mem = @import("std").mem; |
| 3 | const fmt = @import("std").fmt; | 3 | const fmt = @import("std").fmt; |
| 4 | 4 | ||
| 5 | const ET = enum { | 5 | const ET = union(enum) { |
| 6 | SINT: i32, | 6 | SINT: i32, |
| 7 | UINT: u32, | 7 | UINT: u32, |
| 8 | 8 | ||
| ... | @@ -15,8 +15,8 @@ const ET = enum { | ... | @@ -15,8 +15,8 @@ const ET = enum { |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | test "enum with members" { | 17 | test "enum with members" { |
| 18 | const a = ET.SINT { -42 }; | 18 | const a = ET { .SINT = -42 }; |
| 19 | const b = ET.UINT { 42 }; | 19 | const b = ET { .UINT = 42 }; |
| 20 | var buf: [20]u8 = undefined; | 20 | var buf: [20]u8 = undefined; |
| 21 | 21 | ||
| 22 | assert(%%a.print(buf[0..]) == 3); | 22 | assert(%%a.print(buf[0..]) == 3); |
test/cases/misc.zig+9-7| ... | @@ -324,8 +324,8 @@ test "constant enum initialization with differing sizes" { | ... | @@ -324,8 +324,8 @@ test "constant enum initialization with differing sizes" { |
| 324 | test3_1(test3_foo); | 324 | test3_1(test3_foo); |
| 325 | test3_2(test3_bar); | 325 | test3_2(test3_bar); |
| 326 | } | 326 | } |
| 327 | const Test3Foo = enum { | 327 | const Test3Foo = union(enum) { |
| 328 | One, | 328 | One: void, |
| 329 | Two: f32, | 329 | Two: f32, |
| 330 | Three: Test3Point, | 330 | Three: Test3Point, |
| 331 | }; | 331 | }; |
| ... | @@ -333,8 +333,8 @@ const Test3Point = struct { | ... | @@ -333,8 +333,8 @@ const Test3Point = struct { |
| 333 | x: i32, | 333 | x: i32, |
| 334 | y: i32, | 334 | y: i32, |
| 335 | }; | 335 | }; |
| 336 | const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}}; | 336 | const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}}; |
| 337 | const test3_bar = Test3Foo.Two{13}; | 337 | const test3_bar = Test3Foo { .Two = 13}; |
| 338 | fn test3_1(f: &const Test3Foo) { | 338 | fn test3_1(f: &const Test3Foo) { |
| 339 | switch (*f) { | 339 | switch (*f) { |
| 340 | Test3Foo.Three => |pt| { | 340 | Test3Foo.Three => |pt| { |
| ... | @@ -449,7 +449,8 @@ fn testArray2DConstDoublePtr(ptr: &const f32) { | ... | @@ -449,7 +449,8 @@ fn testArray2DConstDoublePtr(ptr: &const f32) { |
| 449 | const Tid = builtin.TypeId; | 449 | const Tid = builtin.TypeId; |
| 450 | const AStruct = struct { x: i32, }; | 450 | const AStruct = struct { x: i32, }; |
| 451 | const AnEnum = enum { One, Two, }; | 451 | const AnEnum = enum { One, Two, }; |
| 452 | const AnEnumWithPayload = enum { One: i32, Two, }; | 452 | const AUnionEnum = union(enum) { One: i32, Two: void, }; |
| 453 | const AUnion = union { One: void, Two: void }; | ||
| 453 | 454 | ||
| 454 | test "@typeId" { | 455 | test "@typeId" { |
| 455 | comptime { | 456 | comptime { |
| ... | @@ -474,8 +475,9 @@ test "@typeId" { | ... | @@ -474,8 +475,9 @@ test "@typeId" { |
| 474 | assert(@typeId(%i32) == Tid.ErrorUnion); | 475 | assert(@typeId(%i32) == Tid.ErrorUnion); |
| 475 | assert(@typeId(error) == Tid.Error); | 476 | assert(@typeId(error) == Tid.Error); |
| 476 | assert(@typeId(AnEnum) == Tid.Enum); | 477 | assert(@typeId(AnEnum) == Tid.Enum); |
| 477 | assert(@typeId(@typeOf(AnEnumWithPayload.One)) == Tid.EnumTag); | 478 | assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); |
| 478 | // TODO union | 479 | assert(@typeId(AUnionEnum) == Tid.Union); |
| 480 | assert(@typeId(AUnion) == Tid.Union); | ||
| 479 | assert(@typeId(fn()) == Tid.Fn); | 481 | assert(@typeId(fn()) == Tid.Fn); |
| 480 | assert(@typeId(@typeOf(builtin)) == Tid.Namespace); | 482 | assert(@typeId(@typeOf(builtin)) == Tid.Namespace); |
| 481 | assert(@typeId(@typeOf({this})) == Tid.Block); | 483 | assert(@typeId(@typeOf({this})) == Tid.Block); |
test/cases/reflection.zig+2-2| ... | @@ -62,8 +62,8 @@ const Foo = struct { | ... | @@ -62,8 +62,8 @@ const Foo = struct { |
| 62 | three: void, | 62 | three: void, |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | const Bar = enum { | 65 | const Bar = union(enum) { |
| 66 | One, | 66 | One: void, |
| 67 | Two: i32, | 67 | Two: i32, |
| 68 | Three: bool, | 68 | Three: bool, |
| 69 | Four: f64, | 69 | Four: f64, |
test/cases/switch.zig+19-8| ... | @@ -83,14 +83,14 @@ const SwitchStatmentFoo = enum { | ... | @@ -83,14 +83,14 @@ const SwitchStatmentFoo = enum { |
| 83 | 83 | ||
| 84 | 84 | ||
| 85 | test "switch prong with variable" { | 85 | test "switch prong with variable" { |
| 86 | switchProngWithVarFn(SwitchProngWithVarEnum.One {13}); | 86 | switchProngWithVarFn(SwitchProngWithVarEnum { .One = 13}); |
| 87 | switchProngWithVarFn(SwitchProngWithVarEnum.Two {13.0}); | 87 | switchProngWithVarFn(SwitchProngWithVarEnum { .Two = 13.0}); |
| 88 | switchProngWithVarFn(SwitchProngWithVarEnum.Meh); | 88 | switchProngWithVarFn(SwitchProngWithVarEnum { .Meh = {}}); |
| 89 | } | 89 | } |
| 90 | const SwitchProngWithVarEnum = enum { | 90 | const SwitchProngWithVarEnum = union(enum) { |
| 91 | One: i32, | 91 | One: i32, |
| 92 | Two: f32, | 92 | Two: f32, |
| 93 | Meh, | 93 | Meh: void, |
| 94 | }; | 94 | }; |
| 95 | fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) { | 95 | fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) { |
| 96 | switch(*a) { | 96 | switch(*a) { |
| ... | @@ -112,7 +112,7 @@ test "switch on enum using pointer capture" { | ... | @@ -112,7 +112,7 @@ test "switch on enum using pointer capture" { |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | fn testSwitchEnumPtrCapture() { | 114 | fn testSwitchEnumPtrCapture() { |
| 115 | var value = SwitchProngWithVarEnum.One { 1234 }; | 115 | var value = SwitchProngWithVarEnum { .One = 1234 }; |
| 116 | switch (value) { | 116 | switch (value) { |
| 117 | SwitchProngWithVarEnum.One => |*x| *x += 1, | 117 | SwitchProngWithVarEnum.One => |*x| *x += 1, |
| 118 | else => unreachable, | 118 | else => unreachable, |
| ... | @@ -136,13 +136,13 @@ fn returnsFive() -> i32 { | ... | @@ -136,13 +136,13 @@ fn returnsFive() -> i32 { |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | 138 | ||
| 139 | const Number = enum { | 139 | const Number = union(enum) { |
| 140 | One: u64, | 140 | One: u64, |
| 141 | Two: u8, | 141 | Two: u8, |
| 142 | Three: f32, | 142 | Three: f32, |
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | const number = Number.Three { 1.23 }; | 145 | const number = Number { .Three = 1.23 }; |
| 146 | 146 | ||
| 147 | fn returnsFalse() -> bool { | 147 | fn returnsFalse() -> bool { |
| 148 | switch (number) { | 148 | switch (number) { |
| ... | @@ -224,3 +224,14 @@ fn switchWithUnreachable(x: i32) -> i32 { | ... | @@ -224,3 +224,14 @@ fn switchWithUnreachable(x: i32) -> i32 { |
| 224 | } | 224 | } |
| 225 | return 10; | 225 | return 10; |
| 226 | } | 226 | } |
| 227 | |||
| 228 | fn return_a_number() -> %i32 { | ||
| 229 | return 1; | ||
| 230 | } | ||
| 231 | |||
| 232 | test "capture value of switch with all unreachable prongs" { | ||
| 233 | const x = return_a_number() %% |err| switch (err) { | ||
| 234 | else => unreachable, | ||
| 235 | }; | ||
| 236 | assert(x == 1); | ||
| 237 | } |
test/cases/switch_prong_err_enum.zig+2-2| ... | @@ -9,14 +9,14 @@ fn readOnce() -> %u64 { | ... | @@ -9,14 +9,14 @@ fn readOnce() -> %u64 { |
| 9 | 9 | ||
| 10 | error InvalidDebugInfo; | 10 | error InvalidDebugInfo; |
| 11 | 11 | ||
| 12 | const FormValue = enum { | 12 | const FormValue = union(enum) { |
| 13 | Address: u64, | 13 | Address: u64, |
| 14 | Other: bool, | 14 | Other: bool, |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | fn doThing(form_id: u64) -> %FormValue { | 17 | fn doThing(form_id: u64) -> %FormValue { |
| 18 | return switch (form_id) { | 18 | return switch (form_id) { |
| 19 | 17 => FormValue.Address { %return readOnce() }, | 19 | 17 => FormValue { .Address = %return readOnce() }, |
| 20 | else => error.InvalidDebugInfo, | 20 | else => error.InvalidDebugInfo, |
| 21 | } | 21 | } |
| 22 | } | 22 | } |
test/cases/switch_prong_implicit_cast.zig+4-4| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | ||
| 3 | const FormValue = enum { | 3 | const FormValue = union(enum) { |
| 4 | One, | 4 | One: void, |
| 5 | Two: bool, | 5 | Two: bool, |
| 6 | }; | 6 | }; |
| 7 | 7 | ||
| ... | @@ -9,8 +9,8 @@ error Whatever; | ... | @@ -9,8 +9,8 @@ error Whatever; |
| 9 | 9 | ||
| 10 | fn foo(id: u64) -> %FormValue { | 10 | fn foo(id: u64) -> %FormValue { |
| 11 | switch (id) { | 11 | switch (id) { |
| 12 | 2 => FormValue.Two { true }, | 12 | 2 => FormValue { .Two = true }, |
| 13 | 1 => FormValue.One, | 13 | 1 => FormValue { .One = {} }, |
| 14 | else => return error.Whatever, | 14 | else => return error.Whatever, |
| 15 | } | 15 | } |
| 16 | } | 16 | } |
test/cases/union.zig+118-3| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | ||
| 3 | const Value = enum { | 3 | const Value = union(enum) { |
| 4 | Int: u64, | 4 | Int: u64, |
| 5 | Array: [9]u8, | 5 | Array: [9]u8, |
| 6 | }; | 6 | }; |
| ... | @@ -10,8 +10,8 @@ const Agg = struct { | ... | @@ -10,8 +10,8 @@ const Agg = struct { |
| 10 | val2: Value, | 10 | val2: Value, |
| 11 | }; | 11 | }; |
| 12 | 12 | ||
| 13 | const v1 = Value.Int { 1234 }; | 13 | const v1 = Value { .Int = 1234 }; |
| 14 | const v2 = Value.Array { []u8{3} ** 9 }; | 14 | const v2 = Value { .Array = []u8{3} ** 9 }; |
| 15 | 15 | ||
| 16 | const err = (%Agg)(Agg { | 16 | const err = (%Agg)(Agg { |
| 17 | .val1 = v1, | 17 | .val1 = v1, |
| ... | @@ -75,3 +75,118 @@ test "basic extern unions" { | ... | @@ -75,3 +75,118 @@ test "basic extern unions" { |
| 75 | assert(foo.float == 12.34); | 75 | assert(foo.float == 12.34); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | |||
| 79 | const Letter = enum { | ||
| 80 | A, | ||
| 81 | B, | ||
| 82 | C, | ||
| 83 | }; | ||
| 84 | const Payload = union(Letter) { | ||
| 85 | A: i32, | ||
| 86 | B: f64, | ||
| 87 | C: bool, | ||
| 88 | }; | ||
| 89 | |||
| 90 | test "union with specified enum tag" { | ||
| 91 | doTest(); | ||
| 92 | comptime doTest(); | ||
| 93 | } | ||
| 94 | |||
| 95 | fn doTest() { | ||
| 96 | assert(bar(Payload {.A = 1234}) == -10); | ||
| 97 | } | ||
| 98 | |||
| 99 | fn bar(value: &const Payload) -> i32 { | ||
| 100 | assert(Letter(*value) == Letter.A); | ||
| 101 | return switch (*value) { | ||
| 102 | Payload.A => |x| return x - 1244, | ||
| 103 | Payload.B => |x| if (x == 12.34) i32(20) else 21, | ||
| 104 | Payload.C => |x| if (x) i32(30) else 31, | ||
| 105 | }; | ||
| 106 | } | ||
| 107 | |||
| 108 | const MultipleChoice = union(enum(u32)) { | ||
| 109 | A = 20, | ||
| 110 | B = 40, | ||
| 111 | C = 60, | ||
| 112 | D = 1000, | ||
| 113 | }; | ||
| 114 | test "simple union(enum(u32))" { | ||
| 115 | var x = MultipleChoice.C; | ||
| 116 | assert(x == MultipleChoice.C); | ||
| 117 | assert(u32(@TagType(MultipleChoice)(x)) == 60); | ||
| 118 | } | ||
| 119 | |||
| 120 | const MultipleChoice2 = union(enum(u32)) { | ||
| 121 | Unspecified1: i32, | ||
| 122 | A: f32 = 20, | ||
| 123 | Unspecified2: void, | ||
| 124 | B: bool = 40, | ||
| 125 | Unspecified3: i32, | ||
| 126 | C: i8 = 60, | ||
| 127 | Unspecified4: void, | ||
| 128 | D: void = 1000, | ||
| 129 | Unspecified5: i32, | ||
| 130 | }; | ||
| 131 | |||
| 132 | test "union(enum(u32)) with specified and unspecified tag values" { | ||
| 133 | comptime assert(@TagType(@TagType(MultipleChoice2)) == u32); | ||
| 134 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 {.C = 123}); | ||
| 135 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 { .C = 123} ); | ||
| 136 | } | ||
| 137 | |||
| 138 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) { | ||
| 139 | assert(u32(@TagType(MultipleChoice2)(*x)) == 60); | ||
| 140 | assert(1123 == switch (*x) { | ||
| 141 | MultipleChoice2.A => 1, | ||
| 142 | MultipleChoice2.B => 2, | ||
| 143 | MultipleChoice2.C => |v| i32(1000) + v, | ||
| 144 | MultipleChoice2.D => 4, | ||
| 145 | MultipleChoice2.Unspecified1 => 5, | ||
| 146 | MultipleChoice2.Unspecified2 => 6, | ||
| 147 | MultipleChoice2.Unspecified3 => 7, | ||
| 148 | MultipleChoice2.Unspecified4 => 8, | ||
| 149 | MultipleChoice2.Unspecified5 => 9, | ||
| 150 | }); | ||
| 151 | } | ||
| 152 | |||
| 153 | |||
| 154 | const ExternPtrOrInt = extern union { | ||
| 155 | ptr: &u8, | ||
| 156 | int: u64 | ||
| 157 | }; | ||
| 158 | test "extern union size" { | ||
| 159 | comptime assert(@sizeOf(ExternPtrOrInt) == 8); | ||
| 160 | } | ||
| 161 | |||
| 162 | const PackedPtrOrInt = packed union { | ||
| 163 | ptr: &u8, | ||
| 164 | int: u64 | ||
| 165 | }; | ||
| 166 | test "extern union size" { | ||
| 167 | comptime assert(@sizeOf(PackedPtrOrInt) == 8); | ||
| 168 | } | ||
| 169 | |||
| 170 | const ZeroBits = union { | ||
| 171 | OnlyField: void, | ||
| 172 | }; | ||
| 173 | test "union with only 1 field which is void should be zero bits" { | ||
| 174 | comptime assert(@sizeOf(ZeroBits) == 0); | ||
| 175 | } | ||
| 176 | |||
| 177 | const TheTag = enum {A, B, C}; | ||
| 178 | const TheUnion = union(TheTag) { A: i32, B: i32, C: i32 }; | ||
| 179 | test "union field access gives the enum values" { | ||
| 180 | assert(TheUnion.A == TheTag.A); | ||
| 181 | assert(TheUnion.B == TheTag.B); | ||
| 182 | assert(TheUnion.C == TheTag.C); | ||
| 183 | } | ||
| 184 | |||
| 185 | test "cast union to tag type of union" { | ||
| 186 | testCastUnionToTagType(TheUnion {.B = 1234}); | ||
| 187 | comptime testCastUnionToTagType(TheUnion {.B = 1234}); | ||
| 188 | } | ||
| 189 | |||
| 190 | fn testCastUnionToTagType(x: &const TheUnion) { | ||
| 191 | assert(TheTag(*x) == TheTag.B); | ||
| 192 | } |
test/compile_errors.zig+336-14| ... | @@ -930,8 +930,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -930,8 +930,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 930 | \\fn bad_eql_1(a: []u8, b: []u8) -> bool { | 930 | \\fn bad_eql_1(a: []u8, b: []u8) -> bool { |
| 931 | \\ a == b | 931 | \\ a == b |
| 932 | \\} | 932 | \\} |
| 933 | \\const EnumWithData = enum { | 933 | \\const EnumWithData = union(enum) { |
| 934 | \\ One, | 934 | \\ One: void, |
| 935 | \\ Two: i32, | 935 | \\ Two: i32, |
| 936 | \\}; | 936 | \\}; |
| 937 | \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) -> bool { | 937 | \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) -> bool { |
| ... | @@ -1145,19 +1145,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -1145,19 +1145,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1145 | \\const JasonHM = u8; | 1145 | \\const JasonHM = u8; |
| 1146 | \\const JasonList = &JsonNode; | 1146 | \\const JasonList = &JsonNode; |
| 1147 | \\ | 1147 | \\ |
| 1148 | \\const JsonOA = enum { | 1148 | \\const JsonOA = union(enum) { |
| 1149 | \\ JSONArray: JsonList, | 1149 | \\ JSONArray: JsonList, |
| 1150 | \\ JSONObject: JasonHM, | 1150 | \\ JSONObject: JasonHM, |
| 1151 | \\}; | 1151 | \\}; |
| 1152 | \\ | 1152 | \\ |
| 1153 | \\const JsonType = enum { | 1153 | \\const JsonType = union(enum) { |
| 1154 | \\ JSONNull: void, | 1154 | \\ JSONNull: void, |
| 1155 | \\ JSONInteger: isize, | 1155 | \\ JSONInteger: isize, |
| 1156 | \\ JSONDouble: f64, | 1156 | \\ JSONDouble: f64, |
| 1157 | \\ JSONBool: bool, | 1157 | \\ JSONBool: bool, |
| 1158 | \\ JSONString: []u8, | 1158 | \\ JSONString: []u8, |
| 1159 | \\ JSONArray, | 1159 | \\ JSONArray: void, |
| 1160 | \\ JSONObject, | 1160 | \\ JSONObject: void, |
| 1161 | \\}; | 1161 | \\}; |
| 1162 | \\ | 1162 | \\ |
| 1163 | \\pub const JsonNode = struct { | 1163 | \\pub const JsonNode = struct { |
| ... | @@ -2138,7 +2138,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2138,7 +2138,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2138 | \\ | 2138 | \\ |
| 2139 | \\const MdText = ArrayList(u8); | 2139 | \\const MdText = ArrayList(u8); |
| 2140 | \\ | 2140 | \\ |
| 2141 | \\const MdNode = enum { | 2141 | \\const MdNode = union(enum) { |
| 2142 | \\ Header: struct { | 2142 | \\ Header: struct { |
| 2143 | \\ text: MdText, | 2143 | \\ text: MdText, |
| 2144 | \\ weight: HeaderValue, | 2144 | \\ weight: HeaderValue, |
| ... | @@ -2297,6 +2297,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2297,6 +2297,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2297 | , | 2297 | , |
| 2298 | ".tmp_source.zig:2:21: error: type 'i32' does not support @memberType"); | 2298 | ".tmp_source.zig:2:21: error: type 'i32' does not support @memberType"); |
| 2299 | 2299 | ||
| 2300 | cases.add("@memberType on enum", | ||
| 2301 | \\comptime { | ||
| 2302 | \\ _ = @memberType(Foo, 0); | ||
| 2303 | \\} | ||
| 2304 | \\const Foo = enum {A,}; | ||
| 2305 | , | ||
| 2306 | ".tmp_source.zig:2:21: error: type 'Foo' does not support @memberType"); | ||
| 2307 | |||
| 2300 | cases.add("@memberType struct out of bounds", | 2308 | cases.add("@memberType struct out of bounds", |
| 2301 | \\comptime { | 2309 | \\comptime { |
| 2302 | \\ _ = @memberType(Foo, 0); | 2310 | \\ _ = @memberType(Foo, 0); |
| ... | @@ -2305,13 +2313,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2305,13 +2313,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2305 | , | 2313 | , |
| 2306 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); | 2314 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); |
| 2307 | 2315 | ||
| 2308 | cases.add("@memberType enum out of bounds", | 2316 | cases.add("@memberType union out of bounds", |
| 2309 | \\comptime { | 2317 | \\comptime { |
| 2310 | \\ _ = @memberType(Foo, 0); | 2318 | \\ _ = @memberType(Foo, 1); |
| 2311 | \\} | 2319 | \\} |
| 2312 | \\const Foo = enum {}; | 2320 | \\const Foo = union {A: void,}; |
| 2313 | , | 2321 | , |
| 2314 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); | 2322 | ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); |
| 2315 | 2323 | ||
| 2316 | cases.add("@memberName on unsupported type", | 2324 | cases.add("@memberName on unsupported type", |
| 2317 | \\comptime { | 2325 | \\comptime { |
| ... | @@ -2330,11 +2338,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2330,11 +2338,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2330 | 2338 | ||
| 2331 | cases.add("@memberName enum out of bounds", | 2339 | cases.add("@memberName enum out of bounds", |
| 2332 | \\comptime { | 2340 | \\comptime { |
| 2333 | \\ _ = @memberName(Foo, 0); | 2341 | \\ _ = @memberName(Foo, 1); |
| 2334 | \\} | 2342 | \\} |
| 2335 | \\const Foo = enum {}; | 2343 | \\const Foo = enum {A,}; |
| 2336 | , | 2344 | , |
| 2337 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); | 2345 | ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); |
| 2346 | |||
| 2347 | cases.add("@memberName union out of bounds", | ||
| 2348 | \\comptime { | ||
| 2349 | \\ _ = @memberName(Foo, 1); | ||
| 2350 | \\} | ||
| 2351 | \\const Foo = union {A:i32,}; | ||
| 2352 | , | ||
| 2353 | ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); | ||
| 2338 | 2354 | ||
| 2339 | cases.add("calling var args extern function, passing array instead of pointer", | 2355 | cases.add("calling var args extern function, passing array instead of pointer", |
| 2340 | \\export fn entry() { | 2356 | \\export fn entry() { |
| ... | @@ -2362,4 +2378,310 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2362,4 +2378,310 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2362 | ".tmp_source.zig:4:25: error: aoeu", | 2378 | ".tmp_source.zig:4:25: error: aoeu", |
| 2363 | ".tmp_source.zig:1:36: note: called from here", | 2379 | ".tmp_source.zig:1:36: note: called from here", |
| 2364 | ".tmp_source.zig:12:20: note: referenced here"); | 2380 | ".tmp_source.zig:12:20: note: referenced here"); |
| 2381 | |||
| 2382 | cases.add("specify enum tag type that is too small", | ||
| 2383 | \\const Small = enum (u2) { | ||
| 2384 | \\ One, | ||
| 2385 | \\ Two, | ||
| 2386 | \\ Three, | ||
| 2387 | \\ Four, | ||
| 2388 | \\ Five, | ||
| 2389 | \\}; | ||
| 2390 | \\ | ||
| 2391 | \\export fn entry() { | ||
| 2392 | \\ var x = Small.One; | ||
| 2393 | \\} | ||
| 2394 | , | ||
| 2395 | ".tmp_source.zig:1:20: error: 'u2' too small to hold all bits; must be at least 'u3'"); | ||
| 2396 | |||
| 2397 | cases.add("specify non-integer enum tag type", | ||
| 2398 | \\const Small = enum (f32) { | ||
| 2399 | \\ One, | ||
| 2400 | \\ Two, | ||
| 2401 | \\ Three, | ||
| 2402 | \\}; | ||
| 2403 | \\ | ||
| 2404 | \\export fn entry() { | ||
| 2405 | \\ var x = Small.One; | ||
| 2406 | \\} | ||
| 2407 | , | ||
| 2408 | ".tmp_source.zig:1:20: error: expected integer, found 'f32'"); | ||
| 2409 | |||
| 2410 | cases.add("implicitly casting enum to tag type", | ||
| 2411 | \\const Small = enum(u2) { | ||
| 2412 | \\ One, | ||
| 2413 | \\ Two, | ||
| 2414 | \\ Three, | ||
| 2415 | \\ Four, | ||
| 2416 | \\}; | ||
| 2417 | \\ | ||
| 2418 | \\export fn entry() { | ||
| 2419 | \\ var x: u2 = Small.Two; | ||
| 2420 | \\} | ||
| 2421 | , | ||
| 2422 | ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'"); | ||
| 2423 | |||
| 2424 | cases.add("explicitly casting enum to non tag type", | ||
| 2425 | \\const Small = enum(u2) { | ||
| 2426 | \\ One, | ||
| 2427 | \\ Two, | ||
| 2428 | \\ Three, | ||
| 2429 | \\ Four, | ||
| 2430 | \\}; | ||
| 2431 | \\ | ||
| 2432 | \\export fn entry() { | ||
| 2433 | \\ var x = u3(Small.Two); | ||
| 2434 | \\} | ||
| 2435 | , | ||
| 2436 | ".tmp_source.zig:9:15: error: enum to integer cast to 'u3' instead of its tag type, 'u2'"); | ||
| 2437 | |||
| 2438 | cases.add("explicitly casting non tag type to enum", | ||
| 2439 | \\const Small = enum(u2) { | ||
| 2440 | \\ One, | ||
| 2441 | \\ Two, | ||
| 2442 | \\ Three, | ||
| 2443 | \\ Four, | ||
| 2444 | \\}; | ||
| 2445 | \\ | ||
| 2446 | \\export fn entry() { | ||
| 2447 | \\ var y = u3(3); | ||
| 2448 | \\ var x = Small(y); | ||
| 2449 | \\} | ||
| 2450 | , | ||
| 2451 | ".tmp_source.zig:10:18: error: integer to enum cast from 'u3' instead of its tag type, 'u2'"); | ||
| 2452 | |||
| 2453 | cases.add("non unsigned integer enum tag type", | ||
| 2454 | \\const Small = enum(i2) { | ||
| 2455 | \\ One, | ||
| 2456 | \\ Two, | ||
| 2457 | \\ Three, | ||
| 2458 | \\ Four, | ||
| 2459 | \\}; | ||
| 2460 | \\ | ||
| 2461 | \\export fn entry() { | ||
| 2462 | \\ var y = Small.Two; | ||
| 2463 | \\} | ||
| 2464 | , | ||
| 2465 | ".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'"); | ||
| 2466 | |||
| 2467 | cases.add("struct fields with value assignments", | ||
| 2468 | \\const MultipleChoice = struct { | ||
| 2469 | \\ A: i32 = 20, | ||
| 2470 | \\}; | ||
| 2471 | \\export fn entry() { | ||
| 2472 | \\ var x: MultipleChoice = undefined; | ||
| 2473 | \\} | ||
| 2474 | , | ||
| 2475 | ".tmp_source.zig:2:14: error: enums, not structs, support field assignment"); | ||
| 2476 | |||
| 2477 | cases.add("union fields with value assignments", | ||
| 2478 | \\const MultipleChoice = union { | ||
| 2479 | \\ A: i32 = 20, | ||
| 2480 | \\}; | ||
| 2481 | \\export fn entry() { | ||
| 2482 | \\ var x: MultipleChoice = undefined; | ||
| 2483 | \\} | ||
| 2484 | , | ||
| 2485 | ".tmp_source.zig:2:14: error: non-enum union field assignment", | ||
| 2486 | ".tmp_source.zig:1:24: note: consider 'union(enum)' here"); | ||
| 2487 | |||
| 2488 | cases.add("enum with 0 fields", | ||
| 2489 | \\const Foo = enum {}; | ||
| 2490 | \\export fn entry() -> usize { | ||
| 2491 | \\ return @sizeOf(Foo); | ||
| 2492 | \\} | ||
| 2493 | , | ||
| 2494 | ".tmp_source.zig:1:13: error: enums must have 1 or more fields"); | ||
| 2495 | |||
| 2496 | cases.add("union with 0 fields", | ||
| 2497 | \\const Foo = union {}; | ||
| 2498 | \\export fn entry() -> usize { | ||
| 2499 | \\ return @sizeOf(Foo); | ||
| 2500 | \\} | ||
| 2501 | , | ||
| 2502 | ".tmp_source.zig:1:13: error: unions must have 1 or more fields"); | ||
| 2503 | |||
| 2504 | cases.add("enum value already taken", | ||
| 2505 | \\const MultipleChoice = enum(u32) { | ||
| 2506 | \\ A = 20, | ||
| 2507 | \\ B = 40, | ||
| 2508 | \\ C = 60, | ||
| 2509 | \\ D = 1000, | ||
| 2510 | \\ E = 60, | ||
| 2511 | \\}; | ||
| 2512 | \\export fn entry() { | ||
| 2513 | \\ var x = MultipleChoice.C; | ||
| 2514 | \\} | ||
| 2515 | , | ||
| 2516 | ".tmp_source.zig:6:9: error: enum tag value 60 already taken", | ||
| 2517 | ".tmp_source.zig:4:9: note: other occurrence here"); | ||
| 2518 | |||
| 2519 | cases.add("union with specified enum omits field", | ||
| 2520 | \\const Letter = enum { | ||
| 2521 | \\ A, | ||
| 2522 | \\ B, | ||
| 2523 | \\ C, | ||
| 2524 | \\}; | ||
| 2525 | \\const Payload = union(Letter) { | ||
| 2526 | \\ A: i32, | ||
| 2527 | \\ B: f64, | ||
| 2528 | \\}; | ||
| 2529 | \\export fn entry() -> usize { | ||
| 2530 | \\ return @sizeOf(Payload); | ||
| 2531 | \\} | ||
| 2532 | , | ||
| 2533 | ".tmp_source.zig:6:17: error: enum field missing: 'C'", | ||
| 2534 | ".tmp_source.zig:4:5: note: declared here"); | ||
| 2535 | |||
| 2536 | cases.add("@TagType when union has no attached enum", | ||
| 2537 | \\const Foo = union { | ||
| 2538 | \\ A: i32, | ||
| 2539 | \\}; | ||
| 2540 | \\export fn entry() { | ||
| 2541 | \\ const x = @TagType(Foo); | ||
| 2542 | \\} | ||
| 2543 | , | ||
| 2544 | ".tmp_source.zig:5:24: error: union 'Foo' has no tag", | ||
| 2545 | ".tmp_source.zig:1:13: note: consider 'union(enum)' here"); | ||
| 2546 | |||
| 2547 | cases.add("non-integer tag type to automatic union enum", | ||
| 2548 | \\const Foo = union(enum(f32)) { | ||
| 2549 | \\ A: i32, | ||
| 2550 | \\}; | ||
| 2551 | \\export fn entry() { | ||
| 2552 | \\ const x = @TagType(Foo); | ||
| 2553 | \\} | ||
| 2554 | , | ||
| 2555 | ".tmp_source.zig:1:23: error: expected integer tag type, found 'f32'"); | ||
| 2556 | |||
| 2557 | cases.add("non-enum tag type passed to union", | ||
| 2558 | \\const Foo = union(u32) { | ||
| 2559 | \\ A: i32, | ||
| 2560 | \\}; | ||
| 2561 | \\export fn entry() { | ||
| 2562 | \\ const x = @TagType(Foo); | ||
| 2563 | \\} | ||
| 2564 | , | ||
| 2565 | ".tmp_source.zig:1:18: error: expected enum tag type, found 'u32'"); | ||
| 2566 | |||
| 2567 | cases.add("union auto-enum value already taken", | ||
| 2568 | \\const MultipleChoice = union(enum(u32)) { | ||
| 2569 | \\ A = 20, | ||
| 2570 | \\ B = 40, | ||
| 2571 | \\ C = 60, | ||
| 2572 | \\ D = 1000, | ||
| 2573 | \\ E = 60, | ||
| 2574 | \\}; | ||
| 2575 | \\export fn entry() { | ||
| 2576 | \\ var x = MultipleChoice { .C = {} }; | ||
| 2577 | \\} | ||
| 2578 | , | ||
| 2579 | ".tmp_source.zig:6:9: error: enum tag value 60 already taken", | ||
| 2580 | ".tmp_source.zig:4:9: note: other occurrence here"); | ||
| 2581 | |||
| 2582 | cases.add("union enum field does not match enum", | ||
| 2583 | \\const Letter = enum { | ||
| 2584 | \\ A, | ||
| 2585 | \\ B, | ||
| 2586 | \\ C, | ||
| 2587 | \\}; | ||
| 2588 | \\const Payload = union(Letter) { | ||
| 2589 | \\ A: i32, | ||
| 2590 | \\ B: f64, | ||
| 2591 | \\ C: bool, | ||
| 2592 | \\ D: bool, | ||
| 2593 | \\}; | ||
| 2594 | \\export fn entry() { | ||
| 2595 | \\ var a = Payload {.A = 1234}; | ||
| 2596 | \\} | ||
| 2597 | , | ||
| 2598 | ".tmp_source.zig:10:5: error: enum field not found: 'D'", | ||
| 2599 | ".tmp_source.zig:1:16: note: enum declared here"); | ||
| 2600 | |||
| 2601 | cases.add("field type supplied in an enum", | ||
| 2602 | \\const Letter = enum { | ||
| 2603 | \\ A: void, | ||
| 2604 | \\ B, | ||
| 2605 | \\ C, | ||
| 2606 | \\}; | ||
| 2607 | \\export fn entry() { | ||
| 2608 | \\ var b = Letter.B; | ||
| 2609 | \\} | ||
| 2610 | , | ||
| 2611 | ".tmp_source.zig:2:8: error: structs and unions, not enums, support field types", | ||
| 2612 | ".tmp_source.zig:1:16: note: consider 'union(enum)' here"); | ||
| 2613 | |||
| 2614 | cases.add("struct field missing type", | ||
| 2615 | \\const Letter = struct { | ||
| 2616 | \\ A, | ||
| 2617 | \\}; | ||
| 2618 | \\export fn entry() { | ||
| 2619 | \\ var a = Letter { .A = {} }; | ||
| 2620 | \\} | ||
| 2621 | , | ||
| 2622 | ".tmp_source.zig:2:5: error: struct field missing type"); | ||
| 2623 | |||
| 2624 | cases.add("extern union field missing type", | ||
| 2625 | \\const Letter = extern union { | ||
| 2626 | \\ A, | ||
| 2627 | \\}; | ||
| 2628 | \\export fn entry() { | ||
| 2629 | \\ var a = Letter { .A = {} }; | ||
| 2630 | \\} | ||
| 2631 | , | ||
| 2632 | ".tmp_source.zig:2:5: error: union field missing type"); | ||
| 2633 | |||
| 2634 | cases.add("extern union given enum tag type", | ||
| 2635 | \\const Letter = enum { | ||
| 2636 | \\ A, | ||
| 2637 | \\ B, | ||
| 2638 | \\ C, | ||
| 2639 | \\}; | ||
| 2640 | \\const Payload = extern union(Letter) { | ||
| 2641 | \\ A: i32, | ||
| 2642 | \\ B: f64, | ||
| 2643 | \\ C: bool, | ||
| 2644 | \\}; | ||
| 2645 | \\export fn entry() { | ||
| 2646 | \\ var a = Payload { .A = { 1234 } }; | ||
| 2647 | \\} | ||
| 2648 | , | ||
| 2649 | ".tmp_source.zig:6:29: error: extern union does not support enum tag type"); | ||
| 2650 | |||
| 2651 | cases.add("packed union given enum tag type", | ||
| 2652 | \\const Letter = enum { | ||
| 2653 | \\ A, | ||
| 2654 | \\ B, | ||
| 2655 | \\ C, | ||
| 2656 | \\}; | ||
| 2657 | \\const Payload = packed union(Letter) { | ||
| 2658 | \\ A: i32, | ||
| 2659 | \\ B: f64, | ||
| 2660 | \\ C: bool, | ||
| 2661 | \\}; | ||
| 2662 | \\export fn entry() { | ||
| 2663 | \\ var a = Payload { .A = { 1234 } }; | ||
| 2664 | \\} | ||
| 2665 | , | ||
| 2666 | ".tmp_source.zig:6:29: error: packed union does not support enum tag type"); | ||
| 2667 | |||
| 2668 | cases.add("switch on union with no attached enum", | ||
| 2669 | \\const Payload = union { | ||
| 2670 | \\ A: i32, | ||
| 2671 | \\ B: f64, | ||
| 2672 | \\ C: bool, | ||
| 2673 | \\}; | ||
| 2674 | \\export fn entry() { | ||
| 2675 | \\ const a = Payload { .A = { 1234 } }; | ||
| 2676 | \\ foo(a); | ||
| 2677 | \\} | ||
| 2678 | \\fn foo(a: &const Payload) { | ||
| 2679 | \\ switch (*a) { | ||
| 2680 | \\ Payload.A => {}, | ||
| 2681 | \\ else => unreachable, | ||
| 2682 | \\ } | ||
| 2683 | \\} | ||
| 2684 | , | ||
| 2685 | ".tmp_source.zig:11:13: error: switch on union which has no attached enum", | ||
| 2686 | ".tmp_source.zig:1:17: note: consider 'union(enum)' here"); | ||
| 2365 | } | 2687 | } |
test/tests.zig+5-5| ... | @@ -150,8 +150,8 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons | ... | @@ -150,8 +150,8 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons |
| 150 | continue; | 150 | continue; |
| 151 | } | 151 | } |
| 152 | const these_tests = b.addTest(root_src); | 152 | const these_tests = b.addTest(root_src); |
| 153 | these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @enumTagName(test_target.os), | 153 | these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), |
| 154 | @enumTagName(test_target.arch), @enumTagName(mode), if (link_libc) "c" else "bare")); | 154 | @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare")); |
| 155 | these_tests.setFilter(test_filter); | 155 | these_tests.setFilter(test_filter); |
| 156 | these_tests.setBuildMode(mode); | 156 | these_tests.setBuildMode(mode); |
| 157 | if (!is_native) { | 157 | if (!is_native) { |
| ... | @@ -428,7 +428,7 @@ pub const CompareOutputContext = struct { | ... | @@ -428,7 +428,7 @@ pub const CompareOutputContext = struct { |
| 428 | Special.None => { | 428 | Special.None => { |
| 429 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { | 429 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { |
| 430 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})", | 430 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})", |
| 431 | "compare-output", case.name, @enumTagName(mode)); | 431 | "compare-output", case.name, @tagName(mode)); |
| 432 | if (self.test_filter) |filter| { | 432 | if (self.test_filter) |filter| { |
| 433 | if (mem.indexOf(u8, annotated_case_name, filter) == null) | 433 | if (mem.indexOf(u8, annotated_case_name, filter) == null) |
| 434 | continue; | 434 | continue; |
| ... | @@ -682,7 +682,7 @@ pub const CompileErrorContext = struct { | ... | @@ -682,7 +682,7 @@ pub const CompileErrorContext = struct { |
| 682 | 682 | ||
| 683 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { | 683 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { |
| 684 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})", | 684 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})", |
| 685 | case.name, @enumTagName(mode)); | 685 | case.name, @tagName(mode)); |
| 686 | if (self.test_filter) |filter| { | 686 | if (self.test_filter) |filter| { |
| 687 | if (mem.indexOf(u8, annotated_case_name, filter) == null) | 687 | if (mem.indexOf(u8, annotated_case_name, filter) == null) |
| 688 | continue; | 688 | continue; |
| ... | @@ -750,7 +750,7 @@ pub const BuildExamplesContext = struct { | ... | @@ -750,7 +750,7 @@ pub const BuildExamplesContext = struct { |
| 750 | 750 | ||
| 751 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { | 751 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { |
| 752 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})", | 752 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})", |
| 753 | root_src, @enumTagName(mode)); | 753 | root_src, @tagName(mode)); |
| 754 | if (self.test_filter) |filter| { | 754 | if (self.test_filter) |filter| { |
| 755 | if (mem.indexOf(u8, annotated_case_name, filter) == null) | 755 | if (mem.indexOf(u8, annotated_case_name, filter) == null) |
| 756 | continue; | 756 | continue; |
test/translate_c.zig+10| ... | @@ -1178,4 +1178,14 @@ pub fn addCases(cases: &tests.TranslateCContext) { | ... | @@ -1178,4 +1178,14 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 1178 | , | 1178 | , |
| 1179 | \\pub var v0: ?&const u8 = c"0.0.0"; | 1179 | \\pub var v0: ?&const u8 = c"0.0.0"; |
| 1180 | ); | 1180 | ); |
| 1181 | |||
| 1182 | cases.add("static incomplete array inside function", | ||
| 1183 | \\void foo(void) { | ||
| 1184 | \\ static const char v2[] = "2.2.2"; | ||
| 1185 | \\} | ||
| 1186 | , | ||
| 1187 | \\pub fn foo() { | ||
| 1188 | \\ const v2: &const u8 = c"2.2.2"; | ||
| 1189 | \\} | ||
| 1190 | ); | ||
| 1181 | } | 1191 | } |