authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-04 15:28:17-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-04 15:28:17-05:00
log42004f9013ba2d06b457f858e0e269ef4ad23554
treeee99dd89c9ce7e7c30a76e7bf0d9f7da7c0c64c7
parentafe3aae582d5051406832e32fc01374f2a0029b7
parenta966275e509670e750ef54a37f7202078aa4cf07

Merge branch 'master' into llvm6


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)
47option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead of the embedded LLD" OFF)47option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead of the embedded LLD" OFF)
4848
49find_package(llvm)49find_package(llvm)
50include_directories(${LLVM_INCLUDE_DIRS})
51
52find_package(clang)50find_package(clang)
53include_directories(${CLANG_INCLUDE_DIRS})
5451
55if(ZIG_FORCE_EXTERNAL_LLD)52if(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})
58else()57else()
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_SOURCES64 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}
45454545
4546/* Bit Test */
4547
4548static __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
4556static __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
4563static __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
4571static __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
45774546
4578/* SIMD load ops */4547/* SIMD load ops */
45794548
...@@ -4844,293 +4813,105 @@ _mm512_knot(__mmask16 __M)...@@ -4844,293 +4813,105 @@ _mm512_knot(__mmask16 __M)
48444813
4845/* Integer compare */4814/* Integer compare */
48464815
4847static __inline__ __mmask16 __DEFAULT_FN_ATTRS4816#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) \
48524821 _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_GE)
4853static __inline__ __mmask16 __DEFAULT_FN_ATTRS4822#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) \
48584827 _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GT)
4859static __inline__ __mmask16 __DEFAULT_FN_ATTRS4828#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) \
48644833 _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_LT)
4865static __inline__ __mmask16 __DEFAULT_FN_ATTRS4834#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) \
48704839 _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_NE)
4871static __inline__ __mmask8 __DEFAULT_FN_ATTRS4840
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)
48764845#define _mm512_cmpge_epu32_mask(A, B) \
4877static __inline__ __mmask8 __DEFAULT_FN_ATTRS4846 _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)
48824851#define _mm512_mask_cmpgt_epu32_mask(k, A, B) \
4883static __inline__ __mmask8 __DEFAULT_FN_ATTRS4852 _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)
48884857#define _mm512_cmplt_epu32_mask(A, B) \
4889static __inline__ __mmask8 __DEFAULT_FN_ATTRS4858 _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)
48944863#define _mm512_mask_cmpneq_epu32_mask(k, A, B) \
4895static __inline__ __mmask16 __DEFAULT_FN_ATTRS4864 _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) \
49004869 _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_EQ)
4901static __inline__ __mmask16 __DEFAULT_FN_ATTRS4870#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) \
49064875 _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_GT)
4907static __inline__ __mmask16 __DEFAULT_FN_ATTRS4876#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) \
49124881 _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LE)
4913static __inline__ __mmask16 __DEFAULT_FN_ATTRS4882#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) \
49184887 _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_NE)
4919static __inline__ __mmask8 __DEFAULT_FN_ATTRS4888#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)
49244893#define _mm512_mask_cmpeq_epu64_mask(k, A, B) \
4925static __inline__ __mmask8 __DEFAULT_FN_ATTRS4894 _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)
49304899#define _mm512_cmpgt_epu64_mask(A, B) \
4931static __inline__ __mmask8 __DEFAULT_FN_ATTRS4900 _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)
49364905#define _mm512_mask_cmple_epu64_mask(k, A, B) \
4937static __inline__ __mmask8 __DEFAULT_FN_ATTRS4906 _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)
49424911#define _mm512_cmpneq_epu64_mask(A, B) \
4943static __inline__ __mmask16 __DEFAULT_FN_ATTRS4912 _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
4949static __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
4955static __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
4961static __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
4967static __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
4973static __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
4979static __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
4985static __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
4991static __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
4997static __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
5003static __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
5009static __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
5015static __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
5021static __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
5027static __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
5033static __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
5039static __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
5045static __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
5051static __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
5057static __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
5063static __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
5069static __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
5075static __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
5081static __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
5087static __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
5093static __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
5099static __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
5105static __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
5111static __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
5117static __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
5123static __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
5129static __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}
51344915
5135static __inline__ __m512i __DEFAULT_FN_ATTRS4916static __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}
67996580
6800static __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
6808static __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
6815static __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
6823static __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}
68296581
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}
71956947
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)); })
72016967
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)); })
72076972
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)); })
72136977
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)); })
72196989
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)); })
72256994
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)); })
72316999
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)); })
72377011
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)); })
72437016
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)); })
72497021
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)); })
72557033
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)); })
72617038
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)); })
72677043
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); })
91688944
8945/* Bit Test */
8946
8947static __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
8954static __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
8961static __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
8968static __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
8975static __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
8982static __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
8989static __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
8996static __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
9169static __inline__ __m512 __DEFAULT_FN_ATTRS9003static __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.01#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 53#define LLD_VERSION_MAJOR 5
4#define LLD_VERSION_MINOR 04#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;
52StringSaver Saver{BAlloc};52StringSaver Saver{BAlloc};
53std::vector<SpecificAllocBase *> SpecificAllocBase::Instances;53std::vector<SpecificAllocBase *> SpecificAllocBase::Instances;
5454
55bool link(ArrayRef<const char *> Args, raw_ostream &Diag) {55bool 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 }
11281134
1129 // Do LTO by compiling bitcode input files to a set of native COFF files then1135 // 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 {
32uint64_t ErrorCount;32uint64_t ErrorCount;
33raw_ostream *ErrorOS;33raw_ostream *ErrorOS;
3434
35static LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) {35LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) {
36 // Dealloc/destroy ManagedStatic variables before calling36 // Dealloc/destroy ManagedStatic variables before calling
37 // _exit(). In a non-LTO build, this is a nop. In an LTO37 // _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 }
8384
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);
27LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix);27LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix);
28LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix);28LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix);
2929
30LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
31
30template <class T> T check(ErrorOr<T> V, const Twine &Prefix) {32template <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]);
428428
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}];
431431
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>
522static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {523static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {
523 memcpy(Buf, D.data(), D.size());524 memcpy(Buf, D.data(), D.size());
524525
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}
529535
530template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() {536template <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;
104104
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};
108109
109class GotSection : public SyntheticSection {110class GotSection : public SyntheticSection {
deps/lld/include/lld/Driver/Driver.h+1-1
...@@ -15,7 +15,7 @@...@@ -15,7 +15,7 @@
1515
16namespace lld {16namespace lld {
17namespace coff {17namespace coff {
18bool link(llvm::ArrayRef<const char *> Args,18bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,
19 llvm::raw_ostream &Diag = llvm::errs());19 llvm::raw_ostream &Diag = llvm::errs());
20}20}
2121
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}
626625
627void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,626void 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
9bar:
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};
20972098
2098// Enums are sum types, and can hold more complex data of different types.
2099const 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.
2105const c = ComplexType.Ok { 0 };2100const c = Type.Ok;
21062101
2107// The ordinal value of a simple enum with no data members can be2102// 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.2104const Value = enum(u2) {
2110const 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.
2115test "enum ordinal value" {2112test "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.
2119const Value2 = enum(u32) {
2120 Hundred = 100,
2121 Thousand = 1000,
2122 Million = 1000000,
2123};
2124test "set enum ordinal value" {
2125 assert(u32(Value2.Hundred) == 100);
2126 assert(u32(Value2.Thousand) == 1000);
2127 assert(u32(Value2.Million) == 1000000);
2119}2128}
21202129
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 namespaced2131// 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.
2124const Suit = enum {2133const Suit = enum {
...@@ -2127,26 +2136,120 @@ const Suit = enum {...@@ -2127,26 +2136,120 @@ const Suit = enum {
2127 Diamonds,2136 Diamonds,
2128 Hearts,2137 Hearts,
21292138
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};
2134test "enum method" {2143test "enum method" {
2135 const p = Suit.Spades;2144 const p = Suit.Spades;
2136 assert(p.ordinal() == 1);2145 assert(!p.isClubs());
2137}2146}
21382147
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.
2143const Foo = enum {2149const Foo = enum {
2150 String,
2151 Number,
2152 None,
2153};
2154test "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.
2165const Small = enum {
2166 One,
2167 Two,
2168 Three,
2169 Four,
2170};
2171test "@TagType" {
2172 assert(@TagType(Small) == u2);
2173}
2174
2175// @memberCount tells how many fields an enum has:
2176test "@memberCount" {
2177 assert(@memberCount(Small) == 4);
2178}
2179
2180// @memberName tells the name of a field in an enum:
2181test "@memberName" {
2182 assert(mem.eql(u8, @memberName(Small, 1), "Two"));
2183}
2184
2185// @tagName gives a []const u8 representation of an enum value:
2186test "@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
2192Test 1/8 enum ordinal value...OK
2193Test 2/8 set enum ordinal value...OK
2194Test 3/8 enum method...OK
2195Test 4/8 enum variant switch...OK
2196Test 5/8 @TagType...OK
2197Test 6/8 @memberCount...OK
2198Test 7/8 @memberName...OK
2199Test 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;
2208const mem = @import("std").mem;
2209
2210// A union has only 1 active field at a time.
2211const Payload = union {
2212 Int: i64,
2213 Float: f64,
2214 Bool: bool,
2215};
2216test "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:
2226const ComplexTypeTag = enum { Ok, NotOk };
2227const ComplexType = union(ComplexTypeTag) {
2228 Ok: u8,
2229 NotOk: void,
2230};
2231
2232// Declare a specific instance of the union variant.
2233test "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.
2239test "@TagType" {
2240 assert(@TagType(ComplexType) == ComplexTypeTag);
2241}
2242
2243// Unions can be made to infer the enum tag type.
2244const 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};
2148test "enum variant switch" {2251test "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 reference2254 // 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" {
21552258
2156 // Capture by value2259 // 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 },
21602264
...@@ -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}
21662271
2167// The @enumTagName and @memberCount builtin functions can be used to2272// TODO union methods
2168// the string representation and number of members respectively.2273
2169const BuiltinType = enum {2274
2170 A: f32,2275const Small = union {
2171 B: u32,2276 A: i32,
2172 C,2277 B: bool,
2278 C: u8,
2173};2279};
21742280
2175test "enum builtins" {2281// @memberCount tells how many fields a union has:
2176 assert(mem.eql(u8, @enumTagName(BuiltinType.A { 0 }), "A"));2282test "@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:
2287test "@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.
2293const Small2 = union(enum) {
2294 A: i32,
2295 B: bool,
2296 C: u8,
2297};
2298test "@tagName" {
2299 assert(mem.eql(u8, @tagName(Small2.C), "C"));
2179}</code></pre>2300}</code></pre>
2180 <pre><code class="sh">$ zig test enum.zig2301 <pre><code class="sh">$ zig test union.zig
2181Test 1/4 enum ordinal value...OK2302Test 1/7 simple union...OK
2182Test 2/4 enum method...OK2303Test 2/7 declare union value...OK
2183Test 3/4 enum variant switch...OK2304Test 3/7 @TagType...OK
2184Test 4/4 enum builtins...OK</code></pre>2305Test 4/7 union variant switch...OK
2185 <p>2306Test 5/7 @memberCount...OK
2186 Enums are generated as a struct with a tag field and union field. Zig2307Test 6/7 @memberName...OK
2308Test 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;
2198const builtin = @import("builtin");2315const 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
57035825
5704ContainerMember = (ContainerField | FnDef | GlobalVarDecl)5826ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
57055827
5706ContainerField = Symbol option(":" Expression) ","5828ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","
57075829
5708UseDecl = "use" Expression ";"5830UseDecl = "use" Expression ";"
57095831
...@@ -5837,7 +5959,9 @@ GroupedExpression = "(" Expression ")"...@@ -5837,7 +5959,9 @@ GroupedExpression = "(" Expression ")"
58375959
5838KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"5960KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"
58395961
5840ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"</code></pre>5962ContainerDecl = 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 @@
1const builtin = @import("builtin");
1const std = @import("std");2const std = @import("std");
2const io = std.io;3const io = std.io;
3const fmt = std.fmt;4const fmt = std.fmt;
...@@ -15,7 +16,7 @@ pub fn main() -> %void {...@@ -15,7 +16,7 @@ pub fn main() -> %void {
1516
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);
2021
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};
9999
100struct ConstEnumValue {
101 uint64_t tag;
102 ConstExprValue *payload;
103};
104
105struct ConstStructValue {100struct ConstStructValue {
106 ConstExprValue *fields;101 ConstExprValue *fields;
107 ConstParent parent;102 ConstParent parent;
108};103};
109104
110struct ConstUnionValue {105struct 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 {
345340
346struct TypeEnumField {341struct 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};
352346
353struct TypeUnionField {347struct 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};
359353
...@@ -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};
778773
779struct AstNodeStructField {774struct 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};
784780
785struct AstNodeStringLiteral {781struct 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 invalid1009 bool is_invalid; // true if any fields are invalid
1016 TypeTableEntry *tag_type;1010 TypeTableEntry *tag_int_type;
1017 LLVMTypeRef union_type_ref;
10181011
1019 ScopeDecls *decls_scope;1012 ScopeDecls *decls_scope;
10201013
...@@ -1026,18 +1019,7 @@ struct TypeTableEntryEnum {...@@ -1026,18 +1019,7 @@ struct TypeTableEntryEnum {
10261019
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};
10371022
1038struct 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 invalid1036 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;
10571039
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};
20902070
2091struct IrInstructionEnumFieldPtr {
2092 IrInstruction base;
2093
2094 IrInstruction *enum_ptr;
2095 TypeEnumField *field;
2096 bool is_const;
2097};
2098
2099struct IrInstructionUnionFieldPtr {2071struct IrInstructionUnionFieldPtr {
2100 IrInstruction base;2072 IrInstruction base;
21012073
...@@ -2299,7 +2271,7 @@ struct IrInstructionClz {...@@ -2299,7 +2271,7 @@ struct IrInstructionClz {
2299 IrInstruction *value;2271 IrInstruction *value;
2300};2272};
23012273
2302struct IrInstructionEnumTag {2274struct IrInstructionUnionTag {
2303 IrInstruction base;2275 IrInstruction base;
23042276
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};
25712543
2572struct IrInstructionInitEnum {
2573 IrInstruction base;
2574
2575 TypeTableEntry *enum_type;
2576 TypeEnumField *field;
2577 IrInstruction *init_value;
2578 LLVMValueRef tmp_ptr;
2579};
2580
2581struct IrInstructionPtrCast {2544struct IrInstructionPtrCast {
2582 IrInstruction base;2545 IrInstruction base;
25832546
...@@ -2689,7 +2652,13 @@ struct IrInstructionPanic {...@@ -2689,7 +2652,13 @@ struct IrInstructionPanic {
2689 IrInstruction *msg;2652 IrInstruction *msg;
2690};2653};
26912654
2692struct IrInstructionEnumTagName {2655struct IrInstructionTagName {
2656 IrInstruction base;
2657
2658 IrInstruction *target;
2659};
2660
2661struct IrInstructionTagType {
2693 IrInstruction base;2662 IrInstruction base;
26942663
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 }
12451241
...@@ -1263,22 +1259,6 @@ bool type_is_invalid(TypeTableEntry *type_entry) {...@@ -1263,22 +1259,6 @@ bool type_is_invalid(TypeTableEntry *type_entry) {
1263}1259}
12641260
12651261
1266TypeTableEntry *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
1282static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {1262static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1283 assert(enum_type->id == TypeTableEntryIdEnum);1263 assert(enum_type->id == TypeTableEntryIdEnum);
12841264
...@@ -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);
13101290
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);
13211293
...@@ -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;
13241296
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);
13561299
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 }
13631305
1364 // unset temporary flag1306 // 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;
13691309
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 }
13921332
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;
14901334
1491 // create debug type for tag1335 // 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, "");
15011345
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}
15061349
1507static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {1350static 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;
16591502
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;
18721715
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);
18781718
1879 // set temporary flag1719 // set temporary flag
1880 union_type->data.unionation.embedded_in_current = true;1720 union_type->data.unionation.embedded_in_current = true;
18811721
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;
18861727
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;
18951736
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);
19001739
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);
19031742
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 }
19201759
1760
1921 // unset temporary flag1761 // 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 }
19491789
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;
19541791
1792 TypeTableEntry *tag_type = union_type->data.unionation.tag_type;
1793 if (tag_type == nullptr) {
1794 assert(most_aligned_union_member != nullptr);
19551795
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);
20031850
2004 // create llvm type for root struct1851 // 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);
20091854
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 }
20171862
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);
20221867
20231868
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 union1869 // 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);
20461880
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);
20611899
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) {
20961934
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);
21011950
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;
21051952
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;
21141955
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;
21201981
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;
21231987
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 }
21261994
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 }
21322023
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;
21372031
2138 // also compute abi_alignment2032 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}
21452056
2146static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {2057static 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;
21912109
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;
22272150
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 }
22322170
...@@ -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) {
22382176
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);
22432191
...@@ -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) {
22452193
2246 Scope *scope = &union_type->data.unionation.decls_scope->base;2194 Scope *scope = &union_type->data.unionation.decls_scope->base;
22472195
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;
22562290
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);
22622349
2263 if (!type_has_bits(field_type))2350 if (!type_has_bits(field_type))
2264 continue;2351 continue;
22652352
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;
22682355
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 }
22742364
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 }
22762446
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}
22872452
2288static void get_fully_qualified_decl_name_internal(Buf *buf, Scope *scope, uint8_t sep) {2453static 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}
31673331
3332TypeUnionField *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
3345TypeEnumField *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
3168static bool is_container(TypeTableEntry *type_entry) {3356static 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 algorithm4151 // 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}
41554342
4343void 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
4349ConstExprValue *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
4156void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) {4356void 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}
42184418
4219void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag) {4419void 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}
42244424
4225ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag) {4425ConstExprValue *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}
42304430
4431
4231void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value) {4432void 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}
48315025
4832TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {5026TypeTableEntry *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);
48385031
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 }
48575050
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);
64ScopeDecls *get_container_scope(TypeTableEntry *type_entry);64ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
65TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);65TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
66TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);66TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
67TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);
68TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag);
69
67bool is_container_ref(TypeTableEntry *type_entry);70bool is_container_ref(TypeTableEntry *type_entry);
68void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);71void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
69void scan_import(CodeGen *g, ImportTableEntry *import);72void 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);
109void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);112void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);
110ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);113ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);
111114
115void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint);
116ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint);
117
112void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative);118void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative);
113ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative);119ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative);
114120
...@@ -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);
121void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);127void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);
122ConstExprValue *create_const_float(TypeTableEntry *type, double value);128ConstExprValue *create_const_float(TypeTableEntry *type, double value);
123129
124void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag);130void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);
125ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag);131ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag);
126132
127void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);133void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);
128ConstExprValue *create_const_bool(CodeGen *g, bool value);134ConstExprValue *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);
158164
159TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);165TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
160ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);166ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
161TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type);
162void expand_undef_array(CodeGen *g, ConstExprValue *const_val);167void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
163void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);168void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
164169
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 }
676693
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
1228uint32_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
1236bool bigint_eql(BigInt a, BigInt b) {
1237 return bigint_cmp(&a, &b) == CmpEQ;
1238}
1239
1240void 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 functions88// convenience functions
89Cmp bigint_cmp_zero(const BigInt *op);89Cmp bigint_cmp_zero(const BigInt *op);
9090
91void bigint_incr(BigInt *value);
92
91bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result);93bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result);
9294
95uint32_t bigint_hash(BigInt x);
96bool bigint_eql(BigInt a, BigInt b);
97
93#endif98#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 type1916 // 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
1942static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) {1940static 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 }
19541944
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}
19591949
1960static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) {1950static 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}
23762366
2377static 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
2398static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,2367static 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);
24252392
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}
27482718
2749static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable,2719static 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);
27542725
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;
27592730
2760 // if the field_count can't fit in the bits of the enum_tag_type, then it can't possibly2731 // if the field_count can't fit in the bits of the enum_type, then it can't possibly
2761 // be the wrong value2732 // 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
27702740
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}
27782748
2779static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable,2749static 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}
33493319
3350static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrInstructionEnumTag *instruction) {3320static 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;
33553327
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;
33593331
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}
33643337
3365static 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
3392static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {3338static 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);
34353382
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) {
38383787
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);
40033951
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 }
40073960
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 }
40293990
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 }
40333995
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);
40353998
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 }
40454008
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;
40584010
4059 bool make_unnamed_struct;4011 case TypeTableEntryIdEnum:
40604012 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) {
43034220
43044221
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;
43094225
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}
43424258
...@@ -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};
3031
31const char *err_str(int err);32const 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}
225225
226static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumFieldPtr *) {
227 return IrInstructionIdEnumFieldPtr;
228}
229
230static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionFieldPtr *) {226static 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}
321317
322static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTag *) {318static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionTag *) {
323 return IrInstructionIdEnumTag;319 return IrInstructionIdUnionTag;
324}320}
325321
326static constexpr IrInstructionId ir_instruction_id(IrInstructionImport *) {322static 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}
481477
482static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) {
483 return IrInstructionIdInitEnum;
484}
485
486static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {478static 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}
549541
550static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTagName *) {542static constexpr IrInstructionId ir_instruction_id(IrInstructionTagName *) {
551 return IrInstructionIdEnumTagName;543 return IrInstructionIdTagName;
544}
545
546static constexpr IrInstructionId ir_instruction_id(IrInstructionTagType *) {
547 return IrInstructionIdTagType;
552}548}
553549
554static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr *) {550static 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}
911907
912static 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
924static 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
933static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,908static 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}
15261501
1527static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1502static 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;
15301505
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}
15351510
1536static 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
1543static IrInstruction *ir_build_import(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) {1511static 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}
20311999
2032static 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
2045static 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
2054static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,2000static 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}
22612207
2262static IrInstruction *ir_build_enum_tag_name(IrBuilder *irb, Scope *scope, AstNode *source_node,2208static 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
2219static 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;
22672224
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}
24682425
2469static 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
2476static IrInstruction *ir_instruction_unionfieldptr_get_dep(IrInstructionUnionFieldPtr *instruction, size_t index) {2426static 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}
26442594
2645static IrInstruction *ir_instruction_enumtag_get_dep(IrInstructionEnumTag *instruction, size_t index) {2595static 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}
29302880
2931static 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
2938static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instruction,2881static 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}
30613004
3062static IrInstruction *ir_instruction_enumtagname_get_dep(IrInstructionEnumTagName *instruction, size_t index) {3005static 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
3012static 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
46714619
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;
46804638
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);
83508307
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 }
83608332
...@@ -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}
83668338
8339static 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
8367static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,8364static 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);
84218418
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
84368449
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 }
84428455
...@@ -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 }
88758888
8876 // explicit cast from integer to enum type with no payload8889 // 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 }
88838893
8884 // explicit cast from enum type with no payload to integer8894 // 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 }
88918898
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 anything8910 // 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;
90979115
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}
91019119
...@@ -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;
91179135
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
9140static 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}
91219159
...@@ -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;
93289366
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;
93489386
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 }
1115511187
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 }
1116011192
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
1176811793
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 }
1236912400
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;
1238312402
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;
1238512406
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);
1239512416
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}
1276312781
12764static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) {12782static 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;
1276712785
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 }
1277312795
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);
1277512798
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 }
1278812811
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);
1281812841
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;
1286512888
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,
1294612969
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;
1295812984 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/8313015 // 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
1299613042
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;
1300313049
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 }
1301213052
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 }
1302513065
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}
1303513075
13036static TypeTableEntry *ir_analyze_instruction_enum_tag(IrAnalyze *ira, IrInstructionEnumTag *enum_tag_instruction) {13076static 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}
1304213082
...@@ -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
1319213232
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;
1319613236
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}
1364113643
13642static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructionEnumTagName *instruction) {13644static 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;
1364613648
13647 assert(target->value.type->id == TypeTableEntryIdEnumTag);13649 assert(target->value.type->id == TypeTableEntryIdEnum);
1364813650
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 }
1365813658
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 }
1366313663
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;
1380713807
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}
1381213812
...@@ -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
1387013870
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 }
1387513878
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];
1464314646
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];
1468514688
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;
1506115075
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];
1506715082
...@@ -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;
1507515090
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 }
1509215094
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}
1583015843
15844static 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
15831static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {15883static 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}
292292
293static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {293static 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;
295295
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}
363363
364static 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
371static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) {364static 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}
377370
...@@ -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}
511504
512static void ir_print_enum_tag(IrPrint *irp, IrInstructionEnumTag *instruction) {505static 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}
516509
...@@ -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}
801794
802static 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
808static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {795static 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}
887874
888static void ir_print_enum_tag_name(IrPrint *irp, IrInstructionEnumTagName *instruction) {875static 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}
892879
...@@ -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}
996983
984static 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
997990
998static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {991static 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"
935936
936static void set_color_posix(TermColor color) {937static 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};
2627
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}
23782378
2379/*2379/*
2380ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"2380ContainerDecl = option("extern" | "packed")
2381 ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))
2382 "{" many(ContainerMember) "}"
2381ContainerMember = (ContainerField | FnDef | GlobalVarDecl)2383ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
2382ContainerField = Symbol option(":" Expression) ","2384ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","
2383*/2385*/
2384static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) {2386static 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;
24172419
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);
24192443
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;
24542478
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);
24572482
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 }
24632493
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);
24712499
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}
653653
654static 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
654static bool c_is_float(Context *c, QualType qt) {662static 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 }
34213448
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 }
43064333
4307 return 0;4334 return ErrorCCompileErrors;
4308 }4335 }
43094336
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();
794794
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);
797797
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;
4const assert = debug.assert;4const assert = debug.assert;
5const ArrayList = @import("array_list.zig").ArrayList;5const ArrayList = @import("array_list.zig").ArrayList;
66
7const 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.
8pub const Buffer = struct {10pub 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 }
98100
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 };
7171
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 exists456 // 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};
687687
688const Target = enum {688const Target = union(enum) {
689 Native,689 Native: void,
690 Cross: CrossTarget,690 Cross: CrossTarget,
691691
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));
11901190
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));
11931193
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 }
11981198
...@@ -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));
16241624
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));
16271627
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 }
16321632
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};
282282
283const FormValue = enum {283const 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};
309309
...@@ -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
475475
476fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {476fn 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}
480480
481fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {481fn 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}
485485
486fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue {486fn 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 {
510510
511fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {511fn 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}
515515
516fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue {516fn 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
520520
521fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue {521fn 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) },
550548
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 },
559557
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) },
562560
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 }
673671
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;
676674
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;
679677
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));
843841
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;
846844
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 };
852850
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 @@
1const builtin = @import("builtin");
1const std = @import("index.zig");2const std = @import("index.zig");
2const io = std.io;3const io = std.io;
3const math = std.math;4const 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 };
107108
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 };
113114
...@@ -117,7 +118,7 @@ pub const Elf = struct {...@@ -117,7 +118,7 @@ pub const Elf = struct {
117 // skip over padding118 // skip over padding
118 %return elf.in_file.seekForward(9);119 %return elf.in_file.seekForward(9);
119120
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 };
127128
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 };
140141
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;
143144
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 }
153154
154 // skip over flags155 // skip over flags
155 %return elf.in_file.seekForward(4);156 %return elf.in_file.seekForward(4);
156157
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) or159 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 }
163164
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));
169170
170 if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;171 if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
171172
...@@ -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;
189190
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;
204205
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 }
219220
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}
1111
12pub fn swapIf(is_be: bool, comptime T: type, x: T) -> T {12pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T {
13 if (builtin.is_big_endian == is_be) swap(T, x) else x13 if (builtin.endian == endian) swap(T, x) else x
14}14}
1515
16pub fn swap(comptime T: type, x: T) -> T {16pub 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 }
442442
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 }
446446
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 }
450450
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 }
456456
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 }
465465
466466
std/mem.zig+79-32
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const debug = @import("debug.zig");1const debug = @import("debug.zig");
2const assert = debug.assert;2const assert = debug.assert;
3const math = @import("math/index.zig");3const math = @import("math/index.zig");
4const builtin = @import("builtin");
45
5pub const Cmp = math.Cmp;6pub const Cmp = math.Cmp;
67
...@@ -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 store182/// T specifies the return type, which must be large enough to store
182/// the result.183/// the result.
183pub fn readInt(bytes: []const u8, comptime T: type, big_endian: bool) -> T {184/// See also ::readIntBE or ::readIntLE.
185pub 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}
200205
206/// Reads a big-endian int of type T from bytes.
207/// bytes.len must be exactly @sizeOf(T).
208pub 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).
222pub 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 zeroes234/// 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.
204pub fn writeInt(buf: []u8, value: var, big_endian: bool) {237pub 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) {
211244 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" {
348fn testReadIntImpl() {384fn 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}
365412
366test "testWriteInt" {413test "testWriteInt" {
...@@ -370,16 +417,16 @@ test "testWriteInt" {...@@ -370,16 +417,16 @@ test "testWriteInt" {
370fn testWriteIntImpl() {417fn testWriteIntImpl() {
371 var bytes: [4]u8 = undefined;418 var bytes: [4]u8 = undefined;
372419
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 }));
375422
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 }));
378425
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 }));
381428
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}
385432
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,
6060
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 });
221221
...@@ -281,13 +281,13 @@ pub const ChildProcess = struct {...@@ -281,13 +281,13 @@ pub const ChildProcess = struct {
281281
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 }
293293
...@@ -722,14 +722,14 @@ const ErrInt = @IntType(false, @sizeOf(error) * 8);...@@ -722,14 +722,14 @@ const ErrInt = @IntType(false, @sizeOf(error) * 8);
722722
723fn writeIntFd(fd: i32, value: ErrInt) -> %void {723fn 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}
728728
729fn readIntFd(fd: i32) -> %ErrInt {729fn 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}
734734
735extern fn sigchld_handler(_: i32) {735extern fn sigchld_handler(_: i32) {
std/os/index.zig+3-2
...@@ -939,6 +939,7 @@ start_over:...@@ -939,6 +939,7 @@ start_over:
939}939}
940940
941pub const Dir = struct {941pub 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 {
981982
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 }
986987
987 /// Memory such as file names referenced in this returned entry becomes invalid988 /// 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;
10191020
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 {
10161016
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}
10221022
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 {
9898
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");
44
5pub const Cmp = math.Cmp;5pub const Cmp = math.Cmp;
66
7/// Stable sort using O(1) space. Currently implemented as insertion sort.
8pub 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.
7pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) {20pub 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// tests72// tests
6073
74test "stable sort" {
75 testStableSort();
76 // TODO: uncomment this after https://github.com/zig-lang/zig/issues/639
77 //comptime testStableSort();
78}
79fn 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}
123const IdAndValue = struct {
124 id: i32,
125 value: i32,
126};
127fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) -> Cmp {
128 return i32asc(a.value, b.value);
129}
130
61test "testSort" {131test "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 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const is_test = builtin.is_test;2const is_test = builtin.is_test;
33
4const low = if (builtin.is_big_endian) 1 else 0;4const low = switch (builtin.endian) { builtin.Endian.Big => 1, builtin.Endian.Little => 0 };
5const high = 1 - low;5const high = 1 - low;
66
7pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?&DoubleInt) -> DoubleInt {7pub 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 @@
1const E = enum { A: [9]u8, B: u64, };1const E = union(enum) { A: [9]u8, B: u64, };
2const S = struct { x: u8, y: E, };2const S = struct { x: u8, y: E, };
33
4const assert = @import("std").debug.assert;4const assert = @import("std").debug.assert;
55
6test "bug 394 fixed" {6test "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;
2const mem = @import("std").mem;2const mem = @import("std").mem;
33
4test "enum type" {4test "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;
88
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};
27const Foo = enum {27const Foo = union(enum) {
28 One: i32,28 One: i32,
29 Two: Point,29 Two: Point,
30 Three: void,30 Three: void,
31};31};
32const FooNoVoid = enum {32const 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};
4242
43fn returnAnInt(x: i32) -> Foo {43fn returnAnInt(x: i32) -> Foo {
44 Foo.One { x }44 Foo { .One = x }
45}45}
4646
4747
48test "constant enum with payload" {48test "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}
6868
69const AnEnumWithPayload = enum {69const AnEnumWithPayload = union(enum) {
70 Empty,70 Empty: void,
71 Full: i32,71 Full: i32,
72};72};
7373
...@@ -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}
9191
92fn shouldEqual(n: Number, expected: usize) {92fn shouldEqual(n: Number, expected: u3) {
93 assert(usize(n) == expected);93 assert(u3(n) == expected);
94}94}
9595
9696
...@@ -98,7 +98,7 @@ test "int to enum" {...@@ -98,7 +98,7 @@ test "int to enum" {
98 testIntToEnumEval(3);98 testIntToEnumEval(3);
99}99}
100fn testIntToEnumEval(x: i32) {100fn testIntToEnumEval(x: i32) {
101 assert(IntToEnumNumber(x) == IntToEnumNumber.Three);101 assert(IntToEnumNumber(u3(x)) == IntToEnumNumber.Three);
102}102}
103const IntToEnumNumber = enum {103const IntToEnumNumber = enum {
104 Zero,104 Zero,
...@@ -109,13 +109,13 @@ const IntToEnumNumber = enum {...@@ -109,13 +109,13 @@ const IntToEnumNumber = enum {
109};109};
110110
111111
112test "@enumTagName" {112test "@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}
116116
117fn testEnumTagNameBare(n: BareNumber) -> []const u8 {117fn testEnumTagNameBare(n: BareNumber) -> []const u8 {
118 return @enumTagName(n);118 return @tagName(n);
119}119}
120120
121const BareNumber = enum {121const BareNumber = enum {
...@@ -132,12 +132,11 @@ test "enum alignment" {...@@ -132,12 +132,11 @@ test "enum alignment" {
132 }132 }
133}133}
134134
135const AlignTestEnum = enum {135const AlignTestEnum = union(enum) {
136 A: [9]u8,136 A: [9]u8,
137 B: u64,137 B: u64,
138};138};
139139
140const ValueCount0 = enum {};
141const ValueCount1 = enum { I0 };140const ValueCount1 = enum { I0 };
142const ValueCount2 = enum { I0, I1 };141const ValueCount2 = enum { I0, I1 };
143const ValueCount256 = enum {142const ValueCount256 = enum {
...@@ -183,10 +182,165 @@ const ValueCount257 = enum {...@@ -183,10 +182,165 @@ const ValueCount257 = enum {
183182
184test "enum sizes" {183test "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
192const Small2 = enum (u2) {
193 One,
194 Two,
195};
196const Small = enum (u2) {
197 One,
198 Two,
199 Three,
200 Four,
201};
202
203test "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
217const A = enum (u3) {
218 One,
219 Two,
220 Three,
221 Four,
222 One2,
223 Two2,
224 Three2,
225 Four2,
226};
227
228const B = enum (u3) {
229 One3,
230 Two3,
231 Three3,
232 Four3,
233 One23,
234 Two23,
235 Three23,
236 Four23,
237};
238
239const C = enum (u2) {
240 One4,
241 Two4,
242 Three4,
243 Four4,
244};
245
246const BitFieldOfEnums = packed struct {
247 a: A,
248 b: B,
249 c: C,
250};
251
252const bit_field_1 = BitFieldOfEnums {
253 .a = A.Two,
254 .b = B.Three3,
255 .c = C.Four4,
256};
257
258test "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
273fn getA(data: &const BitFieldOfEnums) -> A {
274 return data.a;
275}
276
277fn getB(data: &const BitFieldOfEnums) -> B {
278 return data.b;
279}
280
281fn getC(data: &const BitFieldOfEnums) -> C {
282 return data.c;
283}
284
285test "casting enum to its tag type" {
286 testCastEnumToTagType(Small2.Two);
287 comptime testCastEnumToTagType(Small2.Two);
288}
289
290fn testCastEnumToTagType(value: Small2) {
291 assert(u2(value) == 1);
292}
293
294const MultipleChoice = enum(u32) {
295 A = 20,
296 B = 40,
297 C = 60,
298 D = 1000,
299};
300
301test "enum with specified tag values" {
302 testEnumWithSpecifiedTagValues(MultipleChoice.C);
303 comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
304}
305
306fn 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
316const 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
328test "enum with specified and unspecified tag values" {
329 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
330 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
331}
332
333fn 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;
2const mem = @import("std").mem;2const mem = @import("std").mem;
3const fmt = @import("std").fmt;3const fmt = @import("std").fmt;
44
5const ET = enum {5const ET = union(enum) {
6 SINT: i32,6 SINT: i32,
7 UINT: u32,7 UINT: u32,
88
...@@ -15,8 +15,8 @@ const ET = enum {...@@ -15,8 +15,8 @@ const ET = enum {
15};15};
1616
17test "enum with members" {17test "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;
2121
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}
327const Test3Foo = enum {327const 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};
336const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}};336const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}};
337const test3_bar = Test3Foo.Two{13};337const test3_bar = Test3Foo { .Two = 13};
338fn test3_1(f: &const Test3Foo) {338fn 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) {
449const Tid = builtin.TypeId;449const Tid = builtin.TypeId;
450const AStruct = struct { x: i32, };450const AStruct = struct { x: i32, };
451const AnEnum = enum { One, Two, };451const AnEnum = enum { One, Two, };
452const AnEnumWithPayload = enum { One: i32, Two, };452const AUnionEnum = union(enum) { One: i32, Two: void, };
453const AUnion = union { One: void, Two: void };
453454
454test "@typeId" {455test "@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 union479 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};
6464
65const Bar = enum {65const 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 {
8383
8484
85test "switch prong with variable" {85test "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}
90const SwitchProngWithVarEnum = enum {90const SwitchProngWithVarEnum = union(enum) {
91 One: i32,91 One: i32,
92 Two: f32,92 Two: f32,
93 Meh,93 Meh: void,
94};94};
95fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) {95fn 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}
113113
114fn testSwitchEnumPtrCapture() {114fn 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}
137137
138138
139const Number = enum {139const Number = union(enum) {
140 One: u64,140 One: u64,
141 Two: u8,141 Two: u8,
142 Three: f32,142 Three: f32,
143};143};
144144
145const number = Number.Three { 1.23 };145const number = Number { .Three = 1.23 };
146146
147fn returnsFalse() -> bool {147fn 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
228fn return_a_number() -> %i32 {
229 return 1;
230}
231
232test "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 {
99
10error InvalidDebugInfo;10error InvalidDebugInfo;
1111
12const FormValue = enum {12const FormValue = union(enum) {
13 Address: u64,13 Address: u64,
14 Other: bool,14 Other: bool,
15};15};
1616
17fn doThing(form_id: u64) -> %FormValue {17fn 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 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3const FormValue = enum {3const FormValue = union(enum) {
4 One,4 One: void,
5 Two: bool,5 Two: bool,
6};6};
77
...@@ -9,8 +9,8 @@ error Whatever;...@@ -9,8 +9,8 @@ error Whatever;
99
10fn foo(id: u64) -> %FormValue {10fn 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 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3const Value = enum {3const 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};
1212
13const v1 = Value.Int { 1234 };13const v1 = Value { .Int = 1234 };
14const v2 = Value.Array { []u8{3} ** 9 };14const v2 = Value { .Array = []u8{3} ** 9 };
1515
16const err = (%Agg)(Agg {16const 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}
7777
78
79const Letter = enum {
80 A,
81 B,
82 C,
83};
84const Payload = union(Letter) {
85 A: i32,
86 B: f64,
87 C: bool,
88};
89
90test "union with specified enum tag" {
91 doTest();
92 comptime doTest();
93}
94
95fn doTest() {
96 assert(bar(Payload {.A = 1234}) == -10);
97}
98
99fn 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
108const MultipleChoice = union(enum(u32)) {
109 A = 20,
110 B = 40,
111 C = 60,
112 D = 1000,
113};
114test "simple union(enum(u32))" {
115 var x = MultipleChoice.C;
116 assert(x == MultipleChoice.C);
117 assert(u32(@TagType(MultipleChoice)(x)) == 60);
118}
119
120const 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
132test "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
138fn 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
154const ExternPtrOrInt = extern union {
155 ptr: &u8,
156 int: u64
157};
158test "extern union size" {
159 comptime assert(@sizeOf(ExternPtrOrInt) == 8);
160}
161
162const PackedPtrOrInt = packed union {
163 ptr: &u8,
164 int: u64
165};
166test "extern union size" {
167 comptime assert(@sizeOf(PackedPtrOrInt) == 8);
168}
169
170const ZeroBits = union {
171 OnlyField: void,
172};
173test "union with only 1 field which is void should be zero bits" {
174 comptime assert(@sizeOf(ZeroBits) == 0);
175}
176
177const TheTag = enum {A, B, C};
178const TheUnion = union(TheTag) { A: i32, B: i32, C: i32 };
179test "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
185test "cast union to tag type of union" {
186 testCastUnionToTagType(TheUnion {.B = 1234});
187 comptime testCastUnionToTagType(TheUnion {.B = 1234});
188}
189
190fn 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 == b931 \\ 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");
22992299
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");
23072315
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");
23152323
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) {
23302338
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");
23382354
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 {
682682
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 {
750750
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}