mirror of
https://github.com/ziglang/zig.git
synced 2025-12-23 22:53:06 +00:00
Merge branch 'master' into llvm6
This commit is contained in:
commit
42004f9013
@ -47,15 +47,20 @@ option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF)
|
||||
option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead of the embedded LLD" OFF)
|
||||
|
||||
find_package(llvm)
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
|
||||
find_package(clang)
|
||||
include_directories(${CLANG_INCLUDE_DIRS})
|
||||
|
||||
if(ZIG_FORCE_EXTERNAL_LLD)
|
||||
find_package(lld)
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
include_directories(${LLD_INCLUDE_DIRS})
|
||||
include_directories(${CLANG_INCLUDE_DIRS})
|
||||
else()
|
||||
# This goes first so that we find embedded LLD instead
|
||||
# of system LLD.
|
||||
include_directories("${CMAKE_SOURCE_DIR}/deps/lld/include")
|
||||
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
include_directories(${CLANG_INCLUDE_DIRS})
|
||||
set(EMBEDDED_LLD_LIB_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/deps/lld/lib/Driver/DarwinLdDriver.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/deps/lld/lib/Config/Version.cpp"
|
||||
|
||||
@ -4543,37 +4543,6 @@ _mm512_maskz_unpacklo_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
|
||||
(__v8di)_mm512_setzero_si512());
|
||||
}
|
||||
|
||||
/* Bit Test */
|
||||
|
||||
static __inline __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_test_epi32_mask(__m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask16) __builtin_ia32_ptestmd512 ((__v16si) __A,
|
||||
(__v16si) __B,
|
||||
(__mmask16) -1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_test_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask16) __builtin_ia32_ptestmd512 ((__v16si) __A,
|
||||
(__v16si) __B, __U);
|
||||
}
|
||||
|
||||
static __inline __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_test_epi64_mask(__m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask8) __builtin_ia32_ptestmq512 ((__v8di) __A,
|
||||
(__v8di) __B,
|
||||
(__mmask8) -1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_test_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask8) __builtin_ia32_ptestmq512 ((__v8di) __A, (__v8di) __B, __U);
|
||||
}
|
||||
|
||||
|
||||
/* SIMD load ops */
|
||||
|
||||
@ -4844,293 +4813,105 @@ _mm512_knot(__mmask16 __M)
|
||||
|
||||
/* Integer compare */
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpeq_epi32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_pcmpeqd512_mask((__v16si)__a, (__v16si)__b,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
#define _mm512_cmpeq_epi32_mask(A, B) \
|
||||
_mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_EQ)
|
||||
#define _mm512_mask_cmpeq_epi32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_EQ)
|
||||
#define _mm512_cmpge_epi32_mask(A, B) \
|
||||
_mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_GE)
|
||||
#define _mm512_mask_cmpge_epi32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GE)
|
||||
#define _mm512_cmpgt_epi32_mask(A, B) \
|
||||
_mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_GT)
|
||||
#define _mm512_mask_cmpgt_epi32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GT)
|
||||
#define _mm512_cmple_epi32_mask(A, B) \
|
||||
_mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_LE)
|
||||
#define _mm512_mask_cmple_epi32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LE)
|
||||
#define _mm512_cmplt_epi32_mask(A, B) \
|
||||
_mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_LT)
|
||||
#define _mm512_mask_cmplt_epi32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LT)
|
||||
#define _mm512_cmpneq_epi32_mask(A, B) \
|
||||
_mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_NE)
|
||||
#define _mm512_mask_cmpneq_epi32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_NE)
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpeq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_pcmpeqd512_mask((__v16si)__a, (__v16si)__b,
|
||||
__u);
|
||||
}
|
||||
#define _mm512_cmpeq_epu32_mask(A, B) \
|
||||
_mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_EQ)
|
||||
#define _mm512_mask_cmpeq_epu32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_EQ)
|
||||
#define _mm512_cmpge_epu32_mask(A, B) \
|
||||
_mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_GE)
|
||||
#define _mm512_mask_cmpge_epu32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GE)
|
||||
#define _mm512_cmpgt_epu32_mask(A, B) \
|
||||
_mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_GT)
|
||||
#define _mm512_mask_cmpgt_epu32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GT)
|
||||
#define _mm512_cmple_epu32_mask(A, B) \
|
||||
_mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_LE)
|
||||
#define _mm512_mask_cmple_epu32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LE)
|
||||
#define _mm512_cmplt_epu32_mask(A, B) \
|
||||
_mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_LT)
|
||||
#define _mm512_mask_cmplt_epu32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LT)
|
||||
#define _mm512_cmpneq_epu32_mask(A, B) \
|
||||
_mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_NE)
|
||||
#define _mm512_mask_cmpneq_epu32_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_NE)
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpeq_epu32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 0,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
#define _mm512_cmpeq_epi64_mask(A, B) \
|
||||
_mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_EQ)
|
||||
#define _mm512_mask_cmpeq_epi64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_EQ)
|
||||
#define _mm512_cmpge_epi64_mask(A, B) \
|
||||
_mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_GE)
|
||||
#define _mm512_mask_cmpge_epi64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GE)
|
||||
#define _mm512_cmpgt_epi64_mask(A, B) \
|
||||
_mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_GT)
|
||||
#define _mm512_mask_cmpgt_epi64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GT)
|
||||
#define _mm512_cmple_epi64_mask(A, B) \
|
||||
_mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_LE)
|
||||
#define _mm512_mask_cmple_epi64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LE)
|
||||
#define _mm512_cmplt_epi64_mask(A, B) \
|
||||
_mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_LT)
|
||||
#define _mm512_mask_cmplt_epi64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LT)
|
||||
#define _mm512_cmpneq_epi64_mask(A, B) \
|
||||
_mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_NE)
|
||||
#define _mm512_mask_cmpneq_epi64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_NE)
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpeq_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 0,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpeq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_pcmpeqq512_mask((__v8di)__a, (__v8di)__b,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpeq_epi64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_pcmpeqq512_mask((__v8di)__a, (__v8di)__b,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpeq_epu64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 0,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpeq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 0,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpge_epi32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 5,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpge_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 5,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpge_epu32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 5,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpge_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 5,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpge_epi64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 5,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpge_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 5,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpge_epu64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 5,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpge_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 5,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpgt_epi32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_pcmpgtd512_mask((__v16si)__a, (__v16si)__b,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpgt_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_pcmpgtd512_mask((__v16si)__a, (__v16si)__b,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpgt_epu32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 6,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpgt_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 6,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpgt_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_pcmpgtq512_mask((__v8di)__a, (__v8di)__b,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpgt_epi64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_pcmpgtq512_mask((__v8di)__a, (__v8di)__b,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpgt_epu64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 6,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpgt_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 6,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmple_epi32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 2,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmple_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 2,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmple_epu32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 2,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmple_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 2,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmple_epi64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 2,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmple_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 2,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmple_epu64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 2,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmple_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 2,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmplt_epi32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 1,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmplt_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 1,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmplt_epu32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 1,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmplt_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 1,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmplt_epi64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 1,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmplt_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 1,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmplt_epu64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 1,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmplt_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 1,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpneq_epi32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 4,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpneq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 4,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpneq_epu32_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 4,
|
||||
(__mmask16)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpneq_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 4,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpneq_epi64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 4,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpneq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 4,
|
||||
__u);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_cmpneq_epu64_mask(__m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 4,
|
||||
(__mmask8)-1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_cmpneq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
|
||||
return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 4,
|
||||
__u);
|
||||
}
|
||||
#define _mm512_cmpeq_epu64_mask(A, B) \
|
||||
_mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_EQ)
|
||||
#define _mm512_mask_cmpeq_epu64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_EQ)
|
||||
#define _mm512_cmpge_epu64_mask(A, B) \
|
||||
_mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_GE)
|
||||
#define _mm512_mask_cmpge_epu64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GE)
|
||||
#define _mm512_cmpgt_epu64_mask(A, B) \
|
||||
_mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_GT)
|
||||
#define _mm512_mask_cmpgt_epu64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GT)
|
||||
#define _mm512_cmple_epu64_mask(A, B) \
|
||||
_mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_LE)
|
||||
#define _mm512_mask_cmple_epu64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LE)
|
||||
#define _mm512_cmplt_epu64_mask(A, B) \
|
||||
_mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_LT)
|
||||
#define _mm512_mask_cmplt_epu64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LT)
|
||||
#define _mm512_cmpneq_epu64_mask(A, B) \
|
||||
_mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_NE)
|
||||
#define _mm512_mask_cmpneq_epu64_mask(k, A, B) \
|
||||
_mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_NE)
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS
|
||||
_mm512_cvtepi8_epi32(__m128i __A)
|
||||
@ -6797,35 +6578,6 @@ _mm512_maskz_permutex2var_ps (__mmask16 __U, __m512 __A, __m512i __I,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_testn_epi32_mask (__m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask16) __builtin_ia32_ptestnmd512 ((__v16si) __A,
|
||||
(__v16si) __B,
|
||||
(__mmask16) -1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_testn_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask16) __builtin_ia32_ptestnmd512 ((__v16si) __A,
|
||||
(__v16si) __B, __U);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_testn_epi64_mask (__m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask8) __builtin_ia32_ptestnmq512 ((__v8di) __A,
|
||||
(__v8di) __B,
|
||||
(__mmask8) -1);
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_testn_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask8) __builtin_ia32_ptestnmq512 ((__v8di) __A,
|
||||
(__v8di) __B, __U);
|
||||
}
|
||||
|
||||
#define _mm512_cvtt_roundpd_epu32(A, R) __extension__ ({ \
|
||||
(__m256i)__builtin_ia32_cvttpd2udq512_mask((__v8df)(__m512d)(A), \
|
||||
@ -7194,76 +6946,100 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B)
|
||||
}
|
||||
|
||||
#define _mm512_shuffle_f32x4(A, B, imm) __extension__ ({ \
|
||||
(__m512)__builtin_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \
|
||||
(__v16sf)(__m512)(B), (int)(imm), \
|
||||
(__v16sf)_mm512_undefined_ps(), \
|
||||
(__mmask16)-1); })
|
||||
(__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \
|
||||
(__v16sf)(__m512)(B), \
|
||||
0 + ((((imm) >> 0) & 0x3) * 4), \
|
||||
1 + ((((imm) >> 0) & 0x3) * 4), \
|
||||
2 + ((((imm) >> 0) & 0x3) * 4), \
|
||||
3 + ((((imm) >> 0) & 0x3) * 4), \
|
||||
0 + ((((imm) >> 2) & 0x3) * 4), \
|
||||
1 + ((((imm) >> 2) & 0x3) * 4), \
|
||||
2 + ((((imm) >> 2) & 0x3) * 4), \
|
||||
3 + ((((imm) >> 2) & 0x3) * 4), \
|
||||
16 + ((((imm) >> 4) & 0x3) * 4), \
|
||||
17 + ((((imm) >> 4) & 0x3) * 4), \
|
||||
18 + ((((imm) >> 4) & 0x3) * 4), \
|
||||
19 + ((((imm) >> 4) & 0x3) * 4), \
|
||||
16 + ((((imm) >> 6) & 0x3) * 4), \
|
||||
17 + ((((imm) >> 6) & 0x3) * 4), \
|
||||
18 + ((((imm) >> 6) & 0x3) * 4), \
|
||||
19 + ((((imm) >> 6) & 0x3) * 4)); })
|
||||
|
||||
#define _mm512_mask_shuffle_f32x4(W, U, A, B, imm) __extension__ ({ \
|
||||
(__m512)__builtin_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \
|
||||
(__v16sf)(__m512)(B), (int)(imm), \
|
||||
(__v16sf)(__m512)(W), \
|
||||
(__mmask16)(U)); })
|
||||
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
|
||||
(__v16sf)_mm512_shuffle_f32x4((A), (B), (imm)), \
|
||||
(__v16sf)(__m512)(W)); })
|
||||
|
||||
#define _mm512_maskz_shuffle_f32x4(U, A, B, imm) __extension__ ({ \
|
||||
(__m512)__builtin_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \
|
||||
(__v16sf)(__m512)(B), (int)(imm), \
|
||||
(__v16sf)_mm512_setzero_ps(), \
|
||||
(__mmask16)(U)); })
|
||||
(__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
|
||||
(__v16sf)_mm512_shuffle_f32x4((A), (B), (imm)), \
|
||||
(__v16sf)_mm512_setzero_ps()); })
|
||||
|
||||
#define _mm512_shuffle_f64x2(A, B, imm) __extension__ ({ \
|
||||
(__m512d)__builtin_ia32_shuf_f64x2_mask((__v8df)(__m512d)(A), \
|
||||
(__v8df)(__m512d)(B), (int)(imm), \
|
||||
(__v8df)_mm512_undefined_pd(), \
|
||||
(__mmask8)-1); })
|
||||
(__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \
|
||||
(__v8df)(__m512d)(B), \
|
||||
0 + ((((imm) >> 0) & 0x3) * 2), \
|
||||
1 + ((((imm) >> 0) & 0x3) * 2), \
|
||||
0 + ((((imm) >> 2) & 0x3) * 2), \
|
||||
1 + ((((imm) >> 2) & 0x3) * 2), \
|
||||
8 + ((((imm) >> 4) & 0x3) * 2), \
|
||||
9 + ((((imm) >> 4) & 0x3) * 2), \
|
||||
8 + ((((imm) >> 6) & 0x3) * 2), \
|
||||
9 + ((((imm) >> 6) & 0x3) * 2)); })
|
||||
|
||||
#define _mm512_mask_shuffle_f64x2(W, U, A, B, imm) __extension__ ({ \
|
||||
(__m512d)__builtin_ia32_shuf_f64x2_mask((__v8df)(__m512d)(A), \
|
||||
(__v8df)(__m512d)(B), (int)(imm), \
|
||||
(__v8df)(__m512d)(W), \
|
||||
(__mmask8)(U)); })
|
||||
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
|
||||
(__v8df)_mm512_shuffle_f64x2((A), (B), (imm)), \
|
||||
(__v8df)(__m512d)(W)); })
|
||||
|
||||
#define _mm512_maskz_shuffle_f64x2(U, A, B, imm) __extension__ ({ \
|
||||
(__m512d)__builtin_ia32_shuf_f64x2_mask((__v8df)(__m512d)(A), \
|
||||
(__v8df)(__m512d)(B), (int)(imm), \
|
||||
(__v8df)_mm512_setzero_pd(), \
|
||||
(__mmask8)(U)); })
|
||||
(__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
|
||||
(__v8df)_mm512_shuffle_f64x2((A), (B), (imm)), \
|
||||
(__v8df)_mm512_setzero_pd()); })
|
||||
|
||||
#define _mm512_shuffle_i32x4(A, B, imm) __extension__ ({ \
|
||||
(__m512i)__builtin_ia32_shuf_i32x4_mask((__v16si)(__m512i)(A), \
|
||||
(__v16si)(__m512i)(B), (int)(imm), \
|
||||
(__v16si)_mm512_setzero_si512(), \
|
||||
(__mmask16)-1); })
|
||||
(__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \
|
||||
(__v8di)(__m512i)(B), \
|
||||
0 + ((((imm) >> 0) & 0x3) * 2), \
|
||||
1 + ((((imm) >> 0) & 0x3) * 2), \
|
||||
0 + ((((imm) >> 2) & 0x3) * 2), \
|
||||
1 + ((((imm) >> 2) & 0x3) * 2), \
|
||||
8 + ((((imm) >> 4) & 0x3) * 2), \
|
||||
9 + ((((imm) >> 4) & 0x3) * 2), \
|
||||
8 + ((((imm) >> 6) & 0x3) * 2), \
|
||||
9 + ((((imm) >> 6) & 0x3) * 2)); })
|
||||
|
||||
#define _mm512_mask_shuffle_i32x4(W, U, A, B, imm) __extension__ ({ \
|
||||
(__m512i)__builtin_ia32_shuf_i32x4_mask((__v16si)(__m512i)(A), \
|
||||
(__v16si)(__m512i)(B), (int)(imm), \
|
||||
(__v16si)(__m512i)(W), \
|
||||
(__mmask16)(U)); })
|
||||
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
|
||||
(__v16si)_mm512_shuffle_i32x4((A), (B), (imm)), \
|
||||
(__v16si)(__m512i)(W)); })
|
||||
|
||||
#define _mm512_maskz_shuffle_i32x4(U, A, B, imm) __extension__ ({ \
|
||||
(__m512i)__builtin_ia32_shuf_i32x4_mask((__v16si)(__m512i)(A), \
|
||||
(__v16si)(__m512i)(B), (int)(imm), \
|
||||
(__v16si)_mm512_setzero_si512(), \
|
||||
(__mmask16)(U)); })
|
||||
(__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
|
||||
(__v16si)_mm512_shuffle_i32x4((A), (B), (imm)), \
|
||||
(__v16si)_mm512_setzero_si512()); })
|
||||
|
||||
#define _mm512_shuffle_i64x2(A, B, imm) __extension__ ({ \
|
||||
(__m512i)__builtin_ia32_shuf_i64x2_mask((__v8di)(__m512i)(A), \
|
||||
(__v8di)(__m512i)(B), (int)(imm), \
|
||||
(__v8di)_mm512_setzero_si512(), \
|
||||
(__mmask8)-1); })
|
||||
(__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \
|
||||
(__v8di)(__m512i)(B), \
|
||||
0 + ((((imm) >> 0) & 0x3) * 2), \
|
||||
1 + ((((imm) >> 0) & 0x3) * 2), \
|
||||
0 + ((((imm) >> 2) & 0x3) * 2), \
|
||||
1 + ((((imm) >> 2) & 0x3) * 2), \
|
||||
8 + ((((imm) >> 4) & 0x3) * 2), \
|
||||
9 + ((((imm) >> 4) & 0x3) * 2), \
|
||||
8 + ((((imm) >> 6) & 0x3) * 2), \
|
||||
9 + ((((imm) >> 6) & 0x3) * 2)); })
|
||||
|
||||
#define _mm512_mask_shuffle_i64x2(W, U, A, B, imm) __extension__ ({ \
|
||||
(__m512i)__builtin_ia32_shuf_i64x2_mask((__v8di)(__m512i)(A), \
|
||||
(__v8di)(__m512i)(B), (int)(imm), \
|
||||
(__v8di)(__m512i)(W), \
|
||||
(__mmask8)(U)); })
|
||||
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
|
||||
(__v8di)_mm512_shuffle_i64x2((A), (B), (imm)), \
|
||||
(__v8di)(__m512i)(W)); })
|
||||
|
||||
#define _mm512_maskz_shuffle_i64x2(U, A, B, imm) __extension__ ({ \
|
||||
(__m512i)__builtin_ia32_shuf_i64x2_mask((__v8di)(__m512i)(A), \
|
||||
(__v8di)(__m512i)(B), (int)(imm), \
|
||||
(__v8di)_mm512_setzero_si512(), \
|
||||
(__mmask8)(U)); })
|
||||
(__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
|
||||
(__v8di)_mm512_shuffle_i64x2((A), (B), (imm)), \
|
||||
(__v8di)_mm512_setzero_si512()); })
|
||||
|
||||
#define _mm512_shuffle_pd(A, B, M) __extension__ ({ \
|
||||
(__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \
|
||||
@ -9166,6 +8942,64 @@ _mm512_maskz_compress_epi32 (__mmask16 __U, __m512i __A)
|
||||
(__mmask8)(M), \
|
||||
_MM_FROUND_CUR_DIRECTION); })
|
||||
|
||||
/* Bit Test */
|
||||
|
||||
static __inline __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_test_epi32_mask (__m512i __A, __m512i __B)
|
||||
{
|
||||
return _mm512_cmpneq_epi32_mask (_mm512_and_epi32(__A, __B),
|
||||
_mm512_setzero_epi32());
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_test_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B)
|
||||
{
|
||||
return _mm512_mask_cmpneq_epi32_mask (__U, _mm512_and_epi32 (__A, __B),
|
||||
_mm512_setzero_epi32());
|
||||
}
|
||||
|
||||
static __inline __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_test_epi64_mask (__m512i __A, __m512i __B)
|
||||
{
|
||||
return _mm512_cmpneq_epi64_mask (_mm512_and_epi32 (__A, __B),
|
||||
_mm512_setzero_epi32());
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_test_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B)
|
||||
{
|
||||
return _mm512_mask_cmpneq_epi64_mask (__U, _mm512_and_epi32 (__A, __B),
|
||||
_mm512_setzero_epi32());
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_testn_epi32_mask (__m512i __A, __m512i __B)
|
||||
{
|
||||
return _mm512_cmpeq_epi32_mask (_mm512_and_epi32 (__A, __B),
|
||||
_mm512_setzero_epi32());
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_testn_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B)
|
||||
{
|
||||
return _mm512_mask_cmpeq_epi32_mask (__U, _mm512_and_epi32 (__A, __B),
|
||||
_mm512_setzero_epi32());
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_testn_epi64_mask (__m512i __A, __m512i __B)
|
||||
{
|
||||
return _mm512_cmpeq_epi64_mask (_mm512_and_epi32 (__A, __B),
|
||||
_mm512_setzero_epi32());
|
||||
}
|
||||
|
||||
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
|
||||
_mm512_mask_testn_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B)
|
||||
{
|
||||
return _mm512_mask_cmpeq_epi64_mask (__U, _mm512_and_epi32 (__A, __B),
|
||||
_mm512_setzero_epi32());
|
||||
}
|
||||
|
||||
static __inline__ __m512 __DEFAULT_FN_ATTRS
|
||||
_mm512_movehdup_ps (__m512 __A)
|
||||
{
|
||||
|
||||
4
deps/lld-prebuilt/lld/Config/Version.inc
vendored
4
deps/lld-prebuilt/lld/Config/Version.inc
vendored
@ -1,5 +1,5 @@
|
||||
#define LLD_VERSION 5.0.0
|
||||
#define LLD_VERSION_STRING "5.0.0"
|
||||
#define LLD_VERSION 5.0.1
|
||||
#define LLD_VERSION_STRING "5.0.1"
|
||||
#define LLD_VERSION_MAJOR 5
|
||||
#define LLD_VERSION_MINOR 0
|
||||
#define LLD_REVISION_STRING ""
|
||||
|
||||
1
deps/lld/COFF/Config.h
vendored
1
deps/lld/COFF/Config.h
vendored
@ -157,6 +157,7 @@ struct Configuration {
|
||||
uint32_t MinorImageVersion = 0;
|
||||
uint32_t MajorOSVersion = 6;
|
||||
uint32_t MinorOSVersion = 0;
|
||||
bool CanExitEarly = false;
|
||||
bool DynamicBase = true;
|
||||
bool NxCompat = true;
|
||||
bool AllowIsolation = true;
|
||||
|
||||
10
deps/lld/COFF/Driver.cpp
vendored
10
deps/lld/COFF/Driver.cpp
vendored
@ -52,15 +52,21 @@ BumpPtrAllocator BAlloc;
|
||||
StringSaver Saver{BAlloc};
|
||||
std::vector<SpecificAllocBase *> SpecificAllocBase::Instances;
|
||||
|
||||
bool link(ArrayRef<const char *> Args, raw_ostream &Diag) {
|
||||
bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {
|
||||
ErrorCount = 0;
|
||||
ErrorOS = &Diag;
|
||||
Config = make<Configuration>();
|
||||
Config->Argv = {Args.begin(), Args.end()};
|
||||
Config->ColorDiagnostics =
|
||||
(ErrorOS == &llvm::errs() && Process::StandardErrHasColors());
|
||||
Config->CanExitEarly = CanExitEarly;
|
||||
Driver = make<LinkerDriver>();
|
||||
Driver->link(Args);
|
||||
|
||||
// Call exit() if we can to avoid calling destructors.
|
||||
if (CanExitEarly)
|
||||
exitLld(ErrorCount ? 1 : 0);
|
||||
|
||||
freeArena();
|
||||
return !ErrorCount;
|
||||
}
|
||||
@ -1123,7 +1129,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||
// This is useful because MSVC link.exe can generate complete PDBs.
|
||||
if (Args.hasArg(OPT_msvclto)) {
|
||||
invokeMSVC(Args);
|
||||
exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Do LTO by compiling bitcode input files to a set of native COFF files then
|
||||
|
||||
5
deps/lld/COFF/Error.cpp
vendored
5
deps/lld/COFF/Error.cpp
vendored
@ -32,7 +32,7 @@ namespace coff {
|
||||
uint64_t ErrorCount;
|
||||
raw_ostream *ErrorOS;
|
||||
|
||||
static LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) {
|
||||
LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) {
|
||||
// Dealloc/destroy ManagedStatic variables before calling
|
||||
// _exit(). In a non-LTO build, this is a nop. In an LTO
|
||||
// build allows us to get the output of -time-passes.
|
||||
@ -78,7 +78,8 @@ void error(const Twine &Msg) {
|
||||
print("error: ", raw_ostream::RED);
|
||||
*ErrorOS << "too many errors emitted, stopping now"
|
||||
<< " (use /ERRORLIMIT:0 to see all errors)\n";
|
||||
exitLld(1);
|
||||
if (Config->CanExitEarly)
|
||||
exitLld(1);
|
||||
}
|
||||
|
||||
++ErrorCount;
|
||||
|
||||
2
deps/lld/COFF/Error.h
vendored
2
deps/lld/COFF/Error.h
vendored
@ -27,6 +27,8 @@ LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
|
||||
LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix);
|
||||
LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix);
|
||||
|
||||
LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
|
||||
|
||||
template <class T> T check(ErrorOr<T> V, const Twine &Prefix) {
|
||||
if (auto EC = V.getError())
|
||||
fatal(EC, Prefix);
|
||||
|
||||
12
deps/lld/ELF/SyntheticSections.cpp
vendored
12
deps/lld/ELF/SyntheticSections.cpp
vendored
@ -427,10 +427,11 @@ CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Piece,
|
||||
&Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]);
|
||||
|
||||
// Search for an existing CIE by CIE contents/relocation target pair.
|
||||
CieRecord *Cie = &CieMap[{Piece.data(), Personality}];
|
||||
CieRecord *&Cie = CieMap[{Piece.data(), Personality}];
|
||||
|
||||
// If not found, create a new one.
|
||||
if (Cie->Piece == nullptr) {
|
||||
if (!Cie) {
|
||||
Cie = make<CieRecord>();
|
||||
Cie->Piece = &Piece;
|
||||
Cies.push_back(Cie);
|
||||
}
|
||||
@ -522,9 +523,14 @@ template <class ELFT>
|
||||
static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {
|
||||
memcpy(Buf, D.data(), D.size());
|
||||
|
||||
size_t Aligned = alignTo(D.size(), sizeof(typename ELFT::uint));
|
||||
|
||||
// Zero-clear trailing padding if it exists.
|
||||
memset(Buf + D.size(), 0, Aligned - D.size());
|
||||
|
||||
// Fix the size field. -4 since size does not include the size field itself.
|
||||
const endianness E = ELFT::TargetEndianness;
|
||||
write32<E>(Buf, alignTo(D.size(), sizeof(typename ELFT::uint)) - 4);
|
||||
write32<E>(Buf, Aligned - 4);
|
||||
}
|
||||
|
||||
template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() {
|
||||
|
||||
3
deps/lld/ELF/SyntheticSections.h
vendored
3
deps/lld/ELF/SyntheticSections.h
vendored
@ -103,7 +103,8 @@ private:
|
||||
std::vector<CieRecord *> Cies;
|
||||
|
||||
// CIE records are uniquified by their contents and personality functions.
|
||||
llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord> CieMap;
|
||||
llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord *>
|
||||
CieMap;
|
||||
};
|
||||
|
||||
class GotSection : public SyntheticSection {
|
||||
|
||||
2
deps/lld/include/lld/Driver/Driver.h
vendored
2
deps/lld/include/lld/Driver/Driver.h
vendored
@ -15,7 +15,7 @@
|
||||
|
||||
namespace lld {
|
||||
namespace coff {
|
||||
bool link(llvm::ArrayRef<const char *> Args,
|
||||
bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,
|
||||
llvm::raw_ostream &Diag = llvm::errs());
|
||||
}
|
||||
|
||||
|
||||
@ -621,7 +621,6 @@ void ArchHandler_x86_64::applyFixupFinal(
|
||||
// Fall into llvm_unreachable().
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
|
||||
|
||||
64
deps/lld/test/ELF/eh-frame-padding-no-rosegment.s
vendored
Normal file
64
deps/lld/test/ELF/eh-frame-padding-no-rosegment.s
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
// REQUIRES: x86
|
||||
|
||||
.cfi_startproc
|
||||
.cfi_personality 0x1b, bar
|
||||
.cfi_endproc
|
||||
|
||||
.global bar
|
||||
.hidden bar
|
||||
bar:
|
||||
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
|
||||
// Check the size of the CIE (0x18 + 4) and FDE (0x10 + 4)
|
||||
// RUN: llvm-readobj -s -section-data %t.o | FileCheck --check-prefix=OBJ %s
|
||||
|
||||
// OBJ: Name: .eh_frame
|
||||
// OBJ-NEXT: Type:
|
||||
// OBJ-NEXT: Flags [
|
||||
// OBJ-NEXT: SHF_ALLOC
|
||||
// OBJ-NEXT: ]
|
||||
// OBJ-NEXT: Address:
|
||||
// OBJ-NEXT: Offset:
|
||||
// OBJ-NEXT: Size:
|
||||
// OBJ-NEXT: Link:
|
||||
// OBJ-NEXT: Info:
|
||||
// OBJ-NEXT: AddressAlignment:
|
||||
// OBJ-NEXT: EntrySize:
|
||||
// OBJ-NEXT: SectionData (
|
||||
// OBJ-NEXT: 0000: 18000000 00000000 017A5052 00017810
|
||||
// OBJ-NEXT: 0010: 061B0000 00001B0C 07089001 10000000
|
||||
// OBJ-NEXT: 0020: 20000000 00000000 00000000 00000000
|
||||
// OBJ-NEXT: )
|
||||
|
||||
// RUN: ld.lld %t.o -no-rosegment -o %t -shared
|
||||
|
||||
// Check that .eh_frame is in the same segment as .text
|
||||
// RUN: llvm-readobj -l --elf-output-style=GNU %t | FileCheck --check-prefix=PHDR %s
|
||||
|
||||
// PHDR: Segment Sections
|
||||
// PHDR: .text
|
||||
// PHDR-SAME: .eh_frame
|
||||
|
||||
// Check that the CIE and FDE are padded with 0x00 and not 0xCC when the
|
||||
// .eh_frame section is placed in the executable segment
|
||||
// RUN: llvm-readobj -s -section-data %t | FileCheck %s
|
||||
|
||||
// CHECK: Name: .eh_frame
|
||||
// CHECK-NEXT: Type:
|
||||
// CHECK-NEXT: Flags
|
||||
// CHECK-NEXT: SHF_ALLOC
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address:
|
||||
// CHECK-NEXT: Offset:
|
||||
// CHECK-NEXT: Size:
|
||||
// CHECK-NEXT: Link:
|
||||
// CHECK-NEXT: Info:
|
||||
// CHECK-NEXT: AddressAlignment:
|
||||
// CHECK-NEXT: EntrySize:
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 1C000000 00000000 017A5052 00017810
|
||||
// CHECK-NEXT: 0010: 061BBEFF FFFF1B0C 07089001 00000000
|
||||
// CHECK-NEXT: 0020: 14000000 24000000 A8FFFFFF 00000000
|
||||
// CHECK-NEXT: 0030: 00000000 00000000
|
||||
// CHECK-NEXT: )
|
||||
2
deps/lld/tools/lld/lld.cpp
vendored
2
deps/lld/tools/lld/lld.cpp
vendored
@ -103,7 +103,7 @@ int main(int Argc, const char **Argv) {
|
||||
case Gnu:
|
||||
return !elf::link(Args, true);
|
||||
case WinLink:
|
||||
return !coff::link(Args);
|
||||
return !coff::link(Args, true);
|
||||
case Darwin:
|
||||
return !mach_o::link(Args);
|
||||
default:
|
||||
|
||||
@ -136,7 +136,8 @@
|
||||
<li><a href="#builtin-divFloor">@divFloor</a></li>
|
||||
<li><a href="#builtin-divTrunc">@divTrunc</a></li>
|
||||
<li><a href="#builtin-embedFile">@embedFile</a></li>
|
||||
<li><a href="#builtin-enumTagName">@enumTagName</a></li>
|
||||
<li><a href="#builtin-tagName">@tagName</a></li>
|
||||
<li><a href="#builtin-EnumTagType">@EnumTagType</a></li>
|
||||
<li><a href="#builtin-errorName">@errorName</a></li>
|
||||
<li><a href="#builtin-fence">@fence</a></li>
|
||||
<li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li>
|
||||
@ -2095,30 +2096,38 @@ const Type = enum {
|
||||
NotOk,
|
||||
};
|
||||
|
||||
// Enums are sum types, and can hold more complex data of different types.
|
||||
const ComplexType = enum {
|
||||
Ok: u8,
|
||||
NotOk: void,
|
||||
};
|
||||
|
||||
// Declare a specific instance of the enum variant.
|
||||
const c = ComplexType.Ok { 0 };
|
||||
const c = Type.Ok;
|
||||
|
||||
// The ordinal value of a simple enum with no data members can be
|
||||
// retrieved by a simple cast.
|
||||
// The value starts from 0, counting up for each member.
|
||||
const Value = enum {
|
||||
// If you want access to the ordinal value of an enum, you
|
||||
// can specify the tag type.
|
||||
const Value = enum(u2) {
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
};
|
||||
|
||||
// Now you can cast between u2 and Value.
|
||||
// The ordinal value starts from 0, counting up for each member.
|
||||
test "enum ordinal value" {
|
||||
assert(usize(Value.Zero) == 0);
|
||||
assert(usize(Value.One) == 1);
|
||||
assert(usize(Value.Two) == 2);
|
||||
assert(u2(Value.Zero) == 0);
|
||||
assert(u2(Value.One) == 1);
|
||||
assert(u2(Value.Two) == 2);
|
||||
}
|
||||
|
||||
// Enums can have methods, the same as structs.
|
||||
// You can override the ordinal value for an enum.
|
||||
const Value2 = enum(u32) {
|
||||
Hundred = 100,
|
||||
Thousand = 1000,
|
||||
Million = 1000000,
|
||||
};
|
||||
test "set enum ordinal value" {
|
||||
assert(u32(Value2.Hundred) == 100);
|
||||
assert(u32(Value2.Thousand) == 1000);
|
||||
assert(u32(Value2.Million) == 1000000);
|
||||
}
|
||||
|
||||
// Enums can have methods, the same as structs and unions.
|
||||
// Enum methods are not special, they are only namespaced
|
||||
// functions that you can call with dot syntax.
|
||||
const Suit = enum {
|
||||
@ -2127,26 +2136,120 @@ const Suit = enum {
|
||||
Diamonds,
|
||||
Hearts,
|
||||
|
||||
pub fn ordinal(self: &const Suit) -> u8 {
|
||||
u8(*self)
|
||||
pub fn isClubs(self: Suit) -> bool {
|
||||
return self == Suit.Clubs;
|
||||
}
|
||||
};
|
||||
test "enum method" {
|
||||
const p = Suit.Spades;
|
||||
assert(p.ordinal() == 1);
|
||||
assert(!p.isClubs());
|
||||
}
|
||||
|
||||
// An enum variant of different types can be switched upon.
|
||||
// The associated data can be retrieved using `|...|` syntax.
|
||||
//
|
||||
// A void type is not required on a tag-only member.
|
||||
const Foo = enum {
|
||||
String: []const u8,
|
||||
Number: u64,
|
||||
String,
|
||||
Number,
|
||||
None,
|
||||
};
|
||||
test "enum variant switch" {
|
||||
const p = Foo.Number { 54 };
|
||||
const p = Foo.Number;
|
||||
const what_is_it = switch (p) {
|
||||
Foo.String => "this is a string",
|
||||
Foo.Number => "this is a number",
|
||||
Foo.None => "this is a none",
|
||||
};
|
||||
assert(mem.eql(u8, what_is_it, "this is a number"));
|
||||
}
|
||||
|
||||
// @TagType can be used to access the integer tag type of an enum.
|
||||
const Small = enum {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
};
|
||||
test "@TagType" {
|
||||
assert(@TagType(Small) == u2);
|
||||
}
|
||||
|
||||
// @memberCount tells how many fields an enum has:
|
||||
test "@memberCount" {
|
||||
assert(@memberCount(Small) == 4);
|
||||
}
|
||||
|
||||
// @memberName tells the name of a field in an enum:
|
||||
test "@memberName" {
|
||||
assert(mem.eql(u8, @memberName(Small, 1), "Two"));
|
||||
}
|
||||
|
||||
// @tagName gives a []const u8 representation of an enum value:
|
||||
test "@tagName" {
|
||||
assert(mem.eql(u8, @tagName(Small.Three), "Three"));
|
||||
}</code></pre>
|
||||
<p>TODO extern enum</p>
|
||||
<p>TODO packed enum</p>
|
||||
<pre><code class="sh">$ zig test enum.zig
|
||||
Test 1/8 enum ordinal value...OK
|
||||
Test 2/8 set enum ordinal value...OK
|
||||
Test 3/8 enum method...OK
|
||||
Test 4/8 enum variant switch...OK
|
||||
Test 5/8 @TagType...OK
|
||||
Test 6/8 @memberCount...OK
|
||||
Test 7/8 @memberName...OK
|
||||
Test 8/8 @tagName...OK</code></pre>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li><a href="#builtin-memberName">@memberName</a></li>
|
||||
<li><a href="#builtin-memberCount">@memberCount</a></li>
|
||||
<li><a href="#builtin-tagName">@tagName</a></li>
|
||||
</ul>
|
||||
<h2 id="union">union</h2>
|
||||
<pre><code class="zig">const assert = @import("std").debug.assert;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
// A union has only 1 active field at a time.
|
||||
const Payload = union {
|
||||
Int: i64,
|
||||
Float: f64,
|
||||
Bool: bool,
|
||||
};
|
||||
test "simple union" {
|
||||
var payload = Payload {.Int = 1234};
|
||||
// payload.Float = 12.34; // ERROR! field not active
|
||||
assert(payload.Int == 1234);
|
||||
// You can activate another field by assigning the entire union.
|
||||
payload = Payload {.Float = 12.34};
|
||||
assert(payload.Float == 12.34);
|
||||
}
|
||||
|
||||
// Unions can be given an enum tag type:
|
||||
const ComplexTypeTag = enum { Ok, NotOk };
|
||||
const ComplexType = union(ComplexTypeTag) {
|
||||
Ok: u8,
|
||||
NotOk: void,
|
||||
};
|
||||
|
||||
// Declare a specific instance of the union variant.
|
||||
test "declare union value" {
|
||||
const c = ComplexType { .Ok = 0 };
|
||||
assert(ComplexTypeTag(c) == ComplexTypeTag.Ok);
|
||||
}
|
||||
|
||||
// @TagType can be used to access the enum tag type of a union.
|
||||
test "@TagType" {
|
||||
assert(@TagType(ComplexType) == ComplexTypeTag);
|
||||
}
|
||||
|
||||
// Unions can be made to infer the enum tag type.
|
||||
const Foo = union(enum) {
|
||||
String: []const u8,
|
||||
Number: u64,
|
||||
|
||||
// void can be omitted when inferring enum tag type.
|
||||
None,
|
||||
};
|
||||
test "union variant switch" {
|
||||
const p = Foo { .Number = 54 };
|
||||
const what_is_it = switch (p) {
|
||||
// Capture by reference
|
||||
Foo.String => |*x| {
|
||||
@ -2155,6 +2258,7 @@ test "enum variant switch" {
|
||||
|
||||
// Capture by value
|
||||
Foo.Number => |x| {
|
||||
assert(x == 54);
|
||||
"this is a number"
|
||||
},
|
||||
|
||||
@ -2162,37 +2266,50 @@ test "enum variant switch" {
|
||||
"this is a none"
|
||||
}
|
||||
};
|
||||
assert(mem.eql(u8, what_is_it, "this is a number"));
|
||||
}
|
||||
|
||||
// The @enumTagName and @memberCount builtin functions can be used to
|
||||
// the string representation and number of members respectively.
|
||||
const BuiltinType = enum {
|
||||
A: f32,
|
||||
B: u32,
|
||||
C,
|
||||
// TODO union methods
|
||||
|
||||
|
||||
const Small = union {
|
||||
A: i32,
|
||||
B: bool,
|
||||
C: u8,
|
||||
};
|
||||
|
||||
test "enum builtins" {
|
||||
assert(mem.eql(u8, @enumTagName(BuiltinType.A { 0 }), "A"));
|
||||
assert(mem.eql(u8, @enumTagName(BuiltinType.C), "C"));
|
||||
assert(@memberCount(BuiltinType) == 3);
|
||||
// @memberCount tells how many fields a union has:
|
||||
test "@memberCount" {
|
||||
assert(@memberCount(Small) == 3);
|
||||
}
|
||||
|
||||
// @memberName tells the name of a field in an enum:
|
||||
test "@memberName" {
|
||||
assert(mem.eql(u8, @memberName(Small, 1), "B"));
|
||||
}
|
||||
|
||||
// @tagName gives a []const u8 representation of an enum value,
|
||||
// but only if the union has an enum tag type.
|
||||
const Small2 = union(enum) {
|
||||
A: i32,
|
||||
B: bool,
|
||||
C: u8,
|
||||
};
|
||||
test "@tagName" {
|
||||
assert(mem.eql(u8, @tagName(Small2.C), "C"));
|
||||
}</code></pre>
|
||||
<pre><code class="sh">$ zig test enum.zig
|
||||
Test 1/4 enum ordinal value...OK
|
||||
Test 2/4 enum method...OK
|
||||
Test 3/4 enum variant switch...OK
|
||||
Test 4/4 enum builtins...OK</code></pre>
|
||||
<pre><code class="sh">$ zig test union.zig
|
||||
Test 1/7 simple union...OK
|
||||
Test 2/7 declare union value...OK
|
||||
Test 3/7 @TagType...OK
|
||||
Test 4/7 union variant switch...OK
|
||||
Test 5/7 @memberCount...OK
|
||||
Test 6/7 @memberName...OK
|
||||
Test 7/7 @tagName...OK</code></pre>
|
||||
<p>
|
||||
Enums are generated as a struct with a tag field and union field. Zig
|
||||
Unions with an enum tag are generated as a struct with a tag field and union field. Zig
|
||||
sorts the order of the tag and union field by the largest alignment.
|
||||
</p>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li><a href="#builtin-enumTagName">@enumTagName</a></li>
|
||||
<li><a href="#builtin-memberCount">@memberCount</a></li>
|
||||
</ul>
|
||||
<h2 id="union">union</h2>
|
||||
<p>TODO union documentation</p>
|
||||
<h2 id="switch">switch</h2>
|
||||
<pre><code class="zig">const assert = @import("std").debug.assert;
|
||||
const builtin = @import("builtin");
|
||||
@ -4251,10 +4368,15 @@ test.zig:6:2: error: found compile log statement
|
||||
<ul>
|
||||
<li><a href="#builtin-import">@import</a></li>
|
||||
</ul>
|
||||
<h3 id="builtin-enumTagName">@enumTagName</h3>
|
||||
<pre><code class="zig">@enumTagName(value: var) -> []const u8</code></pre>
|
||||
<h3 id="builtin-tagName">@tagName</h3>
|
||||
<pre><code class="zig">@tagName(value: var) -> []const u8</code></pre>
|
||||
<p>
|
||||
Converts an enum tag name to a slice of bytes.
|
||||
Converts an enum value or union value to a slice of bytes representing the name.
|
||||
</p>
|
||||
<h3 id="builtin-EnumTagType">@EnumTagType</h3>
|
||||
<pre><code class="zig">@EnumTagType(T: type) -> type</code></pre>
|
||||
<p>
|
||||
Returns the integer type that is used to store the enumeration value.
|
||||
</p>
|
||||
<h3 id="builtin-errorName">@errorName</h3>
|
||||
<pre><code class="zig">@errorName(err: error) -> []u8</code></pre>
|
||||
@ -5703,7 +5825,7 @@ VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" Typ
|
||||
|
||||
ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
|
||||
|
||||
ContainerField = Symbol option(":" Expression) ","
|
||||
ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","
|
||||
|
||||
UseDecl = "use" Expression ";"
|
||||
|
||||
@ -5837,7 +5959,9 @@ GroupedExpression = "(" Expression ")"
|
||||
|
||||
KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"
|
||||
|
||||
ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"</code></pre>
|
||||
ContainerDecl = option("extern" | "packed")
|
||||
("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))
|
||||
"{" many(ContainerMember) "}"</code></pre>
|
||||
<h2 id="zen">Zen</h2>
|
||||
<ul>
|
||||
<li>Communicate intent precisely.</li>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const io = std.io;
|
||||
const fmt = std.fmt;
|
||||
@ -15,7 +16,7 @@ pub fn main() -> %void {
|
||||
|
||||
var seed_bytes: [@sizeOf(usize)]u8 = undefined;
|
||||
%%os.getRandomBytes(seed_bytes[0..]);
|
||||
const seed = std.mem.readInt(seed_bytes, usize, true);
|
||||
const seed = std.mem.readInt(seed_bytes, usize, builtin.Endian.Big);
|
||||
var rand = Rand.init(seed);
|
||||
|
||||
const answer = rand.range(u8, 0, 100) + 1;
|
||||
|
||||
@ -97,18 +97,13 @@ struct ConstParent {
|
||||
} data;
|
||||
};
|
||||
|
||||
struct ConstEnumValue {
|
||||
uint64_t tag;
|
||||
ConstExprValue *payload;
|
||||
};
|
||||
|
||||
struct ConstStructValue {
|
||||
ConstExprValue *fields;
|
||||
ConstParent parent;
|
||||
};
|
||||
|
||||
struct ConstUnionValue {
|
||||
uint64_t tag;
|
||||
BigInt tag;
|
||||
ConstExprValue *payload;
|
||||
ConstParent parent;
|
||||
};
|
||||
@ -249,7 +244,7 @@ struct ConstExprValue {
|
||||
ConstExprValue *x_maybe;
|
||||
ConstErrValue x_err_union;
|
||||
ErrorTableEntry *x_pure_err;
|
||||
ConstEnumValue x_enum;
|
||||
BigInt x_enum_tag;
|
||||
ConstStructValue x_struct;
|
||||
ConstUnionValue x_union;
|
||||
ConstArrayValue x_array;
|
||||
@ -345,15 +340,14 @@ struct TldCompTime {
|
||||
|
||||
struct TypeEnumField {
|
||||
Buf *name;
|
||||
TypeTableEntry *type_entry;
|
||||
uint32_t value;
|
||||
uint32_t gen_index;
|
||||
BigInt value;
|
||||
uint32_t decl_index;
|
||||
};
|
||||
|
||||
struct TypeUnionField {
|
||||
Buf *name;
|
||||
TypeEnumField *enum_field;
|
||||
TypeTableEntry *type_entry;
|
||||
uint32_t value;
|
||||
uint32_t gen_index;
|
||||
};
|
||||
|
||||
@ -773,13 +767,15 @@ struct AstNodeContainerDecl {
|
||||
ZigList<AstNode *> fields;
|
||||
ZigList<AstNode *> decls;
|
||||
ContainerLayout layout;
|
||||
AstNode *init_arg_expr; // enum(T) or struct(endianness)
|
||||
AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T))
|
||||
bool auto_enum; // union(enum)
|
||||
};
|
||||
|
||||
struct AstNodeStructField {
|
||||
VisibMod visib_mod;
|
||||
Buf *name;
|
||||
AstNode *type;
|
||||
AstNode *value;
|
||||
};
|
||||
|
||||
struct AstNodeStringLiteral {
|
||||
@ -1009,12 +1005,9 @@ struct TypeTableEntryEnum {
|
||||
AstNode *decl_node;
|
||||
ContainerLayout layout;
|
||||
uint32_t src_field_count;
|
||||
// number of fields in the union. 0 if enum with no payload
|
||||
uint32_t gen_field_count;
|
||||
TypeEnumField *fields;
|
||||
bool is_invalid; // true if any fields are invalid
|
||||
TypeTableEntry *tag_type;
|
||||
LLVMTypeRef union_type_ref;
|
||||
TypeTableEntry *tag_int_type;
|
||||
|
||||
ScopeDecls *decls_scope;
|
||||
|
||||
@ -1026,18 +1019,7 @@ struct TypeTableEntryEnum {
|
||||
|
||||
bool zero_bits_loop_flag;
|
||||
bool zero_bits_known;
|
||||
uint32_t abi_alignment; // also figured out with zero_bits pass
|
||||
|
||||
size_t gen_union_index;
|
||||
size_t gen_tag_index;
|
||||
|
||||
uint32_t union_size_bytes;
|
||||
TypeTableEntry *most_aligned_union_member;
|
||||
};
|
||||
|
||||
struct TypeTableEntryEnumTag {
|
||||
TypeTableEntry *enum_type;
|
||||
TypeTableEntry *int_type;
|
||||
bool generate_name_table;
|
||||
LLVMValueRef name_table;
|
||||
};
|
||||
@ -1052,7 +1034,7 @@ struct TypeTableEntryUnion {
|
||||
uint32_t gen_field_count;
|
||||
TypeUnionField *fields;
|
||||
bool is_invalid; // true if any fields are invalid
|
||||
TypeTableEntry *tag_type;
|
||||
TypeTableEntry *tag_type; // always an enum or null
|
||||
LLVMTypeRef union_type_ref;
|
||||
|
||||
ScopeDecls *decls_scope;
|
||||
@ -1117,7 +1099,6 @@ enum TypeTableEntryId {
|
||||
TypeTableEntryIdErrorUnion,
|
||||
TypeTableEntryIdPureError,
|
||||
TypeTableEntryIdEnum,
|
||||
TypeTableEntryIdEnumTag,
|
||||
TypeTableEntryIdUnion,
|
||||
TypeTableEntryIdFn,
|
||||
TypeTableEntryIdNamespace,
|
||||
@ -1146,7 +1127,6 @@ struct TypeTableEntry {
|
||||
TypeTableEntryMaybe maybe;
|
||||
TypeTableEntryError error;
|
||||
TypeTableEntryEnum enumeration;
|
||||
TypeTableEntryEnumTag enum_tag;
|
||||
TypeTableEntryUnion unionation;
|
||||
TypeTableEntryFn fn;
|
||||
TypeTableEntryBoundFn bound_fn;
|
||||
@ -1285,7 +1265,8 @@ enum BuiltinFnId {
|
||||
BuiltinFnIdBitCast,
|
||||
BuiltinFnIdIntToPtr,
|
||||
BuiltinFnIdPtrToInt,
|
||||
BuiltinFnIdEnumTagName,
|
||||
BuiltinFnIdTagName,
|
||||
BuiltinFnIdTagType,
|
||||
BuiltinFnIdFieldParentPtr,
|
||||
BuiltinFnIdOffsetOf,
|
||||
BuiltinFnIdInlineCall,
|
||||
@ -1829,7 +1810,6 @@ enum IrInstructionId {
|
||||
IrInstructionIdStorePtr,
|
||||
IrInstructionIdFieldPtr,
|
||||
IrInstructionIdStructFieldPtr,
|
||||
IrInstructionIdEnumFieldPtr,
|
||||
IrInstructionIdUnionFieldPtr,
|
||||
IrInstructionIdElemPtr,
|
||||
IrInstructionIdVarPtr,
|
||||
@ -1854,7 +1834,7 @@ enum IrInstructionId {
|
||||
IrInstructionIdTestNonNull,
|
||||
IrInstructionIdUnwrapMaybe,
|
||||
IrInstructionIdMaybeWrap,
|
||||
IrInstructionIdEnumTag,
|
||||
IrInstructionIdUnionTag,
|
||||
IrInstructionIdClz,
|
||||
IrInstructionIdCtz,
|
||||
IrInstructionIdImport,
|
||||
@ -1893,7 +1873,6 @@ enum IrInstructionId {
|
||||
IrInstructionIdErrWrapPayload,
|
||||
IrInstructionIdFnProto,
|
||||
IrInstructionIdTestComptime,
|
||||
IrInstructionIdInitEnum,
|
||||
IrInstructionIdPtrCast,
|
||||
IrInstructionIdBitCast,
|
||||
IrInstructionIdWidenOrShorten,
|
||||
@ -1910,7 +1889,8 @@ enum IrInstructionId {
|
||||
IrInstructionIdSetGlobalLinkage,
|
||||
IrInstructionIdDeclRef,
|
||||
IrInstructionIdPanic,
|
||||
IrInstructionIdEnumTagName,
|
||||
IrInstructionIdTagName,
|
||||
IrInstructionIdTagType,
|
||||
IrInstructionIdFieldParentPtr,
|
||||
IrInstructionIdOffsetOf,
|
||||
IrInstructionIdTypeId,
|
||||
@ -2088,14 +2068,6 @@ struct IrInstructionStructFieldPtr {
|
||||
bool is_const;
|
||||
};
|
||||
|
||||
struct IrInstructionEnumFieldPtr {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *enum_ptr;
|
||||
TypeEnumField *field;
|
||||
bool is_const;
|
||||
};
|
||||
|
||||
struct IrInstructionUnionFieldPtr {
|
||||
IrInstruction base;
|
||||
|
||||
@ -2299,7 +2271,7 @@ struct IrInstructionClz {
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionEnumTag {
|
||||
struct IrInstructionUnionTag {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
@ -2569,15 +2541,6 @@ struct IrInstructionTestComptime {
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionInitEnum {
|
||||
IrInstruction base;
|
||||
|
||||
TypeTableEntry *enum_type;
|
||||
TypeEnumField *field;
|
||||
IrInstruction *init_value;
|
||||
LLVMValueRef tmp_ptr;
|
||||
};
|
||||
|
||||
struct IrInstructionPtrCast {
|
||||
IrInstruction base;
|
||||
|
||||
@ -2689,7 +2652,13 @@ struct IrInstructionPanic {
|
||||
IrInstruction *msg;
|
||||
};
|
||||
|
||||
struct IrInstructionEnumTagName {
|
||||
struct IrInstructionTagName {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *target;
|
||||
};
|
||||
|
||||
struct IrInstructionTagType {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *target;
|
||||
|
||||
818
src/analyze.cpp
818
src/analyze.cpp
File diff suppressed because it is too large
Load Diff
@ -64,6 +64,9 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
|
||||
ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
|
||||
TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
|
||||
TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
|
||||
TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);
|
||||
TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag);
|
||||
|
||||
bool is_container_ref(TypeTableEntry *type_entry);
|
||||
void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
|
||||
void scan_import(CodeGen *g, ImportTableEntry *import);
|
||||
@ -109,6 +112,9 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
|
||||
void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);
|
||||
ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);
|
||||
|
||||
void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint);
|
||||
ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint);
|
||||
|
||||
void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative);
|
||||
ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative);
|
||||
|
||||
@ -121,8 +127,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x);
|
||||
void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);
|
||||
ConstExprValue *create_const_float(TypeTableEntry *type, double value);
|
||||
|
||||
void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag);
|
||||
ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag);
|
||||
void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);
|
||||
ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag);
|
||||
|
||||
void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);
|
||||
ConstExprValue *create_const_bool(CodeGen *g, bool value);
|
||||
@ -158,7 +164,6 @@ ConstExprValue *create_const_vals(size_t count);
|
||||
|
||||
TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
|
||||
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
|
||||
TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type);
|
||||
void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
|
||||
void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
|
||||
|
||||
|
||||
@ -660,7 +660,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
{
|
||||
const char *layout_str = layout_string(node->data.container_decl.layout);
|
||||
const char *container_str = container_string(node->data.container_decl.kind);
|
||||
fprintf(ar->f, "%s%s {\n", layout_str, container_str);
|
||||
fprintf(ar->f, "%s%s", layout_str, container_str);
|
||||
if (node->data.container_decl.auto_enum) {
|
||||
fprintf(ar->f, "(enum");
|
||||
}
|
||||
if (node->data.container_decl.init_arg_expr != nullptr) {
|
||||
fprintf(ar->f, "(");
|
||||
render_node_grouped(ar, node->data.container_decl.init_arg_expr);
|
||||
fprintf(ar->f, ")");
|
||||
}
|
||||
if (node->data.container_decl.auto_enum) {
|
||||
fprintf(ar->f, ")");
|
||||
}
|
||||
|
||||
fprintf(ar->f, " {\n");
|
||||
ar->indent += ar->indent_size;
|
||||
for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) {
|
||||
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) {
|
||||
fprintf(ar->f, ": ");
|
||||
render_node_grouped(ar, field_node->data.struct_field.type);
|
||||
}
|
||||
if (field_node->data.struct_field.value != nullptr) {
|
||||
fprintf(ar->f, "= ");
|
||||
render_node_grouped(ar, field_node->data.struct_field.value);
|
||||
}
|
||||
fprintf(ar->f, ",\n");
|
||||
}
|
||||
|
||||
|
||||
@ -1224,3 +1224,35 @@ Cmp bigint_cmp_zero(const BigInt *op) {
|
||||
}
|
||||
return op->is_negative ? CmpLT : CmpGT;
|
||||
}
|
||||
|
||||
uint32_t bigint_hash(BigInt x) {
|
||||
if (x.digit_count == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return bigint_ptr(&x)[0];
|
||||
}
|
||||
}
|
||||
|
||||
bool bigint_eql(BigInt a, BigInt b) {
|
||||
return bigint_cmp(&a, &b) == CmpEQ;
|
||||
}
|
||||
|
||||
void bigint_incr(BigInt *x) {
|
||||
if (x->digit_count == 0) {
|
||||
bigint_init_unsigned(x, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (x->digit_count == 1 && x->data.digit != UINT64_MAX) {
|
||||
x->data.digit += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
BigInt copy;
|
||||
bigint_init_bigint(©, x);
|
||||
|
||||
BigInt one;
|
||||
bigint_init_unsigned(&one, 1);
|
||||
|
||||
bigint_add(x, ©, &one);
|
||||
}
|
||||
|
||||
@ -88,6 +88,11 @@ size_t bigint_bits_needed(const BigInt *op);
|
||||
// convenience functions
|
||||
Cmp bigint_cmp_zero(const BigInt *op);
|
||||
|
||||
void bigint_incr(BigInt *value);
|
||||
|
||||
bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result);
|
||||
|
||||
uint32_t bigint_hash(BigInt x);
|
||||
bool bigint_eql(BigInt a, BigInt b);
|
||||
|
||||
#endif
|
||||
|
||||
291
src/codegen.cpp
291
src/codegen.cpp
@ -1362,8 +1362,12 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) {
|
||||
if (bigint->digit_count == 0) {
|
||||
return LLVMConstNull(type_ref);
|
||||
}
|
||||
LLVMValueRef unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref,
|
||||
bigint->digit_count, bigint_ptr(bigint));
|
||||
LLVMValueRef unsigned_val;
|
||||
if (bigint->digit_count == 1) {
|
||||
unsigned_val = LLVMConstInt(type_ref, bigint_ptr(bigint)[0], false);
|
||||
} else {
|
||||
unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref, bigint->digit_count, bigint_ptr(bigint));
|
||||
}
|
||||
if (bigint->is_negative) {
|
||||
return LLVMConstNeg(unsigned_val);
|
||||
} else {
|
||||
@ -1627,12 +1631,8 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed);
|
||||
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdEnum) {
|
||||
if (type_entry->data.enumeration.gen_field_count == 0) {
|
||||
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
|
||||
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
|
||||
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdPureError ||
|
||||
type_entry->id == TypeTableEntryIdPointer ||
|
||||
type_entry->id == TypeTableEntryIdBool)
|
||||
@ -1916,9 +1916,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa
|
||||
// enum_tag to the underlying int type
|
||||
TypeTableEntry *int_type;
|
||||
if (actual_type->id == TypeTableEntryIdEnum) {
|
||||
TypeTableEntry *tag_type = actual_type->data.enumeration.tag_type;
|
||||
assert(tag_type->id == TypeTableEntryIdEnumTag);
|
||||
int_type = tag_type->data.enum_tag.int_type;
|
||||
int_type = actual_type->data.enumeration.tag_int_type;
|
||||
} else {
|
||||
int_type = actual_type;
|
||||
}
|
||||
@ -1942,19 +1940,11 @@ static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, I
|
||||
static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
assert(wanted_type->id == TypeTableEntryIdEnum);
|
||||
TypeTableEntry *tag_type = wanted_type->data.enumeration.tag_type;
|
||||
TypeTableEntry *wanted_int_type;
|
||||
if (tag_type->id == TypeTableEntryIdEnumTag) {
|
||||
wanted_int_type = tag_type->data.enum_tag.int_type;
|
||||
} else if (tag_type->id == TypeTableEntryIdInt) {
|
||||
wanted_int_type = tag_type;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
TypeTableEntry *tag_int_type = wanted_type->data.enumeration.tag_int_type;
|
||||
|
||||
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
|
||||
return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base),
|
||||
instruction->target->value.type, wanted_int_type, target_val);
|
||||
instruction->target->value.type, tag_int_type, target_val);
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) {
|
||||
@ -2374,27 +2364,6 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
|
||||
return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_enum_field_ptr(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionEnumFieldPtr *instruction)
|
||||
{
|
||||
TypeTableEntry *enum_ptr_type = instruction->enum_ptr->value.type;
|
||||
assert(enum_ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *enum_type = enum_ptr_type->data.pointer.child_type;
|
||||
assert(enum_type->id == TypeTableEntryIdEnum);
|
||||
|
||||
TypeEnumField *field = instruction->field;
|
||||
|
||||
if (!type_has_bits(field->type_entry))
|
||||
return nullptr;
|
||||
|
||||
LLVMValueRef enum_ptr = ir_llvm_value(g, instruction->enum_ptr);
|
||||
LLVMTypeRef field_type_ref = LLVMPointerType(field->type_entry->type_ref, 0);
|
||||
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, enum_ptr, enum_type->data.enumeration.gen_union_index, "");
|
||||
LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
|
||||
|
||||
return bitcasted_union_field_ptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnionFieldPtr *instruction)
|
||||
{
|
||||
@ -2420,9 +2389,10 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
|
||||
if (ir_want_debug_safety(g, &instruction->base)) {
|
||||
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
|
||||
LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, "");
|
||||
LLVMValueRef expected_tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref,
|
||||
field->value, false);
|
||||
|
||||
|
||||
LLVMValueRef expected_tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,
|
||||
&field->enum_field->value);
|
||||
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk");
|
||||
LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail");
|
||||
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
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionEnumTagName *instruction)
|
||||
IrInstructionTagName *instruction)
|
||||
{
|
||||
TypeTableEntry *enum_tag_type = instruction->target->value.type;
|
||||
assert(enum_tag_type->data.enum_tag.generate_name_table);
|
||||
TypeTableEntry *enum_type = instruction->target->value.type;
|
||||
assert(enum_type->id == TypeTableEntryIdEnum);
|
||||
assert(enum_type->data.enumeration.generate_name_table);
|
||||
|
||||
TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type;
|
||||
LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target);
|
||||
if (ir_want_debug_safety(g, &instruction->base)) {
|
||||
TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type;
|
||||
size_t field_count = enum_type->data.enumeration.src_field_count;
|
||||
|
||||
// if the field_count can't fit in the bits of the enum_tag_type, then it can't possibly
|
||||
// if the field_count can't fit in the bits of the enum_type, then it can't possibly
|
||||
// be the wrong value
|
||||
BigInt field_bi;
|
||||
bigint_init_unsigned(&field_bi, field_count);
|
||||
TypeTableEntry *tag_int_type = enum_tag_type->data.enum_tag.int_type;
|
||||
if (bigint_fits_in_bits(&field_bi, tag_int_type->data.integral.bit_count, false)) {
|
||||
LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(enum_tag_value), field_count, false);
|
||||
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
|
||||
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(g->builtin_types.entry_usize->type_ref),
|
||||
gen_widen_or_shorten(g, false, enum_tag_type->data.enum_tag.int_type,
|
||||
gen_widen_or_shorten(g, false, tag_int_type,
|
||||
g->builtin_types.entry_usize, enum_tag_value),
|
||||
};
|
||||
return LLVMBuildInBoundsGEP(g->builder, enum_tag_type->data.enum_tag.name_table, indices, 2, "");
|
||||
return LLVMBuildInBoundsGEP(g->builder, enum_type->data.enumeration.name_table, indices, 2, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable,
|
||||
@ -3347,48 +3317,24 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
|
||||
return instruction->tmp_ptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrInstructionEnumTag *instruction) {
|
||||
TypeTableEntry *enum_type = instruction->value->value.type;
|
||||
TypeTableEntry *tag_type = enum_type->data.enumeration.tag_type;
|
||||
static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {
|
||||
TypeTableEntry *union_type = instruction->value->value.type;
|
||||
assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
|
||||
|
||||
TypeTableEntry *tag_type = union_type->data.unionation.tag_type;
|
||||
if (!type_has_bits(tag_type))
|
||||
return nullptr;
|
||||
|
||||
LLVMValueRef enum_val = ir_llvm_value(g, instruction->value);
|
||||
if (enum_type->data.enumeration.gen_field_count == 0)
|
||||
return enum_val;
|
||||
LLVMValueRef union_val = ir_llvm_value(g, instruction->value);
|
||||
if (union_type->data.unionation.gen_field_count == 0)
|
||||
return union_val;
|
||||
|
||||
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, enum_val, enum_type->data.enumeration.gen_tag_index, "");
|
||||
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_val,
|
||||
union_type->data.unionation.gen_tag_index, "");
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(g, tag_type, false);
|
||||
return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) {
|
||||
TypeTableEntry *enum_type = instruction->enum_type;
|
||||
uint32_t value = instruction->field->value;
|
||||
LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;
|
||||
LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false);
|
||||
|
||||
if (enum_type->data.enumeration.gen_field_count == 0)
|
||||
return tag_value;
|
||||
|
||||
LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;
|
||||
|
||||
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_type->data.enumeration.gen_tag_index, "");
|
||||
gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
|
||||
|
||||
TypeTableEntry *union_val_type = instruction->field->type_entry;
|
||||
if (type_has_bits(union_val_type)) {
|
||||
LLVMValueRef new_union_val = ir_llvm_value(g, instruction->init_value);
|
||||
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_type->data.enumeration.gen_union_index, "");
|
||||
LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
|
||||
LLVMPointerType(union_val_type->type_ref, 0), "");
|
||||
|
||||
gen_assign_raw(g, bitcasted_union_field_ptr, get_pointer_to_type(g, union_val_type, false), new_union_val);
|
||||
}
|
||||
|
||||
return tmp_struct_ptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {
|
||||
for (size_t i = 0; i < instruction->field_count; i += 1) {
|
||||
IrInstructionStructInitField *field = &instruction->fields[i];
|
||||
@ -3429,8 +3375,9 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
|
||||
if (union_type->data.unionation.gen_tag_index != SIZE_MAX) {
|
||||
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
|
||||
union_type->data.unionation.gen_tag_index, "");
|
||||
LLVMValueRef tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref,
|
||||
type_union_field->value, false);
|
||||
|
||||
LLVMValueRef tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,
|
||||
&type_union_field->enum_field->value);
|
||||
gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
|
||||
|
||||
uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
|
||||
@ -3537,6 +3484,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
case IrInstructionIdOpaqueType:
|
||||
case IrInstructionIdSetAlignStack:
|
||||
case IrInstructionIdArgType:
|
||||
case IrInstructionIdTagType:
|
||||
zig_unreachable();
|
||||
case IrInstructionIdReturn:
|
||||
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
|
||||
@ -3566,8 +3514,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_call(g, executable, (IrInstructionCall *)instruction);
|
||||
case IrInstructionIdStructFieldPtr:
|
||||
return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
|
||||
case IrInstructionIdEnumFieldPtr:
|
||||
return ir_render_enum_field_ptr(g, executable, (IrInstructionEnumFieldPtr *)instruction);
|
||||
case IrInstructionIdUnionFieldPtr:
|
||||
return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction);
|
||||
case IrInstructionIdAsm:
|
||||
@ -3622,10 +3568,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);
|
||||
case IrInstructionIdErrWrapPayload:
|
||||
return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
|
||||
case IrInstructionIdEnumTag:
|
||||
return ir_render_enum_tag(g, executable, (IrInstructionEnumTag *)instruction);
|
||||
case IrInstructionIdInitEnum:
|
||||
return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction);
|
||||
case IrInstructionIdUnionTag:
|
||||
return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);
|
||||
case IrInstructionIdStructInit:
|
||||
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
|
||||
case IrInstructionIdUnionInit:
|
||||
@ -3650,8 +3594,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
|
||||
case IrInstructionIdPanic:
|
||||
return ir_render_panic(g, executable, (IrInstructionPanic *)instruction);
|
||||
case IrInstructionIdEnumTagName:
|
||||
return ir_render_enum_tag_name(g, executable, (IrInstructionEnumTagName *)instruction);
|
||||
case IrInstructionIdTagName:
|
||||
return ir_render_enum_tag_name(g, executable, (IrInstructionTagName *)instruction);
|
||||
case IrInstructionIdFieldParentPtr:
|
||||
return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction);
|
||||
case IrInstructionIdAlignCast:
|
||||
@ -3761,8 +3705,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -3772,6 +3714,12 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdBool:
|
||||
return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);
|
||||
case TypeTableEntryIdEnum:
|
||||
{
|
||||
assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr);
|
||||
LLVMValueRef int_val = gen_const_val(g, const_val);
|
||||
return LLVMConstZExt(int_val, big_int_type_ref);
|
||||
}
|
||||
case TypeTableEntryIdInt:
|
||||
{
|
||||
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
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -3838,7 +3787,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
|
||||
case TypeTableEntryIdPureError:
|
||||
assert(const_val->data.x_pure_err);
|
||||
@ -4001,37 +3949,52 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
ConstExprValue *payload_value = const_val->data.x_union.payload;
|
||||
assert(payload_value != nullptr);
|
||||
|
||||
if (!type_has_bits(payload_value->type)) {
|
||||
return LLVMGetUndef(union_type_ref);
|
||||
}
|
||||
|
||||
uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref);
|
||||
uint64_t pad_bytes = type_entry->data.unionation.union_size_bytes - field_type_bytes;
|
||||
LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value);
|
||||
bool make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) ||
|
||||
payload_value->type != type_entry->data.unionation.most_aligned_union_member;
|
||||
|
||||
LLVMValueRef union_value_ref;
|
||||
{
|
||||
if (pad_bytes == 0) {
|
||||
union_value_ref = correctly_typed_value;
|
||||
if (type_entry->data.unionation.gen_field_count == 0) {
|
||||
if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {
|
||||
return nullptr;
|
||||
} else {
|
||||
LLVMValueRef fields[2];
|
||||
fields[0] = correctly_typed_value;
|
||||
fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes));
|
||||
if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) {
|
||||
union_value_ref = LLVMConstStruct(fields, 2, false);
|
||||
} else {
|
||||
union_value_ref = LLVMConstNamedStruct(union_type_ref, fields, 2);
|
||||
}
|
||||
return bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
|
||||
&const_val->data.x_union.tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {
|
||||
return union_value_ref;
|
||||
LLVMValueRef union_value_ref;
|
||||
bool make_unnamed_struct;
|
||||
if (!type_has_bits(payload_value->type)) {
|
||||
if (type_entry->data.unionation.gen_tag_index == SIZE_MAX)
|
||||
return LLVMGetUndef(type_entry->type_ref);
|
||||
|
||||
union_value_ref = LLVMGetUndef(type_entry->data.unionation.most_aligned_union_member->type_ref);
|
||||
make_unnamed_struct = false;
|
||||
} else {
|
||||
uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref);
|
||||
uint64_t pad_bytes = type_entry->data.unionation.union_size_bytes - field_type_bytes;
|
||||
LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value);
|
||||
make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) ||
|
||||
payload_value->type != type_entry->data.unionation.most_aligned_union_member;
|
||||
|
||||
{
|
||||
if (pad_bytes == 0) {
|
||||
union_value_ref = correctly_typed_value;
|
||||
} else {
|
||||
LLVMValueRef fields[2];
|
||||
fields[0] = correctly_typed_value;
|
||||
fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes));
|
||||
if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) {
|
||||
union_value_ref = LLVMConstStruct(fields, 2, false);
|
||||
} else {
|
||||
union_value_ref = LLVMConstNamedStruct(union_type_ref, fields, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {
|
||||
return union_value_ref;
|
||||
}
|
||||
}
|
||||
|
||||
LLVMValueRef tag_value = LLVMConstInt(type_entry->data.unionation.tag_type->type_ref, const_val->data.x_union.tag, false);
|
||||
LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
|
||||
&const_val->data.x_union.tag);
|
||||
|
||||
LLVMValueRef fields[2];
|
||||
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) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case TypeTableEntryIdEnum:
|
||||
{
|
||||
LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref;
|
||||
LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false);
|
||||
if (type_entry->data.enumeration.gen_field_count == 0) {
|
||||
return tag_value;
|
||||
} else {
|
||||
LLVMTypeRef union_type_ref = type_entry->data.enumeration.union_type_ref;
|
||||
TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag];
|
||||
assert(enum_field->value == const_val->data.x_enum.tag);
|
||||
LLVMValueRef union_value;
|
||||
|
||||
bool make_unnamed_struct;
|
||||
|
||||
if (type_has_bits(enum_field->type_entry)) {
|
||||
uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref,
|
||||
enum_field->type_entry->type_ref);
|
||||
uint64_t pad_bytes = type_entry->data.enumeration.union_size_bytes - field_type_bytes;
|
||||
|
||||
ConstExprValue *payload_value = const_val->data.x_enum.payload;
|
||||
LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value);
|
||||
|
||||
make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) ||
|
||||
payload_value->type != type_entry->data.enumeration.most_aligned_union_member;
|
||||
|
||||
if (pad_bytes == 0) {
|
||||
union_value = correctly_typed_value;
|
||||
} else {
|
||||
LLVMValueRef fields[] = {
|
||||
correctly_typed_value,
|
||||
LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes)),
|
||||
};
|
||||
union_value = LLVMConstStruct(fields, 2, false);
|
||||
}
|
||||
} else {
|
||||
make_unnamed_struct = false;
|
||||
union_value = LLVMGetUndef(union_type_ref);
|
||||
}
|
||||
LLVMValueRef fields[2];
|
||||
fields[type_entry->data.enumeration.gen_tag_index] = tag_value;
|
||||
fields[type_entry->data.enumeration.gen_union_index] = union_value;
|
||||
|
||||
if (make_unnamed_struct) {
|
||||
return LLVMConstStruct(fields, 2, false);
|
||||
} else {
|
||||
return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag);
|
||||
case TypeTableEntryIdFn:
|
||||
return fn_llvm_value(g, const_val->data.x_fn.fn_entry);
|
||||
case TypeTableEntryIdPointer:
|
||||
@ -4303,9 +4220,8 @@ static void generate_enum_name_tables(CodeGen *g) {
|
||||
|
||||
|
||||
for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) {
|
||||
TypeTableEntry *enum_tag_type = g->name_table_enums.at(enum_i);
|
||||
assert(enum_tag_type->id == TypeTableEntryIdEnumTag);
|
||||
TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type;
|
||||
TypeTableEntry *enum_type = g->name_table_enums.at(enum_i);
|
||||
assert(enum_type->id == TypeTableEntryIdEnum);
|
||||
|
||||
size_t field_count = enum_type->data.enumeration.src_field_count;
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(field_count);
|
||||
@ -4336,7 +4252,7 @@ static void generate_enum_name_tables(CodeGen *g) {
|
||||
LLVMSetGlobalConstant(name_table, true);
|
||||
LLVMSetUnnamedAddr(name_table, true);
|
||||
LLVMSetAlignment(name_table, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(name_table_init)));
|
||||
enum_tag_type->data.enum_tag.name_table = name_table;
|
||||
enum_type->data.enumeration.name_table = name_table;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4540,9 +4456,6 @@ static void do_code_gen(CodeGen *g) {
|
||||
} else if (instruction->id == IrInstructionIdErrWrapCode) {
|
||||
IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
|
||||
slot = &err_wrap_code_instruction->tmp_ptr;
|
||||
} else if (instruction->id == IrInstructionIdInitEnum) {
|
||||
IrInstructionInitEnum *init_enum_instruction = (IrInstructionInitEnum *)instruction;
|
||||
slot = &init_enum_instruction->tmp_ptr;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -5039,7 +4952,7 @@ static void define_builtin_fns(CodeGen *g) {
|
||||
create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
|
||||
create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
|
||||
create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);
|
||||
@ -5049,7 +4962,8 @@ static void define_builtin_fns(CodeGen *g) {
|
||||
create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdTagName, "tagName", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdTagType, "TagType", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3);
|
||||
create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdDivExact, "divExact", 2);
|
||||
@ -5215,7 +5129,19 @@ static void define_builtin_compile_vars(CodeGen *g) {
|
||||
assert(FloatModeOptimized == 0);
|
||||
assert(FloatModeStrict == 1);
|
||||
}
|
||||
buf_appendf(contents, "pub const is_big_endian = %s;\n", bool_to_str(g->is_big_endian));
|
||||
{
|
||||
buf_appendf(contents,
|
||||
"pub const Endian = enum {\n"
|
||||
" Big,\n"
|
||||
" Little,\n"
|
||||
"};\n\n");
|
||||
assert(FloatModeOptimized == 0);
|
||||
assert(FloatModeStrict == 1);
|
||||
}
|
||||
{
|
||||
const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little";
|
||||
buf_appendf(contents, "pub const endian = %s;\n", endian_str);
|
||||
}
|
||||
buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
|
||||
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
|
||||
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) {
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
zig_panic("TODO implement get_c_type for more types");
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
|
||||
@ -24,20 +24,20 @@ static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type)
|
||||
bool is_tty = os_stderr_tty();
|
||||
if (color == ErrColorOn || (color == ErrColorAuto && is_tty)) {
|
||||
if (err_type == ErrTypeError) {
|
||||
os_stderr_set_color(TermColorWhite);
|
||||
os_stderr_set_color(TermColorBold);
|
||||
fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col);
|
||||
os_stderr_set_color(TermColorRed);
|
||||
fprintf(stderr, "error:");
|
||||
os_stderr_set_color(TermColorWhite);
|
||||
os_stderr_set_color(TermColorBold);
|
||||
fprintf(stderr, " %s", text);
|
||||
os_stderr_set_color(TermColorReset);
|
||||
fprintf(stderr, "\n");
|
||||
} else if (err_type == ErrTypeNote) {
|
||||
os_stderr_set_color(TermColorWhite);
|
||||
os_stderr_set_color(TermColorBold);
|
||||
fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col);
|
||||
os_stderr_set_color(TermColorCyan);
|
||||
fprintf(stderr, "note:");
|
||||
os_stderr_set_color(TermColorWhite);
|
||||
os_stderr_set_color(TermColorBold);
|
||||
fprintf(stderr, " %s", text);
|
||||
os_stderr_set_color(TermColorReset);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
@ -26,6 +26,7 @@ const char *err_str(int err) {
|
||||
case ErrorExactDivRemainder: return "exact division had a remainder";
|
||||
case ErrorNegativeDenominator: return "negative denominator";
|
||||
case ErrorShiftedOutOneBits: return "exact shift shifted out one bits";
|
||||
case ErrorCCompileErrors: return "C compile errors";
|
||||
}
|
||||
return "(invalid error)";
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ enum Error {
|
||||
ErrorExactDivRemainder,
|
||||
ErrorNegativeDenominator,
|
||||
ErrorShiftedOutOneBits,
|
||||
ErrorCCompileErrors,
|
||||
};
|
||||
|
||||
const char *err_str(int err);
|
||||
|
||||
641
src/ir.cpp
641
src/ir.cpp
File diff suppressed because it is too large
Load Diff
@ -291,7 +291,7 @@ static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruct
|
||||
}
|
||||
|
||||
static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {
|
||||
Buf *field_name = instruction->field->name;
|
||||
Buf *field_name = instruction->field->enum_field->name;
|
||||
|
||||
fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name));
|
||||
fprintf(irp->f, ".%s = ", buf_ptr(field_name));
|
||||
@ -361,17 +361,10 @@ static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_enum_field_ptr(IrPrint *irp, IrInstructionEnumFieldPtr *instruction) {
|
||||
fprintf(irp->f, "@EnumFieldPtr(&");
|
||||
ir_print_other_instruction(irp, instruction->enum_ptr);
|
||||
fprintf(irp->f, ".%s", buf_ptr(instruction->field->name));
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) {
|
||||
fprintf(irp->f, "@UnionFieldPtr(&");
|
||||
ir_print_other_instruction(irp, instruction->union_ptr);
|
||||
fprintf(irp->f, ".%s", buf_ptr(instruction->field->name));
|
||||
fprintf(irp->f, ".%s", buf_ptr(instruction->field->enum_field->name));
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
@ -509,8 +502,8 @@ static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *inst
|
||||
ir_print_other_instruction(irp, instruction->target_value_ptr);
|
||||
}
|
||||
|
||||
static void ir_print_enum_tag(IrPrint *irp, IrInstructionEnumTag *instruction) {
|
||||
fprintf(irp->f, "enumtag ");
|
||||
static void ir_print_union_tag(IrPrint *irp, IrInstructionUnionTag *instruction) {
|
||||
fprintf(irp->f, "uniontag ");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
}
|
||||
|
||||
@ -799,12 +792,6 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction) {
|
||||
fprintf(irp->f, "%s.%s {", buf_ptr(&instruction->enum_type->name), buf_ptr(instruction->field->name));
|
||||
ir_print_other_instruction(irp, instruction->init_value);
|
||||
fprintf(irp->f, "}");
|
||||
}
|
||||
|
||||
static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
|
||||
fprintf(irp->f, "@ptrCast(");
|
||||
if (instruction->dest_type) {
|
||||
@ -885,8 +872,8 @@ static void ir_print_type_name(IrPrint *irp, IrInstructionTypeName *instruction)
|
||||
ir_print_other_instruction(irp, instruction->type_value);
|
||||
}
|
||||
|
||||
static void ir_print_enum_tag_name(IrPrint *irp, IrInstructionEnumTagName *instruction) {
|
||||
fprintf(irp->f, "enumtagname ");
|
||||
static void ir_print_tag_name(IrPrint *irp, IrInstructionTagName *instruction) {
|
||||
fprintf(irp->f, "tagname ");
|
||||
ir_print_other_instruction(irp, instruction->target);
|
||||
}
|
||||
|
||||
@ -994,6 +981,12 @@ static void ir_print_arg_type(IrPrint *irp, IrInstructionArgType *instruction) {
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_enum_tag_type(IrPrint *irp, IrInstructionTagType *instruction) {
|
||||
fprintf(irp->f, "@TagType(");
|
||||
ir_print_other_instruction(irp, instruction->target);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
|
||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
ir_print_prefix(irp, instruction);
|
||||
@ -1072,9 +1065,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdStructFieldPtr:
|
||||
ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);
|
||||
break;
|
||||
case IrInstructionIdEnumFieldPtr:
|
||||
ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction);
|
||||
break;
|
||||
case IrInstructionIdUnionFieldPtr:
|
||||
ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction);
|
||||
break;
|
||||
@ -1117,8 +1107,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdSwitchTarget:
|
||||
ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction);
|
||||
break;
|
||||
case IrInstructionIdEnumTag:
|
||||
ir_print_enum_tag(irp, (IrInstructionEnumTag *)instruction);
|
||||
case IrInstructionIdUnionTag:
|
||||
ir_print_union_tag(irp, (IrInstructionUnionTag *)instruction);
|
||||
break;
|
||||
case IrInstructionIdImport:
|
||||
ir_print_import(irp, (IrInstructionImport *)instruction);
|
||||
@ -1231,9 +1221,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdTestComptime:
|
||||
ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
|
||||
break;
|
||||
case IrInstructionIdInitEnum:
|
||||
ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction);
|
||||
break;
|
||||
case IrInstructionIdPtrCast:
|
||||
ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);
|
||||
break;
|
||||
@ -1267,8 +1254,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdTypeName:
|
||||
ir_print_type_name(irp, (IrInstructionTypeName *)instruction);
|
||||
break;
|
||||
case IrInstructionIdEnumTagName:
|
||||
ir_print_enum_tag_name(irp, (IrInstructionEnumTagName *)instruction);
|
||||
case IrInstructionIdTagName:
|
||||
ir_print_tag_name(irp, (IrInstructionTagName *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCanImplicitCast:
|
||||
ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction);
|
||||
@ -1312,6 +1299,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdArgType:
|
||||
ir_print_arg_type(irp, (IrInstructionArgType *)instruction);
|
||||
break;
|
||||
case IrInstructionIdTagType:
|
||||
ir_print_enum_tag_type(irp, (IrInstructionTagType *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
||||
@ -931,6 +931,7 @@ int os_self_exe_path(Buf *out_path) {
|
||||
#define VT_GREEN "\x1b[32;1m"
|
||||
#define VT_CYAN "\x1b[36;1m"
|
||||
#define VT_WHITE "\x1b[37;1m"
|
||||
#define VT_BOLD "\x1b[0;1m"
|
||||
#define VT_RESET "\x1b[0m"
|
||||
|
||||
static void set_color_posix(TermColor color) {
|
||||
@ -947,6 +948,9 @@ static void set_color_posix(TermColor color) {
|
||||
case TermColorWhite:
|
||||
fprintf(stderr, VT_WHITE);
|
||||
break;
|
||||
case TermColorBold:
|
||||
fprintf(stderr, VT_BOLD);
|
||||
break;
|
||||
case TermColorReset:
|
||||
fprintf(stderr, VT_RESET);
|
||||
break;
|
||||
@ -989,6 +993,7 @@ void os_stderr_set_color(TermColor color) {
|
||||
SetConsoleTextAttribute(stderr_handle, FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);
|
||||
break;
|
||||
case TermColorWhite:
|
||||
case TermColorBold:
|
||||
SetConsoleTextAttribute(stderr_handle,
|
||||
FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);
|
||||
break;
|
||||
|
||||
@ -21,6 +21,7 @@ enum TermColor {
|
||||
TermColorGreen,
|
||||
TermColorCyan,
|
||||
TermColorWhite,
|
||||
TermColorBold,
|
||||
TermColorReset,
|
||||
};
|
||||
|
||||
|
||||
@ -2377,9 +2377,11 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi
|
||||
}
|
||||
|
||||
/*
|
||||
ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"
|
||||
ContainerDecl = option("extern" | "packed")
|
||||
("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))
|
||||
"{" many(ContainerMember) "}"
|
||||
ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
|
||||
ContainerField = Symbol option(":" Expression) ","
|
||||
ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","
|
||||
*/
|
||||
static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) {
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
@ -2415,6 +2417,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
|
||||
node->data.container_decl.layout = layout;
|
||||
node->data.container_decl.kind = kind;
|
||||
|
||||
if (kind == ContainerKindUnion) {
|
||||
Token *lparen_token = &pc->tokens->at(*token_index);
|
||||
if (lparen_token->id == TokenIdLParen) {
|
||||
Token *enum_token = &pc->tokens->at(*token_index + 1);
|
||||
if (enum_token->id == TokenIdKeywordEnum) {
|
||||
Token *paren_token = &pc->tokens->at(*token_index + 2);
|
||||
if (paren_token->id == TokenIdLParen) {
|
||||
node->data.container_decl.auto_enum = true;
|
||||
*token_index += 2;
|
||||
node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, true);
|
||||
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||
} else if (paren_token->id == TokenIdRParen) {
|
||||
node->data.container_decl.auto_enum = true;
|
||||
*token_index += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!node->data.container_decl.auto_enum) {
|
||||
node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false);
|
||||
}
|
||||
|
||||
ast_eat_token(pc, token_index, TokenIdLBrace);
|
||||
|
||||
for (;;) {
|
||||
@ -2452,31 +2476,33 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
|
||||
AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);
|
||||
*token_index += 1;
|
||||
|
||||
node->data.container_decl.fields.append(field_node);
|
||||
field_node->data.struct_field.visib_mod = visib_mod;
|
||||
field_node->data.struct_field.name = token_buf(token);
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdComma || token->id == TokenIdRBrace) {
|
||||
field_node->data.struct_field.type = ast_create_void_type_node(pc, token);
|
||||
Token *colon_token = &pc->tokens->at(*token_index);
|
||||
if (colon_token->id == TokenIdColon) {
|
||||
*token_index += 1;
|
||||
node->data.container_decl.fields.append(field_node);
|
||||
|
||||
if (token->id == TokenIdRBrace) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ast_eat_token(pc, token_index, TokenIdColon);
|
||||
field_node->data.struct_field.type = ast_parse_expression(pc, token_index, true);
|
||||
node->data.container_decl.fields.append(field_node);
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdRBrace) {
|
||||
*token_index += 1;
|
||||
break;
|
||||
} else {
|
||||
ast_eat_token(pc, token_index, TokenIdComma);
|
||||
}
|
||||
field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
}
|
||||
Token *eq_token = &pc->tokens->at(*token_index);
|
||||
if (eq_token->id == TokenIdEq) {
|
||||
*token_index += 1;
|
||||
field_node->data.struct_field.value = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
}
|
||||
|
||||
Token *next_token = &pc->tokens->at(*token_index);
|
||||
if (next_token->id == TokenIdComma) {
|
||||
*token_index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (next_token->id == TokenIdRBrace) {
|
||||
*token_index += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
ast_invalid_token_error(pc, next_token);
|
||||
} else {
|
||||
ast_invalid_token_error(pc, token);
|
||||
}
|
||||
@ -2804,9 +2830,11 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
||||
case NodeTypeContainerDecl:
|
||||
visit_node_list(&node->data.container_decl.fields, visit, context);
|
||||
visit_node_list(&node->data.container_decl.decls, visit, context);
|
||||
visit_field(&node->data.container_decl.init_arg_expr, visit, context);
|
||||
break;
|
||||
case NodeTypeStructField:
|
||||
visit_field(&node->data.struct_field.type, visit, context);
|
||||
visit_field(&node->data.struct_field.value, visit, context);
|
||||
break;
|
||||
case NodeTypeContainerInitExpr:
|
||||
visit_field(&node->data.container_init_expr.type, visit, context);
|
||||
|
||||
@ -651,6 +651,14 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) {
|
||||
const Type *c_type = qual_type_canon(qt);
|
||||
if (c_type->getTypeClass() != Type::Builtin)
|
||||
return false;
|
||||
const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
|
||||
return builtin_ty->getKind() == kind;
|
||||
}
|
||||
|
||||
static bool c_is_float(Context *c, QualType qt) {
|
||||
const Type *c_type = qt.getTypePtr();
|
||||
if (c_type->getTypeClass() != Type::Builtin)
|
||||
@ -978,11 +986,23 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
|
||||
const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty);
|
||||
return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
|
||||
}
|
||||
case Type::IncompleteArray:
|
||||
{
|
||||
const IncompleteArrayType *incomplete_array_ty = static_cast<const IncompleteArrayType *>(ty);
|
||||
QualType child_qt = incomplete_array_ty->getElementType();
|
||||
AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);
|
||||
if (child_type_node == nullptr) {
|
||||
emit_warning(c, source_loc, "unresolved array element type");
|
||||
return nullptr;
|
||||
}
|
||||
AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(),
|
||||
child_qt.isVolatileQualified(), child_type_node);
|
||||
return pointer_node;
|
||||
}
|
||||
case Type::BlockPointer:
|
||||
case Type::LValueReference:
|
||||
case Type::RValueReference:
|
||||
case Type::MemberPointer:
|
||||
case Type::IncompleteArray:
|
||||
case Type::VariableArray:
|
||||
case Type::DependentSizedArray:
|
||||
case Type::DependentSizedExtVector:
|
||||
@ -3417,7 +3437,14 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
|
||||
AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);
|
||||
enum_node->data.container_decl.kind = ContainerKindEnum;
|
||||
enum_node->data.container_decl.layout = ContainerLayoutExtern;
|
||||
enum_node->data.container_decl.init_arg_expr = tag_int_type;
|
||||
// TODO only emit this tag type if the enum tag type is not the default.
|
||||
// I don't know what the default is, need to figure out how clang is deciding.
|
||||
// it appears to at least be different across gcc/msvc
|
||||
if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) &&
|
||||
!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int))
|
||||
{
|
||||
enum_node->data.container_decl.init_arg_expr = tag_int_type;
|
||||
}
|
||||
|
||||
enum_node->data.container_decl.fields.resize(field_count);
|
||||
uint32_t i = 0;
|
||||
@ -4304,7 +4331,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ErrorCCompileErrors;
|
||||
}
|
||||
|
||||
c->ctx = &ast_unit->getASTContext();
|
||||
|
||||
@ -793,7 +793,7 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_
|
||||
zig_unreachable();
|
||||
|
||||
case ZigLLVM_COFF:
|
||||
return lld::coff::link(array_ref_args, false);
|
||||
return lld::coff::link(array_ref_args, false, diag);
|
||||
|
||||
case ZigLLVM_ELF:
|
||||
return lld::elf::link(array_ref_args, false, diag);
|
||||
|
||||
@ -4,6 +4,8 @@ const Allocator = mem.Allocator;
|
||||
const assert = debug.assert;
|
||||
const ArrayList = @import("array_list.zig").ArrayList;
|
||||
|
||||
const fmt = @import("fmt/index.zig");
|
||||
|
||||
/// A buffer that allocates memory and maintains a null byte at the end.
|
||||
pub const Buffer = struct {
|
||||
list: ArrayList(u8),
|
||||
@ -96,6 +98,10 @@ pub const Buffer = struct {
|
||||
mem.copy(u8, self.list.toSlice()[old_len..], m);
|
||||
}
|
||||
|
||||
pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) -> %void {
|
||||
return fmt.format(self, append, format, args);
|
||||
}
|
||||
|
||||
pub fn appendByte(self: &Buffer, byte: u8) -> %void {
|
||||
return self.appendByteNTimes(byte, 1);
|
||||
}
|
||||
|
||||
@ -69,8 +69,8 @@ pub const Builder = struct {
|
||||
used: bool,
|
||||
};
|
||||
|
||||
const UserValue = enum {
|
||||
Flag,
|
||||
const UserValue = union(enum) {
|
||||
Flag: void,
|
||||
Scalar: []const u8,
|
||||
List: ArrayList([]const u8),
|
||||
};
|
||||
@ -450,7 +450,7 @@ pub const Builder = struct {
|
||||
pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {
|
||||
if (%%self.user_input_options.put(name, UserInputOption {
|
||||
.name = name,
|
||||
.value = UserValue.Scalar { value },
|
||||
.value = UserValue { .Scalar = value },
|
||||
.used = false,
|
||||
})) |*prev_value| {
|
||||
// option already exists
|
||||
@ -462,7 +462,7 @@ pub const Builder = struct {
|
||||
%%list.append(value);
|
||||
_ = %%self.user_input_options.put(name, UserInputOption {
|
||||
.name = name,
|
||||
.value = UserValue.List { list },
|
||||
.value = UserValue { .List = list },
|
||||
.used = false,
|
||||
});
|
||||
},
|
||||
@ -471,7 +471,7 @@ pub const Builder = struct {
|
||||
%%list.append(value);
|
||||
_ = %%self.user_input_options.put(name, UserInputOption {
|
||||
.name = name,
|
||||
.value = UserValue.List { *list },
|
||||
.value = UserValue { .List = *list },
|
||||
.used = false,
|
||||
});
|
||||
},
|
||||
@ -487,7 +487,7 @@ pub const Builder = struct {
|
||||
pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool {
|
||||
if (%%self.user_input_options.put(name, UserInputOption {
|
||||
.name = name,
|
||||
.value = UserValue.Flag,
|
||||
.value = UserValue {.Flag = {} },
|
||||
.used = false,
|
||||
})) |*prev_value| {
|
||||
switch (prev_value.value) {
|
||||
@ -685,8 +685,8 @@ const CrossTarget = struct {
|
||||
environ: builtin.Environ,
|
||||
};
|
||||
|
||||
const Target = enum {
|
||||
Native,
|
||||
const Target = union(enum) {
|
||||
Native: void,
|
||||
Cross: CrossTarget,
|
||||
|
||||
pub fn oFileExt(self: &const Target) -> []const u8 {
|
||||
@ -844,7 +844,7 @@ pub const LibExeObjStep = struct {
|
||||
.kind = kind,
|
||||
.root_src = root_src,
|
||||
.name = name,
|
||||
.target = Target.Native,
|
||||
.target = Target { .Native = {} },
|
||||
.linker_script = null,
|
||||
.link_libs = BufSet.init(builder.allocator),
|
||||
.frameworks = BufSet.init(builder.allocator),
|
||||
@ -879,7 +879,7 @@ pub const LibExeObjStep = struct {
|
||||
.kind = kind,
|
||||
.version = *version,
|
||||
.static = static,
|
||||
.target = Target.Native,
|
||||
.target = Target { .Native = {} },
|
||||
.cflags = ArrayList([]const u8).init(builder.allocator),
|
||||
.source_files = ArrayList([]const u8).init(builder.allocator),
|
||||
.object_files = ArrayList([]const u8).init(builder.allocator),
|
||||
@ -948,8 +948,8 @@ pub const LibExeObjStep = struct {
|
||||
pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os,
|
||||
target_environ: builtin.Environ)
|
||||
{
|
||||
self.target = Target.Cross {
|
||||
CrossTarget {
|
||||
self.target = Target {
|
||||
.Cross = CrossTarget {
|
||||
.arch = target_arch,
|
||||
.os = target_os,
|
||||
.environ = target_environ,
|
||||
@ -1186,13 +1186,13 @@ pub const LibExeObjStep = struct {
|
||||
Target.Native => {},
|
||||
Target.Cross => |cross_target| {
|
||||
%%zig_args.append("--target-arch");
|
||||
%%zig_args.append(@enumTagName(cross_target.arch));
|
||||
%%zig_args.append(@tagName(cross_target.arch));
|
||||
|
||||
%%zig_args.append("--target-os");
|
||||
%%zig_args.append(@enumTagName(cross_target.os));
|
||||
%%zig_args.append(@tagName(cross_target.os));
|
||||
|
||||
%%zig_args.append("--target-environ");
|
||||
%%zig_args.append(@enumTagName(cross_target.environ));
|
||||
%%zig_args.append(@tagName(cross_target.environ));
|
||||
},
|
||||
}
|
||||
|
||||
@ -1553,7 +1553,7 @@ pub const TestStep = struct {
|
||||
.name_prefix = "",
|
||||
.filter = null,
|
||||
.link_libs = BufSet.init(builder.allocator),
|
||||
.target = Target.Native,
|
||||
.target = Target { .Native = {} },
|
||||
.exec_cmd_args = null,
|
||||
}
|
||||
}
|
||||
@ -1581,8 +1581,8 @@ pub const TestStep = struct {
|
||||
pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os,
|
||||
target_environ: builtin.Environ)
|
||||
{
|
||||
self.target = Target.Cross {
|
||||
CrossTarget {
|
||||
self.target = Target {
|
||||
.Cross = CrossTarget {
|
||||
.arch = target_arch,
|
||||
.os = target_os,
|
||||
.environ = target_environ,
|
||||
@ -1620,13 +1620,13 @@ pub const TestStep = struct {
|
||||
Target.Native => {},
|
||||
Target.Cross => |cross_target| {
|
||||
%%zig_args.append("--target-arch");
|
||||
%%zig_args.append(@enumTagName(cross_target.arch));
|
||||
%%zig_args.append(@tagName(cross_target.arch));
|
||||
|
||||
%%zig_args.append("--target-os");
|
||||
%%zig_args.append(@enumTagName(cross_target.os));
|
||||
%%zig_args.append(@tagName(cross_target.os));
|
||||
|
||||
%%zig_args.append("--target-environ");
|
||||
%%zig_args.append(@enumTagName(cross_target.environ));
|
||||
%%zig_args.append(@tagName(cross_target.environ));
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -280,7 +280,7 @@ const AbbrevAttr = struct {
|
||||
form_id: u64,
|
||||
};
|
||||
|
||||
const FormValue = enum {
|
||||
const FormValue = union(enum) {
|
||||
Address: u64,
|
||||
Block: []u8,
|
||||
Const: Constant,
|
||||
@ -303,7 +303,7 @@ const Constant = struct {
|
||||
return error.InvalidDebugInfo;
|
||||
if (self.signed)
|
||||
return error.InvalidDebugInfo;
|
||||
return mem.readInt(self.payload, u64, false);
|
||||
return mem.readInt(self.payload, u64, builtin.Endian.Little);
|
||||
}
|
||||
};
|
||||
|
||||
@ -475,16 +475,16 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usiz
|
||||
|
||||
fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
|
||||
const buf = %return readAllocBytes(allocator, in_stream, size);
|
||||
return FormValue.Block { buf };
|
||||
return FormValue { .Block = buf };
|
||||
}
|
||||
|
||||
fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
|
||||
const block_len = %return in_stream.readVarInt(false, usize, size);
|
||||
const block_len = %return in_stream.readVarInt(builtin.Endian.Little, usize, size);
|
||||
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
||||
}
|
||||
|
||||
fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue {
|
||||
FormValue.Const { Constant {
|
||||
FormValue { .Const = Constant {
|
||||
.signed = signed,
|
||||
.payload = %return readAllocBytes(allocator, in_stream, size),
|
||||
}}
|
||||
@ -510,7 +510,7 @@ fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 {
|
||||
|
||||
fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
|
||||
const buf = %return readAllocBytes(allocator, in_stream, size);
|
||||
return FormValue.Ref { buf };
|
||||
return FormValue { .Ref = buf };
|
||||
}
|
||||
|
||||
fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue {
|
||||
@ -520,7 +520,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptim
|
||||
|
||||
fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue {
|
||||
return switch (form_id) {
|
||||
DW.FORM_addr => FormValue.Address { %return parseFormValueTargetAddrSize(in_stream) },
|
||||
DW.FORM_addr => FormValue { .Address = %return parseFormValueTargetAddrSize(in_stream) },
|
||||
DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
|
||||
DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
|
||||
DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
|
||||
@ -540,13 +540,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
|
||||
DW.FORM_exprloc => {
|
||||
const size = %return readULeb128(in_stream);
|
||||
const buf = %return readAllocBytes(allocator, in_stream, size);
|
||||
return FormValue.ExprLoc { buf };
|
||||
},
|
||||
DW.FORM_flag => FormValue.Flag { (%return in_stream.readByte()) != 0 },
|
||||
DW.FORM_flag_present => FormValue.Flag { true },
|
||||
DW.FORM_sec_offset => FormValue.SecOffset {
|
||||
%return parseFormValueDwarfOffsetSize(in_stream, is_64)
|
||||
return FormValue { .ExprLoc = buf };
|
||||
},
|
||||
DW.FORM_flag => FormValue { .Flag = (%return in_stream.readByte()) != 0 },
|
||||
DW.FORM_flag_present => FormValue { .Flag = true },
|
||||
DW.FORM_sec_offset => FormValue { .SecOffset = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||
|
||||
DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),
|
||||
DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),
|
||||
@ -557,11 +555,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
|
||||
parseFormValueRefLen(allocator, in_stream, ref_len)
|
||||
},
|
||||
|
||||
DW.FORM_ref_addr => FormValue.RefAddr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||
DW.FORM_ref_sig8 => FormValue.RefSig8 { %return in_stream.readIntLe(u64) },
|
||||
DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||
DW.FORM_ref_sig8 => FormValue { .RefSig8 = %return in_stream.readIntLe(u64) },
|
||||
|
||||
DW.FORM_string => FormValue.String { %return readStringRaw(allocator, in_stream) },
|
||||
DW.FORM_strp => FormValue.StrPtr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||
DW.FORM_string => FormValue { .String = %return readStringRaw(allocator, in_stream) },
|
||||
DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||
DW.FORM_indirect => {
|
||||
const child_form_id = %return readULeb128(in_stream);
|
||||
parseFormValue(allocator, in_stream, child_form_id, is_64)
|
||||
@ -671,10 +669,10 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
|
||||
continue;
|
||||
}
|
||||
|
||||
const version = %return in_stream.readInt(st.elf.is_big_endian, u16);
|
||||
const version = %return in_stream.readInt(st.elf.endian, u16);
|
||||
if (version != 2) return error.InvalidDebugInfo;
|
||||
|
||||
const prologue_length = %return in_stream.readInt(st.elf.is_big_endian, u32);
|
||||
const prologue_length = %return in_stream.readInt(st.elf.endian, u32);
|
||||
const prog_start_offset = (%return in_file.getPos()) + prologue_length;
|
||||
|
||||
const minimum_instruction_length = %return in_stream.readByte();
|
||||
@ -741,7 +739,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
|
||||
return error.MissingDebugInfo;
|
||||
},
|
||||
DW.LNE_set_address => {
|
||||
const addr = %return in_stream.readInt(st.elf.is_big_endian, usize);
|
||||
const addr = %return in_stream.readInt(st.elf.endian, usize);
|
||||
prog.address = addr;
|
||||
},
|
||||
DW.LNE_define_file => {
|
||||
@ -803,7 +801,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
|
||||
prog.address += inc_addr;
|
||||
},
|
||||
DW.LNS_fixed_advance_pc => {
|
||||
const arg = %return in_stream.readInt(st.elf.is_big_endian, u16);
|
||||
const arg = %return in_stream.readInt(st.elf.endian, u16);
|
||||
prog.address += arg;
|
||||
},
|
||||
DW.LNS_set_prologue_end => {
|
||||
@ -841,13 +839,13 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
|
||||
return;
|
||||
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
|
||||
|
||||
const version = %return in_stream.readInt(st.elf.is_big_endian, u16);
|
||||
const version = %return in_stream.readInt(st.elf.endian, u16);
|
||||
if (version < 2 or version > 5) return error.InvalidDebugInfo;
|
||||
|
||||
const debug_abbrev_offset = if (is_64) {
|
||||
%return in_stream.readInt(st.elf.is_big_endian, u64)
|
||||
%return in_stream.readInt(st.elf.endian, u64)
|
||||
} else {
|
||||
%return in_stream.readInt(st.elf.is_big_endian, u32)
|
||||
%return in_stream.readInt(st.elf.endian, u32)
|
||||
};
|
||||
|
||||
const address_size = %return in_stream.readByte();
|
||||
|
||||
79
std/elf.zig
79
std/elf.zig
@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("index.zig");
|
||||
const io = std.io;
|
||||
const math = std.math;
|
||||
@ -67,7 +68,7 @@ pub const Elf = struct {
|
||||
in_file: &io.File,
|
||||
auto_close_stream: bool,
|
||||
is_64: bool,
|
||||
is_big_endian: bool,
|
||||
endian: builtin.Endian,
|
||||
file_type: FileType,
|
||||
arch: Arch,
|
||||
entry_addr: u64,
|
||||
@ -105,9 +106,9 @@ pub const Elf = struct {
|
||||
else => return error.InvalidFormat,
|
||||
};
|
||||
|
||||
elf.is_big_endian = switch (%return in.readByte()) {
|
||||
1 => false,
|
||||
2 => true,
|
||||
elf.endian = switch (%return in.readByte()) {
|
||||
1 => builtin.Endian.Little,
|
||||
2 => builtin.Endian.Big,
|
||||
else => return error.InvalidFormat,
|
||||
};
|
||||
|
||||
@ -117,7 +118,7 @@ pub const Elf = struct {
|
||||
// skip over padding
|
||||
%return elf.in_file.seekForward(9);
|
||||
|
||||
elf.file_type = switch (%return in.readInt(elf.is_big_endian, u16)) {
|
||||
elf.file_type = switch (%return in.readInt(elf.endian, u16)) {
|
||||
1 => FileType.Relocatable,
|
||||
2 => FileType.Executable,
|
||||
3 => FileType.Shared,
|
||||
@ -125,7 +126,7 @@ pub const Elf = struct {
|
||||
else => return error.InvalidFormat,
|
||||
};
|
||||
|
||||
elf.arch = switch (%return in.readInt(elf.is_big_endian, u16)) {
|
||||
elf.arch = switch (%return in.readInt(elf.endian, u16)) {
|
||||
0x02 => Arch.Sparc,
|
||||
0x03 => Arch.x86,
|
||||
0x08 => Arch.Mips,
|
||||
@ -138,34 +139,34 @@ pub const Elf = struct {
|
||||
else => return error.InvalidFormat,
|
||||
};
|
||||
|
||||
const elf_version = %return in.readInt(elf.is_big_endian, u32);
|
||||
const elf_version = %return in.readInt(elf.endian, u32);
|
||||
if (elf_version != 1) return error.InvalidFormat;
|
||||
|
||||
if (elf.is_64) {
|
||||
elf.entry_addr = %return in.readInt(elf.is_big_endian, u64);
|
||||
elf.program_header_offset = %return in.readInt(elf.is_big_endian, u64);
|
||||
elf.section_header_offset = %return in.readInt(elf.is_big_endian, u64);
|
||||
elf.entry_addr = %return in.readInt(elf.endian, u64);
|
||||
elf.program_header_offset = %return in.readInt(elf.endian, u64);
|
||||
elf.section_header_offset = %return in.readInt(elf.endian, u64);
|
||||
} else {
|
||||
elf.entry_addr = u64(%return in.readInt(elf.is_big_endian, u32));
|
||||
elf.program_header_offset = u64(%return in.readInt(elf.is_big_endian, u32));
|
||||
elf.section_header_offset = u64(%return in.readInt(elf.is_big_endian, u32));
|
||||
elf.entry_addr = u64(%return in.readInt(elf.endian, u32));
|
||||
elf.program_header_offset = u64(%return in.readInt(elf.endian, u32));
|
||||
elf.section_header_offset = u64(%return in.readInt(elf.endian, u32));
|
||||
}
|
||||
|
||||
// skip over flags
|
||||
%return elf.in_file.seekForward(4);
|
||||
|
||||
const header_size = %return in.readInt(elf.is_big_endian, u16);
|
||||
const header_size = %return in.readInt(elf.endian, u16);
|
||||
if ((elf.is_64 and header_size != 64) or
|
||||
(!elf.is_64 and header_size != 52))
|
||||
{
|
||||
return error.InvalidFormat;
|
||||
}
|
||||
|
||||
const ph_entry_size = %return in.readInt(elf.is_big_endian, u16);
|
||||
const ph_entry_count = %return in.readInt(elf.is_big_endian, u16);
|
||||
const sh_entry_size = %return in.readInt(elf.is_big_endian, u16);
|
||||
const sh_entry_count = %return in.readInt(elf.is_big_endian, u16);
|
||||
elf.string_section_index = u64(%return in.readInt(elf.is_big_endian, u16));
|
||||
const ph_entry_size = %return in.readInt(elf.endian, u16);
|
||||
const ph_entry_count = %return in.readInt(elf.endian, u16);
|
||||
const sh_entry_size = %return in.readInt(elf.endian, u16);
|
||||
const sh_entry_count = %return in.readInt(elf.endian, u16);
|
||||
elf.string_section_index = u64(%return in.readInt(elf.endian, u16));
|
||||
|
||||
if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
|
||||
|
||||
@ -188,32 +189,32 @@ pub const Elf = struct {
|
||||
if (sh_entry_size != 64) return error.InvalidFormat;
|
||||
|
||||
for (elf.section_headers) |*section| {
|
||||
section.name = %return in.readInt(elf.is_big_endian, u32);
|
||||
section.sh_type = %return in.readInt(elf.is_big_endian, u32);
|
||||
section.flags = %return in.readInt(elf.is_big_endian, u64);
|
||||
section.addr = %return in.readInt(elf.is_big_endian, u64);
|
||||
section.offset = %return in.readInt(elf.is_big_endian, u64);
|
||||
section.size = %return in.readInt(elf.is_big_endian, u64);
|
||||
section.link = %return in.readInt(elf.is_big_endian, u32);
|
||||
section.info = %return in.readInt(elf.is_big_endian, u32);
|
||||
section.addr_align = %return in.readInt(elf.is_big_endian, u64);
|
||||
section.ent_size = %return in.readInt(elf.is_big_endian, u64);
|
||||
section.name = %return in.readInt(elf.endian, u32);
|
||||
section.sh_type = %return in.readInt(elf.endian, u32);
|
||||
section.flags = %return in.readInt(elf.endian, u64);
|
||||
section.addr = %return in.readInt(elf.endian, u64);
|
||||
section.offset = %return in.readInt(elf.endian, u64);
|
||||
section.size = %return in.readInt(elf.endian, u64);
|
||||
section.link = %return in.readInt(elf.endian, u32);
|
||||
section.info = %return in.readInt(elf.endian, u32);
|
||||
section.addr_align = %return in.readInt(elf.endian, u64);
|
||||
section.ent_size = %return in.readInt(elf.endian, u64);
|
||||
}
|
||||
} else {
|
||||
if (sh_entry_size != 40) return error.InvalidFormat;
|
||||
|
||||
for (elf.section_headers) |*section| {
|
||||
// TODO (multiple occurences) allow implicit cast from %u32 -> %u64 ?
|
||||
section.name = %return in.readInt(elf.is_big_endian, u32);
|
||||
section.sh_type = %return in.readInt(elf.is_big_endian, u32);
|
||||
section.flags = u64(%return in.readInt(elf.is_big_endian, u32));
|
||||
section.addr = u64(%return in.readInt(elf.is_big_endian, u32));
|
||||
section.offset = u64(%return in.readInt(elf.is_big_endian, u32));
|
||||
section.size = u64(%return in.readInt(elf.is_big_endian, u32));
|
||||
section.link = %return in.readInt(elf.is_big_endian, u32);
|
||||
section.info = %return in.readInt(elf.is_big_endian, u32);
|
||||
section.addr_align = u64(%return in.readInt(elf.is_big_endian, u32));
|
||||
section.ent_size = u64(%return in.readInt(elf.is_big_endian, u32));
|
||||
section.name = %return in.readInt(elf.endian, u32);
|
||||
section.sh_type = %return in.readInt(elf.endian, u32);
|
||||
section.flags = u64(%return in.readInt(elf.endian, u32));
|
||||
section.addr = u64(%return in.readInt(elf.endian, u32));
|
||||
section.offset = u64(%return in.readInt(elf.endian, u32));
|
||||
section.size = u64(%return in.readInt(elf.endian, u32));
|
||||
section.link = %return in.readInt(elf.endian, u32);
|
||||
section.info = %return in.readInt(elf.endian, u32);
|
||||
section.addr_align = u64(%return in.readInt(elf.endian, u32));
|
||||
section.ent_size = u64(%return in.readInt(elf.endian, u32));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,8 +9,8 @@ pub fn swapIfBe(comptime T: type, x: T) -> T {
|
||||
swapIf(true, T, x)
|
||||
}
|
||||
|
||||
pub fn swapIf(is_be: bool, comptime T: type, x: T) -> T {
|
||||
if (builtin.is_big_endian == is_be) swap(T, x) else x
|
||||
pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T {
|
||||
if (builtin.endian == endian) swap(T, x) else x
|
||||
}
|
||||
|
||||
pub fn swap(comptime T: type, x: T) -> T {
|
||||
|
||||
14
std/io.zig
14
std/io.zig
@ -259,7 +259,7 @@ pub const File = struct {
|
||||
if (err > 0) {
|
||||
return switch (err) {
|
||||
system.EBADF => error.BadFd,
|
||||
system.ENOMEM => error.OutOfMemory,
|
||||
system.ENOMEM => error.SystemResources,
|
||||
else => os.unexpectedErrorPosix(err),
|
||||
}
|
||||
}
|
||||
@ -441,26 +441,26 @@ pub const InStream = struct {
|
||||
}
|
||||
|
||||
pub fn readIntLe(self: &InStream, comptime T: type) -> %T {
|
||||
return self.readInt(false, T);
|
||||
return self.readInt(builtin.Endian.Little, T);
|
||||
}
|
||||
|
||||
pub fn readIntBe(self: &InStream, comptime T: type) -> %T {
|
||||
return self.readInt(true, T);
|
||||
return self.readInt(builtin.Endian.Big, T);
|
||||
}
|
||||
|
||||
pub fn readInt(self: &InStream, is_be: bool, comptime T: type) -> %T {
|
||||
pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) -> %T {
|
||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||
%return self.readNoEof(bytes[0..]);
|
||||
return mem.readInt(bytes, T, is_be);
|
||||
return mem.readInt(bytes, T, endian);
|
||||
}
|
||||
|
||||
pub fn readVarInt(self: &InStream, is_be: bool, comptime T: type, size: usize) -> %T {
|
||||
pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) -> %T {
|
||||
assert(size <= @sizeOf(T));
|
||||
assert(size <= 8);
|
||||
var input_buf: [8]u8 = undefined;
|
||||
const input_slice = input_buf[0..size];
|
||||
%return self.readNoEof(input_slice);
|
||||
return mem.readInt(input_slice, T, is_be);
|
||||
return mem.readInt(input_slice, T, endian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
109
std/mem.zig
109
std/mem.zig
@ -1,6 +1,7 @@
|
||||
const debug = @import("debug.zig");
|
||||
const assert = debug.assert;
|
||||
const math = @import("math/index.zig");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub const Cmp = math.Cmp;
|
||||
|
||||
@ -180,43 +181,78 @@ test "mem.indexOf" {
|
||||
/// Reads an integer from memory with size equal to bytes.len.
|
||||
/// T specifies the return type, which must be large enough to store
|
||||
/// the result.
|
||||
pub fn readInt(bytes: []const u8, comptime T: type, big_endian: bool) -> T {
|
||||
/// See also ::readIntBE or ::readIntLE.
|
||||
pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) -> T {
|
||||
if (T.bit_count == 8) {
|
||||
return bytes[0];
|
||||
}
|
||||
var result: T = 0;
|
||||
if (big_endian) {
|
||||
for (bytes) |b| {
|
||||
result = (result << 8) | b;
|
||||
}
|
||||
} else {
|
||||
const ShiftType = math.Log2Int(T);
|
||||
for (bytes) |b, index| {
|
||||
result = result | (T(b) << ShiftType(index * 8));
|
||||
}
|
||||
switch (endian) {
|
||||
builtin.Endian.Big => {
|
||||
for (bytes) |b| {
|
||||
result = (result << 8) | b;
|
||||
}
|
||||
},
|
||||
builtin.Endian.Little => {
|
||||
const ShiftType = math.Log2Int(T);
|
||||
for (bytes) |b, index| {
|
||||
result = result | (T(b) << ShiftType(index * 8));
|
||||
}
|
||||
},
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Reads a big-endian int of type T from bytes.
|
||||
/// bytes.len must be exactly @sizeOf(T).
|
||||
pub fn readIntBE(comptime T: type, bytes: []const u8) -> T {
|
||||
if (T.is_signed) {
|
||||
return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));
|
||||
}
|
||||
assert(bytes.len == @sizeOf(T));
|
||||
var result: T = 0;
|
||||
{comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) {
|
||||
result = (result << 8) | T(bytes[i]);
|
||||
}}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Reads a little-endian int of type T from bytes.
|
||||
/// bytes.len must be exactly @sizeOf(T).
|
||||
pub fn readIntLE(comptime T: type, bytes: []const u8) -> T {
|
||||
if (T.is_signed) {
|
||||
return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));
|
||||
}
|
||||
assert(bytes.len == @sizeOf(T));
|
||||
var result: T = 0;
|
||||
{comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) {
|
||||
result |= T(bytes[i]) << i * 8;
|
||||
}}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes
|
||||
/// to fill the entire buffer provided.
|
||||
/// value must be an integer.
|
||||
pub fn writeInt(buf: []u8, value: var, big_endian: bool) {
|
||||
pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) {
|
||||
const uint = @IntType(false, @typeOf(value).bit_count);
|
||||
var bits = @truncate(uint, value);
|
||||
if (big_endian) {
|
||||
var index: usize = buf.len;
|
||||
while (index != 0) {
|
||||
index -= 1;
|
||||
switch (endian) {
|
||||
builtin.Endian.Big => {
|
||||
var index: usize = buf.len;
|
||||
while (index != 0) {
|
||||
index -= 1;
|
||||
|
||||
buf[index] = @truncate(u8, bits);
|
||||
bits >>= 8;
|
||||
}
|
||||
} else {
|
||||
for (buf) |*b| {
|
||||
*b = @truncate(u8, bits);
|
||||
bits >>= 8;
|
||||
}
|
||||
buf[index] = @truncate(u8, bits);
|
||||
bits >>= 8;
|
||||
}
|
||||
},
|
||||
builtin.Endian.Little => {
|
||||
for (buf) |*b| {
|
||||
*b = @truncate(u8, bits);
|
||||
bits >>= 8;
|
||||
}
|
||||
},
|
||||
}
|
||||
assert(bits == 0);
|
||||
}
|
||||
@ -348,19 +384,30 @@ test "testReadInt" {
|
||||
fn testReadIntImpl() {
|
||||
{
|
||||
const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 };
|
||||
assert(readInt(bytes, u32, true) == 0x12345678);
|
||||
assert(readInt(bytes, u32, false) == 0x78563412);
|
||||
assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
|
||||
assert(readIntBE(u32, bytes) == 0x12345678);
|
||||
assert(readIntBE(i32, bytes) == 0x12345678);
|
||||
assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);
|
||||
assert(readIntLE(u32, bytes) == 0x78563412);
|
||||
assert(readIntLE(i32, bytes) == 0x78563412);
|
||||
}
|
||||
{
|
||||
const buf = []u8{0x00, 0x00, 0x12, 0x34};
|
||||
const answer = readInt(buf, u64, true);
|
||||
const answer = readInt(buf, u64, builtin.Endian.Big);
|
||||
assert(answer == 0x00001234);
|
||||
}
|
||||
{
|
||||
const buf = []u8{0x12, 0x34, 0x00, 0x00};
|
||||
const answer = readInt(buf, u64, false);
|
||||
const answer = readInt(buf, u64, builtin.Endian.Little);
|
||||
assert(answer == 0x00003412);
|
||||
}
|
||||
{
|
||||
const bytes = []u8{0xff, 0xfe};
|
||||
assert(readIntBE(u16, bytes) == 0xfffe);
|
||||
assert(readIntBE(i16, bytes) == -0x0002);
|
||||
assert(readIntLE(u16, bytes) == 0xfeff);
|
||||
assert(readIntLE(i16, bytes) == -0x0101);
|
||||
}
|
||||
}
|
||||
|
||||
test "testWriteInt" {
|
||||
@ -370,16 +417,16 @@ test "testWriteInt" {
|
||||
fn testWriteIntImpl() {
|
||||
var bytes: [4]u8 = undefined;
|
||||
|
||||
writeInt(bytes[0..], u32(0x12345678), true);
|
||||
writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
|
||||
assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 }));
|
||||
|
||||
writeInt(bytes[0..], u32(0x78563412), false);
|
||||
writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);
|
||||
assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 }));
|
||||
|
||||
writeInt(bytes[0..], u16(0x1234), true);
|
||||
writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
|
||||
assert(eql(u8, bytes, []u8{ 0x00, 0x00, 0x12, 0x34 }));
|
||||
|
||||
writeInt(bytes[0..], u16(0x1234), false);
|
||||
writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);
|
||||
assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 }));
|
||||
}
|
||||
|
||||
|
||||
@ -58,7 +58,7 @@ pub const ChildProcess = struct {
|
||||
err_pipe: if (is_windows) void else [2]i32,
|
||||
llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,
|
||||
|
||||
pub const Term = enum {
|
||||
pub const Term = union(enum) {
|
||||
Exited: i32,
|
||||
Signal: i32,
|
||||
Stopped: i32,
|
||||
@ -213,9 +213,9 @@ pub const ChildProcess = struct {
|
||||
self.term = (%Term)({
|
||||
var exit_code: windows.DWORD = undefined;
|
||||
if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) {
|
||||
Term.Unknown{0}
|
||||
Term { .Unknown = 0 }
|
||||
} else {
|
||||
Term.Exited {@bitCast(i32, exit_code)}
|
||||
Term { .Exited = @bitCast(i32, exit_code)}
|
||||
}
|
||||
});
|
||||
|
||||
@ -281,13 +281,13 @@ pub const ChildProcess = struct {
|
||||
|
||||
fn statusToTerm(status: i32) -> Term {
|
||||
return if (posix.WIFEXITED(status)) {
|
||||
Term.Exited { posix.WEXITSTATUS(status) }
|
||||
Term { .Exited = posix.WEXITSTATUS(status) }
|
||||
} else if (posix.WIFSIGNALED(status)) {
|
||||
Term.Signal { posix.WTERMSIG(status) }
|
||||
Term { .Signal = posix.WTERMSIG(status) }
|
||||
} else if (posix.WIFSTOPPED(status)) {
|
||||
Term.Stopped { posix.WSTOPSIG(status) }
|
||||
Term { .Stopped = posix.WSTOPSIG(status) }
|
||||
} else {
|
||||
Term.Unknown { status }
|
||||
Term { .Unknown = status }
|
||||
};
|
||||
}
|
||||
|
||||
@ -722,14 +722,14 @@ const ErrInt = @IntType(false, @sizeOf(error) * 8);
|
||||
|
||||
fn writeIntFd(fd: i32, value: ErrInt) -> %void {
|
||||
var bytes: [@sizeOf(ErrInt)]u8 = undefined;
|
||||
mem.writeInt(bytes[0..], value, true);
|
||||
mem.writeInt(bytes[0..], value, builtin.endian);
|
||||
os.posixWrite(fd, bytes[0..]) %% return error.SystemResources;
|
||||
}
|
||||
|
||||
fn readIntFd(fd: i32) -> %ErrInt {
|
||||
var bytes: [@sizeOf(ErrInt)]u8 = undefined;
|
||||
os.posixRead(fd, bytes[0..]) %% return error.SystemResources;
|
||||
return mem.readInt(bytes[0..], ErrInt, true);
|
||||
return mem.readInt(bytes[0..], ErrInt, builtin.endian);
|
||||
}
|
||||
|
||||
extern fn sigchld_handler(_: i32) {
|
||||
|
||||
@ -939,6 +939,7 @@ start_over:
|
||||
}
|
||||
|
||||
pub const Dir = struct {
|
||||
// See man getdents
|
||||
fd: i32,
|
||||
allocator: &Allocator,
|
||||
buf: []u8,
|
||||
@ -981,7 +982,7 @@ pub const Dir = struct {
|
||||
|
||||
pub fn close(self: &Dir) {
|
||||
self.allocator.free(self.buf);
|
||||
close(self.fd);
|
||||
os.close(self.fd);
|
||||
}
|
||||
|
||||
/// Memory such as file names referenced in this returned entry becomes invalid
|
||||
@ -1013,7 +1014,7 @@ pub const Dir = struct {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const linux_entry = @ptrCast(&LinuxEntry, &self.buf[self.index]);
|
||||
const linux_entry = @ptrCast(& align(1) LinuxEntry, &self.buf[self.index]);
|
||||
const next_index = self.index + linux_entry.d_reclen;
|
||||
self.index = next_index;
|
||||
|
||||
|
||||
@ -1016,7 +1016,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
|
||||
|
||||
return os.readLink(allocator, proc_path);
|
||||
},
|
||||
else => @compileError("TODO implement os.path.real for " ++ @enumTagName(builtin.os)),
|
||||
else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -50,12 +50,12 @@ pub const Rand = struct {
|
||||
pub fn fillBytes(r: &Rand, buf: []u8) {
|
||||
var bytes_left = buf.len;
|
||||
while (bytes_left >= @sizeOf(usize)) {
|
||||
mem.writeInt(buf[buf.len - bytes_left..], r.rng.get(), false);
|
||||
mem.writeInt(buf[buf.len - bytes_left..], r.rng.get(), builtin.Endian.Little);
|
||||
bytes_left -= @sizeOf(usize);
|
||||
}
|
||||
if (bytes_left > 0) {
|
||||
var rand_val_array: [@sizeOf(usize)]u8 = undefined;
|
||||
mem.writeInt(rand_val_array[0..], r.rng.get(), false);
|
||||
mem.writeInt(rand_val_array[0..], r.rng.get(), builtin.Endian.Little);
|
||||
while (bytes_left > 0) {
|
||||
buf[buf.len - bytes_left] = rand_val_array[@sizeOf(usize) - bytes_left];
|
||||
bytes_left -= 1;
|
||||
@ -98,7 +98,7 @@ pub const Rand = struct {
|
||||
|
||||
while (true) {
|
||||
r.fillBytes(rand_val_array[0..]);
|
||||
const rand_val = mem.readInt(rand_val_array, T, false);
|
||||
const rand_val = mem.readInt(rand_val_array, T, builtin.Endian.Little);
|
||||
if (rand_val < upper_bound) {
|
||||
return start + (rand_val % total_range);
|
||||
}
|
||||
|
||||
70
std/sort.zig
70
std/sort.zig
@ -4,6 +4,19 @@ const math = @import("math/index.zig");
|
||||
|
||||
pub const Cmp = math.Cmp;
|
||||
|
||||
/// Stable sort using O(1) space. Currently implemented as insertion sort.
|
||||
pub fn sort_stable(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) {
|
||||
{var i: usize = 1; while (i < array.len) : (i += 1) {
|
||||
const x = array[i];
|
||||
var j: usize = i;
|
||||
while (j > 0 and cmp(array[j - 1], x) == Cmp.Greater) : (j -= 1) {
|
||||
array[j] = array[j - 1];
|
||||
}
|
||||
array[j] = x;
|
||||
}}
|
||||
}
|
||||
|
||||
/// Unstable sort using O(n) stack space. Currently implemented as quicksort.
|
||||
pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) {
|
||||
if (array.len > 0) {
|
||||
quicksort(T, array, 0, array.len - 1, cmp);
|
||||
@ -58,6 +71,63 @@ fn reverse(was: Cmp) -> Cmp {
|
||||
// ---------------------------------------
|
||||
// tests
|
||||
|
||||
test "stable sort" {
|
||||
testStableSort();
|
||||
// TODO: uncomment this after https://github.com/zig-lang/zig/issues/639
|
||||
//comptime testStableSort();
|
||||
}
|
||||
fn testStableSort() {
|
||||
var expected = []IdAndValue {
|
||||
IdAndValue{.id = 0, .value = 0},
|
||||
IdAndValue{.id = 1, .value = 0},
|
||||
IdAndValue{.id = 2, .value = 0},
|
||||
IdAndValue{.id = 0, .value = 1},
|
||||
IdAndValue{.id = 1, .value = 1},
|
||||
IdAndValue{.id = 2, .value = 1},
|
||||
IdAndValue{.id = 0, .value = 2},
|
||||
IdAndValue{.id = 1, .value = 2},
|
||||
IdAndValue{.id = 2, .value = 2},
|
||||
};
|
||||
var cases = [][9]IdAndValue {
|
||||
[]IdAndValue {
|
||||
IdAndValue{.id = 0, .value = 0},
|
||||
IdAndValue{.id = 0, .value = 1},
|
||||
IdAndValue{.id = 0, .value = 2},
|
||||
IdAndValue{.id = 1, .value = 0},
|
||||
IdAndValue{.id = 1, .value = 1},
|
||||
IdAndValue{.id = 1, .value = 2},
|
||||
IdAndValue{.id = 2, .value = 0},
|
||||
IdAndValue{.id = 2, .value = 1},
|
||||
IdAndValue{.id = 2, .value = 2},
|
||||
},
|
||||
[]IdAndValue {
|
||||
IdAndValue{.id = 0, .value = 2},
|
||||
IdAndValue{.id = 0, .value = 1},
|
||||
IdAndValue{.id = 0, .value = 0},
|
||||
IdAndValue{.id = 1, .value = 2},
|
||||
IdAndValue{.id = 1, .value = 1},
|
||||
IdAndValue{.id = 1, .value = 0},
|
||||
IdAndValue{.id = 2, .value = 2},
|
||||
IdAndValue{.id = 2, .value = 1},
|
||||
IdAndValue{.id = 2, .value = 0},
|
||||
},
|
||||
};
|
||||
for (cases) |*case| {
|
||||
sort_stable(IdAndValue, (*case)[0..], cmpByValue);
|
||||
for (*case) |item, i| {
|
||||
assert(item.id == expected[i].id);
|
||||
assert(item.value == expected[i].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
const IdAndValue = struct {
|
||||
id: i32,
|
||||
value: i32,
|
||||
};
|
||||
fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) -> Cmp {
|
||||
return i32asc(a.value, b.value);
|
||||
}
|
||||
|
||||
test "testSort" {
|
||||
const u8cases = [][]const []const u8 {
|
||||
[][]const u8{"", ""},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
|
||||
const low = if (builtin.is_big_endian) 1 else 0;
|
||||
const low = switch (builtin.endian) { builtin.Endian.Big => 1, builtin.Endian.Little => 0 };
|
||||
const high = 1 - low;
|
||||
|
||||
pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?&DoubleInt) -> DoubleInt {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
const E = enum { A: [9]u8, B: u64, };
|
||||
const E = union(enum) { A: [9]u8, B: u64, };
|
||||
const S = struct { x: u8, y: E, };
|
||||
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "bug 394 fixed" {
|
||||
const x = S { .x = 3, .y = E.B {1} };
|
||||
const x = S { .x = 3, .y = E {.B = 1 } };
|
||||
assert(x.x == 3);
|
||||
}
|
||||
|
||||
@ -2,8 +2,8 @@ const assert = @import("std").debug.assert;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
test "enum type" {
|
||||
const foo1 = Foo.One {13};
|
||||
const foo2 = Foo.Two { Point { .x = 1234, .y = 5678, }};
|
||||
const foo1 = Foo{ .One = 13};
|
||||
const foo2 = Foo{. Two = Point { .x = 1234, .y = 5678, }};
|
||||
const bar = Bar.B;
|
||||
|
||||
assert(bar == Bar.B);
|
||||
@ -24,12 +24,12 @@ const Point = struct {
|
||||
x: u64,
|
||||
y: u64,
|
||||
};
|
||||
const Foo = enum {
|
||||
const Foo = union(enum) {
|
||||
One: i32,
|
||||
Two: Point,
|
||||
Three: void,
|
||||
};
|
||||
const FooNoVoid = enum {
|
||||
const FooNoVoid = union(enum) {
|
||||
One: i32,
|
||||
Two: Point,
|
||||
};
|
||||
@ -41,13 +41,13 @@ const Bar = enum {
|
||||
};
|
||||
|
||||
fn returnAnInt(x: i32) -> Foo {
|
||||
Foo.One { x }
|
||||
Foo { .One = x }
|
||||
}
|
||||
|
||||
|
||||
test "constant enum with payload" {
|
||||
var empty = AnEnumWithPayload.Empty;
|
||||
var full = AnEnumWithPayload.Full {13};
|
||||
var empty = AnEnumWithPayload {.Empty = {}};
|
||||
var full = AnEnumWithPayload {.Full = 13};
|
||||
shouldBeEmpty(empty);
|
||||
shouldBeNotEmpty(full);
|
||||
}
|
||||
@ -66,8 +66,8 @@ fn shouldBeNotEmpty(x: &const AnEnumWithPayload) {
|
||||
}
|
||||
}
|
||||
|
||||
const AnEnumWithPayload = enum {
|
||||
Empty,
|
||||
const AnEnumWithPayload = union(enum) {
|
||||
Empty: void,
|
||||
Full: i32,
|
||||
};
|
||||
|
||||
@ -89,8 +89,8 @@ test "enum to int" {
|
||||
shouldEqual(Number.Four, 4);
|
||||
}
|
||||
|
||||
fn shouldEqual(n: Number, expected: usize) {
|
||||
assert(usize(n) == expected);
|
||||
fn shouldEqual(n: Number, expected: u3) {
|
||||
assert(u3(n) == expected);
|
||||
}
|
||||
|
||||
|
||||
@ -98,7 +98,7 @@ test "int to enum" {
|
||||
testIntToEnumEval(3);
|
||||
}
|
||||
fn testIntToEnumEval(x: i32) {
|
||||
assert(IntToEnumNumber(x) == IntToEnumNumber.Three);
|
||||
assert(IntToEnumNumber(u3(x)) == IntToEnumNumber.Three);
|
||||
}
|
||||
const IntToEnumNumber = enum {
|
||||
Zero,
|
||||
@ -109,13 +109,13 @@ const IntToEnumNumber = enum {
|
||||
};
|
||||
|
||||
|
||||
test "@enumTagName" {
|
||||
test "@tagName" {
|
||||
assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
||||
comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
||||
}
|
||||
|
||||
fn testEnumTagNameBare(n: BareNumber) -> []const u8 {
|
||||
return @enumTagName(n);
|
||||
return @tagName(n);
|
||||
}
|
||||
|
||||
const BareNumber = enum {
|
||||
@ -132,12 +132,11 @@ test "enum alignment" {
|
||||
}
|
||||
}
|
||||
|
||||
const AlignTestEnum = enum {
|
||||
const AlignTestEnum = union(enum) {
|
||||
A: [9]u8,
|
||||
B: u64,
|
||||
};
|
||||
|
||||
const ValueCount0 = enum {};
|
||||
const ValueCount1 = enum { I0 };
|
||||
const ValueCount2 = enum { I0, I1 };
|
||||
const ValueCount256 = enum {
|
||||
@ -183,10 +182,165 @@ const ValueCount257 = enum {
|
||||
|
||||
test "enum sizes" {
|
||||
comptime {
|
||||
assert(@sizeOf(ValueCount0) == 0);
|
||||
assert(@sizeOf(ValueCount1) == 0);
|
||||
assert(@sizeOf(ValueCount2) == 1);
|
||||
assert(@sizeOf(ValueCount256) == 1);
|
||||
assert(@sizeOf(ValueCount257) == 2);
|
||||
}
|
||||
}
|
||||
|
||||
const Small2 = enum (u2) {
|
||||
One,
|
||||
Two,
|
||||
};
|
||||
const Small = enum (u2) {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
};
|
||||
|
||||
test "set enum tag type" {
|
||||
{
|
||||
var x = Small.One;
|
||||
x = Small.Two;
|
||||
comptime assert(@TagType(Small) == u2);
|
||||
}
|
||||
{
|
||||
var x = Small2.One;
|
||||
x = Small2.Two;
|
||||
comptime assert(@TagType(Small2) == u2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const A = enum (u3) {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
One2,
|
||||
Two2,
|
||||
Three2,
|
||||
Four2,
|
||||
};
|
||||
|
||||
const B = enum (u3) {
|
||||
One3,
|
||||
Two3,
|
||||
Three3,
|
||||
Four3,
|
||||
One23,
|
||||
Two23,
|
||||
Three23,
|
||||
Four23,
|
||||
};
|
||||
|
||||
const C = enum (u2) {
|
||||
One4,
|
||||
Two4,
|
||||
Three4,
|
||||
Four4,
|
||||
};
|
||||
|
||||
const BitFieldOfEnums = packed struct {
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
};
|
||||
|
||||
const bit_field_1 = BitFieldOfEnums {
|
||||
.a = A.Two,
|
||||
.b = B.Three3,
|
||||
.c = C.Four4,
|
||||
};
|
||||
|
||||
test "bit field access with enum fields" {
|
||||
var data = bit_field_1;
|
||||
assert(getA(&data) == A.Two);
|
||||
assert(getB(&data) == B.Three3);
|
||||
assert(getC(&data) == C.Four4);
|
||||
comptime assert(@sizeOf(BitFieldOfEnums) == 1);
|
||||
|
||||
data.b = B.Four3;
|
||||
assert(data.b == B.Four3);
|
||||
|
||||
data.a = A.Three;
|
||||
assert(data.a == A.Three);
|
||||
assert(data.b == B.Four3);
|
||||
}
|
||||
|
||||
fn getA(data: &const BitFieldOfEnums) -> A {
|
||||
return data.a;
|
||||
}
|
||||
|
||||
fn getB(data: &const BitFieldOfEnums) -> B {
|
||||
return data.b;
|
||||
}
|
||||
|
||||
fn getC(data: &const BitFieldOfEnums) -> C {
|
||||
return data.c;
|
||||
}
|
||||
|
||||
test "casting enum to its tag type" {
|
||||
testCastEnumToTagType(Small2.Two);
|
||||
comptime testCastEnumToTagType(Small2.Two);
|
||||
}
|
||||
|
||||
fn testCastEnumToTagType(value: Small2) {
|
||||
assert(u2(value) == 1);
|
||||
}
|
||||
|
||||
const MultipleChoice = enum(u32) {
|
||||
A = 20,
|
||||
B = 40,
|
||||
C = 60,
|
||||
D = 1000,
|
||||
};
|
||||
|
||||
test "enum with specified tag values" {
|
||||
testEnumWithSpecifiedTagValues(MultipleChoice.C);
|
||||
comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
|
||||
}
|
||||
|
||||
fn testEnumWithSpecifiedTagValues(x: MultipleChoice) {
|
||||
assert(u32(x) == 60);
|
||||
assert(1234 == switch (x) {
|
||||
MultipleChoice.A => 1,
|
||||
MultipleChoice.B => 2,
|
||||
MultipleChoice.C => u32(1234),
|
||||
MultipleChoice.D => 4,
|
||||
});
|
||||
}
|
||||
|
||||
const MultipleChoice2 = enum(u32) {
|
||||
Unspecified1,
|
||||
A = 20,
|
||||
Unspecified2,
|
||||
B = 40,
|
||||
Unspecified3,
|
||||
C = 60,
|
||||
Unspecified4,
|
||||
D = 1000,
|
||||
Unspecified5,
|
||||
};
|
||||
|
||||
test "enum with specified and unspecified tag values" {
|
||||
testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
|
||||
comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
|
||||
}
|
||||
|
||||
fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) {
|
||||
assert(u32(x) == 1000);
|
||||
assert(1234 == switch (x) {
|
||||
MultipleChoice2.A => 1,
|
||||
MultipleChoice2.B => 2,
|
||||
MultipleChoice2.C => 3,
|
||||
MultipleChoice2.D => u32(1234),
|
||||
MultipleChoice2.Unspecified1 => 5,
|
||||
MultipleChoice2.Unspecified2 => 6,
|
||||
MultipleChoice2.Unspecified3 => 7,
|
||||
MultipleChoice2.Unspecified4 => 8,
|
||||
MultipleChoice2.Unspecified5 => 9,
|
||||
});
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ const assert = @import("std").debug.assert;
|
||||
const mem = @import("std").mem;
|
||||
const fmt = @import("std").fmt;
|
||||
|
||||
const ET = enum {
|
||||
const ET = union(enum) {
|
||||
SINT: i32,
|
||||
UINT: u32,
|
||||
|
||||
@ -15,8 +15,8 @@ const ET = enum {
|
||||
};
|
||||
|
||||
test "enum with members" {
|
||||
const a = ET.SINT { -42 };
|
||||
const b = ET.UINT { 42 };
|
||||
const a = ET { .SINT = -42 };
|
||||
const b = ET { .UINT = 42 };
|
||||
var buf: [20]u8 = undefined;
|
||||
|
||||
assert(%%a.print(buf[0..]) == 3);
|
||||
|
||||
@ -324,8 +324,8 @@ test "constant enum initialization with differing sizes" {
|
||||
test3_1(test3_foo);
|
||||
test3_2(test3_bar);
|
||||
}
|
||||
const Test3Foo = enum {
|
||||
One,
|
||||
const Test3Foo = union(enum) {
|
||||
One: void,
|
||||
Two: f32,
|
||||
Three: Test3Point,
|
||||
};
|
||||
@ -333,8 +333,8 @@ const Test3Point = struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
};
|
||||
const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}};
|
||||
const test3_bar = Test3Foo.Two{13};
|
||||
const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}};
|
||||
const test3_bar = Test3Foo { .Two = 13};
|
||||
fn test3_1(f: &const Test3Foo) {
|
||||
switch (*f) {
|
||||
Test3Foo.Three => |pt| {
|
||||
@ -449,7 +449,8 @@ fn testArray2DConstDoublePtr(ptr: &const f32) {
|
||||
const Tid = builtin.TypeId;
|
||||
const AStruct = struct { x: i32, };
|
||||
const AnEnum = enum { One, Two, };
|
||||
const AnEnumWithPayload = enum { One: i32, Two, };
|
||||
const AUnionEnum = union(enum) { One: i32, Two: void, };
|
||||
const AUnion = union { One: void, Two: void };
|
||||
|
||||
test "@typeId" {
|
||||
comptime {
|
||||
@ -474,8 +475,9 @@ test "@typeId" {
|
||||
assert(@typeId(%i32) == Tid.ErrorUnion);
|
||||
assert(@typeId(error) == Tid.Error);
|
||||
assert(@typeId(AnEnum) == Tid.Enum);
|
||||
assert(@typeId(@typeOf(AnEnumWithPayload.One)) == Tid.EnumTag);
|
||||
// TODO union
|
||||
assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
|
||||
assert(@typeId(AUnionEnum) == Tid.Union);
|
||||
assert(@typeId(AUnion) == Tid.Union);
|
||||
assert(@typeId(fn()) == Tid.Fn);
|
||||
assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
|
||||
assert(@typeId(@typeOf({this})) == Tid.Block);
|
||||
|
||||
@ -62,8 +62,8 @@ const Foo = struct {
|
||||
three: void,
|
||||
};
|
||||
|
||||
const Bar = enum {
|
||||
One,
|
||||
const Bar = union(enum) {
|
||||
One: void,
|
||||
Two: i32,
|
||||
Three: bool,
|
||||
Four: f64,
|
||||
|
||||
@ -83,14 +83,14 @@ const SwitchStatmentFoo = enum {
|
||||
|
||||
|
||||
test "switch prong with variable" {
|
||||
switchProngWithVarFn(SwitchProngWithVarEnum.One {13});
|
||||
switchProngWithVarFn(SwitchProngWithVarEnum.Two {13.0});
|
||||
switchProngWithVarFn(SwitchProngWithVarEnum.Meh);
|
||||
switchProngWithVarFn(SwitchProngWithVarEnum { .One = 13});
|
||||
switchProngWithVarFn(SwitchProngWithVarEnum { .Two = 13.0});
|
||||
switchProngWithVarFn(SwitchProngWithVarEnum { .Meh = {}});
|
||||
}
|
||||
const SwitchProngWithVarEnum = enum {
|
||||
const SwitchProngWithVarEnum = union(enum) {
|
||||
One: i32,
|
||||
Two: f32,
|
||||
Meh,
|
||||
Meh: void,
|
||||
};
|
||||
fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) {
|
||||
switch(*a) {
|
||||
@ -112,7 +112,7 @@ test "switch on enum using pointer capture" {
|
||||
}
|
||||
|
||||
fn testSwitchEnumPtrCapture() {
|
||||
var value = SwitchProngWithVarEnum.One { 1234 };
|
||||
var value = SwitchProngWithVarEnum { .One = 1234 };
|
||||
switch (value) {
|
||||
SwitchProngWithVarEnum.One => |*x| *x += 1,
|
||||
else => unreachable,
|
||||
@ -136,13 +136,13 @@ fn returnsFive() -> i32 {
|
||||
}
|
||||
|
||||
|
||||
const Number = enum {
|
||||
const Number = union(enum) {
|
||||
One: u64,
|
||||
Two: u8,
|
||||
Three: f32,
|
||||
};
|
||||
|
||||
const number = Number.Three { 1.23 };
|
||||
const number = Number { .Three = 1.23 };
|
||||
|
||||
fn returnsFalse() -> bool {
|
||||
switch (number) {
|
||||
@ -224,3 +224,14 @@ fn switchWithUnreachable(x: i32) -> i32 {
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
fn return_a_number() -> %i32 {
|
||||
return 1;
|
||||
}
|
||||
|
||||
test "capture value of switch with all unreachable prongs" {
|
||||
const x = return_a_number() %% |err| switch (err) {
|
||||
else => unreachable,
|
||||
};
|
||||
assert(x == 1);
|
||||
}
|
||||
|
||||
@ -9,14 +9,14 @@ fn readOnce() -> %u64 {
|
||||
|
||||
error InvalidDebugInfo;
|
||||
|
||||
const FormValue = enum {
|
||||
const FormValue = union(enum) {
|
||||
Address: u64,
|
||||
Other: bool,
|
||||
};
|
||||
|
||||
fn doThing(form_id: u64) -> %FormValue {
|
||||
return switch (form_id) {
|
||||
17 => FormValue.Address { %return readOnce() },
|
||||
17 => FormValue { .Address = %return readOnce() },
|
||||
else => error.InvalidDebugInfo,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
const FormValue = enum {
|
||||
One,
|
||||
const FormValue = union(enum) {
|
||||
One: void,
|
||||
Two: bool,
|
||||
};
|
||||
|
||||
@ -9,8 +9,8 @@ error Whatever;
|
||||
|
||||
fn foo(id: u64) -> %FormValue {
|
||||
switch (id) {
|
||||
2 => FormValue.Two { true },
|
||||
1 => FormValue.One,
|
||||
2 => FormValue { .Two = true },
|
||||
1 => FormValue { .One = {} },
|
||||
else => return error.Whatever,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
const Value = enum {
|
||||
const Value = union(enum) {
|
||||
Int: u64,
|
||||
Array: [9]u8,
|
||||
};
|
||||
@ -10,8 +10,8 @@ const Agg = struct {
|
||||
val2: Value,
|
||||
};
|
||||
|
||||
const v1 = Value.Int { 1234 };
|
||||
const v2 = Value.Array { []u8{3} ** 9 };
|
||||
const v1 = Value { .Int = 1234 };
|
||||
const v2 = Value { .Array = []u8{3} ** 9 };
|
||||
|
||||
const err = (%Agg)(Agg {
|
||||
.val1 = v1,
|
||||
@ -75,3 +75,118 @@ test "basic extern unions" {
|
||||
assert(foo.float == 12.34);
|
||||
}
|
||||
|
||||
|
||||
const Letter = enum {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
};
|
||||
const Payload = union(Letter) {
|
||||
A: i32,
|
||||
B: f64,
|
||||
C: bool,
|
||||
};
|
||||
|
||||
test "union with specified enum tag" {
|
||||
doTest();
|
||||
comptime doTest();
|
||||
}
|
||||
|
||||
fn doTest() {
|
||||
assert(bar(Payload {.A = 1234}) == -10);
|
||||
}
|
||||
|
||||
fn bar(value: &const Payload) -> i32 {
|
||||
assert(Letter(*value) == Letter.A);
|
||||
return switch (*value) {
|
||||
Payload.A => |x| return x - 1244,
|
||||
Payload.B => |x| if (x == 12.34) i32(20) else 21,
|
||||
Payload.C => |x| if (x) i32(30) else 31,
|
||||
};
|
||||
}
|
||||
|
||||
const MultipleChoice = union(enum(u32)) {
|
||||
A = 20,
|
||||
B = 40,
|
||||
C = 60,
|
||||
D = 1000,
|
||||
};
|
||||
test "simple union(enum(u32))" {
|
||||
var x = MultipleChoice.C;
|
||||
assert(x == MultipleChoice.C);
|
||||
assert(u32(@TagType(MultipleChoice)(x)) == 60);
|
||||
}
|
||||
|
||||
const MultipleChoice2 = union(enum(u32)) {
|
||||
Unspecified1: i32,
|
||||
A: f32 = 20,
|
||||
Unspecified2: void,
|
||||
B: bool = 40,
|
||||
Unspecified3: i32,
|
||||
C: i8 = 60,
|
||||
Unspecified4: void,
|
||||
D: void = 1000,
|
||||
Unspecified5: i32,
|
||||
};
|
||||
|
||||
test "union(enum(u32)) with specified and unspecified tag values" {
|
||||
comptime assert(@TagType(@TagType(MultipleChoice2)) == u32);
|
||||
testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 {.C = 123});
|
||||
comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 { .C = 123} );
|
||||
}
|
||||
|
||||
fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) {
|
||||
assert(u32(@TagType(MultipleChoice2)(*x)) == 60);
|
||||
assert(1123 == switch (*x) {
|
||||
MultipleChoice2.A => 1,
|
||||
MultipleChoice2.B => 2,
|
||||
MultipleChoice2.C => |v| i32(1000) + v,
|
||||
MultipleChoice2.D => 4,
|
||||
MultipleChoice2.Unspecified1 => 5,
|
||||
MultipleChoice2.Unspecified2 => 6,
|
||||
MultipleChoice2.Unspecified3 => 7,
|
||||
MultipleChoice2.Unspecified4 => 8,
|
||||
MultipleChoice2.Unspecified5 => 9,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const ExternPtrOrInt = extern union {
|
||||
ptr: &u8,
|
||||
int: u64
|
||||
};
|
||||
test "extern union size" {
|
||||
comptime assert(@sizeOf(ExternPtrOrInt) == 8);
|
||||
}
|
||||
|
||||
const PackedPtrOrInt = packed union {
|
||||
ptr: &u8,
|
||||
int: u64
|
||||
};
|
||||
test "extern union size" {
|
||||
comptime assert(@sizeOf(PackedPtrOrInt) == 8);
|
||||
}
|
||||
|
||||
const ZeroBits = union {
|
||||
OnlyField: void,
|
||||
};
|
||||
test "union with only 1 field which is void should be zero bits" {
|
||||
comptime assert(@sizeOf(ZeroBits) == 0);
|
||||
}
|
||||
|
||||
const TheTag = enum {A, B, C};
|
||||
const TheUnion = union(TheTag) { A: i32, B: i32, C: i32 };
|
||||
test "union field access gives the enum values" {
|
||||
assert(TheUnion.A == TheTag.A);
|
||||
assert(TheUnion.B == TheTag.B);
|
||||
assert(TheUnion.C == TheTag.C);
|
||||
}
|
||||
|
||||
test "cast union to tag type of union" {
|
||||
testCastUnionToTagType(TheUnion {.B = 1234});
|
||||
comptime testCastUnionToTagType(TheUnion {.B = 1234});
|
||||
}
|
||||
|
||||
fn testCastUnionToTagType(x: &const TheUnion) {
|
||||
assert(TheTag(*x) == TheTag.B);
|
||||
}
|
||||
|
||||
@ -930,8 +930,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
\\fn bad_eql_1(a: []u8, b: []u8) -> bool {
|
||||
\\ a == b
|
||||
\\}
|
||||
\\const EnumWithData = enum {
|
||||
\\ One,
|
||||
\\const EnumWithData = union(enum) {
|
||||
\\ One: void,
|
||||
\\ Two: i32,
|
||||
\\};
|
||||
\\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) -> bool {
|
||||
@ -1145,19 +1145,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
\\const JasonHM = u8;
|
||||
\\const JasonList = &JsonNode;
|
||||
\\
|
||||
\\const JsonOA = enum {
|
||||
\\const JsonOA = union(enum) {
|
||||
\\ JSONArray: JsonList,
|
||||
\\ JSONObject: JasonHM,
|
||||
\\};
|
||||
\\
|
||||
\\const JsonType = enum {
|
||||
\\const JsonType = union(enum) {
|
||||
\\ JSONNull: void,
|
||||
\\ JSONInteger: isize,
|
||||
\\ JSONDouble: f64,
|
||||
\\ JSONBool: bool,
|
||||
\\ JSONString: []u8,
|
||||
\\ JSONArray,
|
||||
\\ JSONObject,
|
||||
\\ JSONArray: void,
|
||||
\\ JSONObject: void,
|
||||
\\};
|
||||
\\
|
||||
\\pub const JsonNode = struct {
|
||||
@ -2138,7 +2138,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
\\
|
||||
\\const MdText = ArrayList(u8);
|
||||
\\
|
||||
\\const MdNode = enum {
|
||||
\\const MdNode = union(enum) {
|
||||
\\ Header: struct {
|
||||
\\ text: MdText,
|
||||
\\ weight: HeaderValue,
|
||||
@ -2297,6 +2297,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
,
|
||||
".tmp_source.zig:2:21: error: type 'i32' does not support @memberType");
|
||||
|
||||
cases.add("@memberType on enum",
|
||||
\\comptime {
|
||||
\\ _ = @memberType(Foo, 0);
|
||||
\\}
|
||||
\\const Foo = enum {A,};
|
||||
,
|
||||
".tmp_source.zig:2:21: error: type 'Foo' does not support @memberType");
|
||||
|
||||
cases.add("@memberType struct out of bounds",
|
||||
\\comptime {
|
||||
\\ _ = @memberType(Foo, 0);
|
||||
@ -2305,13 +2313,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
,
|
||||
".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members");
|
||||
|
||||
cases.add("@memberType enum out of bounds",
|
||||
cases.add("@memberType union out of bounds",
|
||||
\\comptime {
|
||||
\\ _ = @memberType(Foo, 0);
|
||||
\\ _ = @memberType(Foo, 1);
|
||||
\\}
|
||||
\\const Foo = enum {};
|
||||
\\const Foo = union {A: void,};
|
||||
,
|
||||
".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members");
|
||||
".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");
|
||||
|
||||
cases.add("@memberName on unsupported type",
|
||||
\\comptime {
|
||||
@ -2330,11 +2338,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
|
||||
cases.add("@memberName enum out of bounds",
|
||||
\\comptime {
|
||||
\\ _ = @memberName(Foo, 0);
|
||||
\\ _ = @memberName(Foo, 1);
|
||||
\\}
|
||||
\\const Foo = enum {};
|
||||
\\const Foo = enum {A,};
|
||||
,
|
||||
".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members");
|
||||
".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");
|
||||
|
||||
cases.add("@memberName union out of bounds",
|
||||
\\comptime {
|
||||
\\ _ = @memberName(Foo, 1);
|
||||
\\}
|
||||
\\const Foo = union {A:i32,};
|
||||
,
|
||||
".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");
|
||||
|
||||
cases.add("calling var args extern function, passing array instead of pointer",
|
||||
\\export fn entry() {
|
||||
@ -2362,4 +2378,310 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
".tmp_source.zig:4:25: error: aoeu",
|
||||
".tmp_source.zig:1:36: note: called from here",
|
||||
".tmp_source.zig:12:20: note: referenced here");
|
||||
|
||||
cases.add("specify enum tag type that is too small",
|
||||
\\const Small = enum (u2) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\ Four,
|
||||
\\ Five,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var x = Small.One;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:20: error: 'u2' too small to hold all bits; must be at least 'u3'");
|
||||
|
||||
cases.add("specify non-integer enum tag type",
|
||||
\\const Small = enum (f32) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var x = Small.One;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:20: error: expected integer, found 'f32'");
|
||||
|
||||
cases.add("implicitly casting enum to tag type",
|
||||
\\const Small = enum(u2) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\ Four,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var x: u2 = Small.Two;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'");
|
||||
|
||||
cases.add("explicitly casting enum to non tag type",
|
||||
\\const Small = enum(u2) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\ Four,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var x = u3(Small.Two);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:9:15: error: enum to integer cast to 'u3' instead of its tag type, 'u2'");
|
||||
|
||||
cases.add("explicitly casting non tag type to enum",
|
||||
\\const Small = enum(u2) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\ Four,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var y = u3(3);
|
||||
\\ var x = Small(y);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:10:18: error: integer to enum cast from 'u3' instead of its tag type, 'u2'");
|
||||
|
||||
cases.add("non unsigned integer enum tag type",
|
||||
\\const Small = enum(i2) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\ Four,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var y = Small.Two;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'");
|
||||
|
||||
cases.add("struct fields with value assignments",
|
||||
\\const MultipleChoice = struct {
|
||||
\\ A: i32 = 20,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var x: MultipleChoice = undefined;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:14: error: enums, not structs, support field assignment");
|
||||
|
||||
cases.add("union fields with value assignments",
|
||||
\\const MultipleChoice = union {
|
||||
\\ A: i32 = 20,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var x: MultipleChoice = undefined;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:14: error: non-enum union field assignment",
|
||||
".tmp_source.zig:1:24: note: consider 'union(enum)' here");
|
||||
|
||||
cases.add("enum with 0 fields",
|
||||
\\const Foo = enum {};
|
||||
\\export fn entry() -> usize {
|
||||
\\ return @sizeOf(Foo);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:13: error: enums must have 1 or more fields");
|
||||
|
||||
cases.add("union with 0 fields",
|
||||
\\const Foo = union {};
|
||||
\\export fn entry() -> usize {
|
||||
\\ return @sizeOf(Foo);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:13: error: unions must have 1 or more fields");
|
||||
|
||||
cases.add("enum value already taken",
|
||||
\\const MultipleChoice = enum(u32) {
|
||||
\\ A = 20,
|
||||
\\ B = 40,
|
||||
\\ C = 60,
|
||||
\\ D = 1000,
|
||||
\\ E = 60,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var x = MultipleChoice.C;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:9: error: enum tag value 60 already taken",
|
||||
".tmp_source.zig:4:9: note: other occurrence here");
|
||||
|
||||
cases.add("union with specified enum omits field",
|
||||
\\const Letter = enum {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\ C,
|
||||
\\};
|
||||
\\const Payload = union(Letter) {
|
||||
\\ A: i32,
|
||||
\\ B: f64,
|
||||
\\};
|
||||
\\export fn entry() -> usize {
|
||||
\\ return @sizeOf(Payload);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:17: error: enum field missing: 'C'",
|
||||
".tmp_source.zig:4:5: note: declared here");
|
||||
|
||||
cases.add("@TagType when union has no attached enum",
|
||||
\\const Foo = union {
|
||||
\\ A: i32,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ const x = @TagType(Foo);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:5:24: error: union 'Foo' has no tag",
|
||||
".tmp_source.zig:1:13: note: consider 'union(enum)' here");
|
||||
|
||||
cases.add("non-integer tag type to automatic union enum",
|
||||
\\const Foo = union(enum(f32)) {
|
||||
\\ A: i32,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ const x = @TagType(Foo);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:23: error: expected integer tag type, found 'f32'");
|
||||
|
||||
cases.add("non-enum tag type passed to union",
|
||||
\\const Foo = union(u32) {
|
||||
\\ A: i32,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ const x = @TagType(Foo);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:18: error: expected enum tag type, found 'u32'");
|
||||
|
||||
cases.add("union auto-enum value already taken",
|
||||
\\const MultipleChoice = union(enum(u32)) {
|
||||
\\ A = 20,
|
||||
\\ B = 40,
|
||||
\\ C = 60,
|
||||
\\ D = 1000,
|
||||
\\ E = 60,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var x = MultipleChoice { .C = {} };
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:9: error: enum tag value 60 already taken",
|
||||
".tmp_source.zig:4:9: note: other occurrence here");
|
||||
|
||||
cases.add("union enum field does not match enum",
|
||||
\\const Letter = enum {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\ C,
|
||||
\\};
|
||||
\\const Payload = union(Letter) {
|
||||
\\ A: i32,
|
||||
\\ B: f64,
|
||||
\\ C: bool,
|
||||
\\ D: bool,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var a = Payload {.A = 1234};
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:10:5: error: enum field not found: 'D'",
|
||||
".tmp_source.zig:1:16: note: enum declared here");
|
||||
|
||||
cases.add("field type supplied in an enum",
|
||||
\\const Letter = enum {
|
||||
\\ A: void,
|
||||
\\ B,
|
||||
\\ C,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var b = Letter.B;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:8: error: structs and unions, not enums, support field types",
|
||||
".tmp_source.zig:1:16: note: consider 'union(enum)' here");
|
||||
|
||||
cases.add("struct field missing type",
|
||||
\\const Letter = struct {
|
||||
\\ A,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var a = Letter { .A = {} };
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:5: error: struct field missing type");
|
||||
|
||||
cases.add("extern union field missing type",
|
||||
\\const Letter = extern union {
|
||||
\\ A,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var a = Letter { .A = {} };
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:5: error: union field missing type");
|
||||
|
||||
cases.add("extern union given enum tag type",
|
||||
\\const Letter = enum {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\ C,
|
||||
\\};
|
||||
\\const Payload = extern union(Letter) {
|
||||
\\ A: i32,
|
||||
\\ B: f64,
|
||||
\\ C: bool,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var a = Payload { .A = { 1234 } };
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:29: error: extern union does not support enum tag type");
|
||||
|
||||
cases.add("packed union given enum tag type",
|
||||
\\const Letter = enum {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\ C,
|
||||
\\};
|
||||
\\const Payload = packed union(Letter) {
|
||||
\\ A: i32,
|
||||
\\ B: f64,
|
||||
\\ C: bool,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ var a = Payload { .A = { 1234 } };
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:29: error: packed union does not support enum tag type");
|
||||
|
||||
cases.add("switch on union with no attached enum",
|
||||
\\const Payload = union {
|
||||
\\ A: i32,
|
||||
\\ B: f64,
|
||||
\\ C: bool,
|
||||
\\};
|
||||
\\export fn entry() {
|
||||
\\ const a = Payload { .A = { 1234 } };
|
||||
\\ foo(a);
|
||||
\\}
|
||||
\\fn foo(a: &const Payload) {
|
||||
\\ switch (*a) {
|
||||
\\ Payload.A => {},
|
||||
\\ else => unreachable,
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:11:13: error: switch on union which has no attached enum",
|
||||
".tmp_source.zig:1:17: note: consider 'union(enum)' here");
|
||||
}
|
||||
|
||||
@ -150,8 +150,8 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons
|
||||
continue;
|
||||
}
|
||||
const these_tests = b.addTest(root_src);
|
||||
these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @enumTagName(test_target.os),
|
||||
@enumTagName(test_target.arch), @enumTagName(mode), if (link_libc) "c" else "bare"));
|
||||
these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os),
|
||||
@tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
|
||||
these_tests.setFilter(test_filter);
|
||||
these_tests.setBuildMode(mode);
|
||||
if (!is_native) {
|
||||
@ -428,7 +428,7 @@ pub const CompareOutputContext = struct {
|
||||
Special.None => {
|
||||
for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
|
||||
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})",
|
||||
"compare-output", case.name, @enumTagName(mode));
|
||||
"compare-output", case.name, @tagName(mode));
|
||||
if (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
continue;
|
||||
@ -682,7 +682,7 @@ pub const CompileErrorContext = struct {
|
||||
|
||||
for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
|
||||
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})",
|
||||
case.name, @enumTagName(mode));
|
||||
case.name, @tagName(mode));
|
||||
if (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
continue;
|
||||
@ -750,7 +750,7 @@ pub const BuildExamplesContext = struct {
|
||||
|
||||
for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
|
||||
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})",
|
||||
root_src, @enumTagName(mode));
|
||||
root_src, @tagName(mode));
|
||||
if (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
continue;
|
||||
|
||||
@ -1178,4 +1178,14 @@ pub fn addCases(cases: &tests.TranslateCContext) {
|
||||
,
|
||||
\\pub var v0: ?&const u8 = c"0.0.0";
|
||||
);
|
||||
|
||||
cases.add("static incomplete array inside function",
|
||||
\\void foo(void) {
|
||||
\\ static const char v2[] = "2.2.2";
|
||||
\\}
|
||||
,
|
||||
\\pub fn foo() {
|
||||
\\ const v2: &const u8 = c"2.2.2";
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user