aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhryx <codroid@gmail.com>2019-05-12 02:00:49 -0700
committerhryx <codroid@gmail.com>2019-05-12 02:00:49 -0700
commit3787f3428625e830fd852a8f5a40c7d8a2d429f6 (patch)
tree23fb493b9d2f07c7abe57955874682959936319a
parent16aee1f58a80295f7599a8290d764a5c7040c373 (diff)
parentedcc7c72d1a684a8a16ca23ad26689f2cce4e803 (diff)
downloadzig-3787f3428625e830fd852a8f5a40c7d8a2d429f6.tar.gz
zig-3787f3428625e830fd852a8f5a40c7d8a2d429f6.zip
Merge branch 'master' into rebased
-rw-r--r--CMakeLists.txt111
-rw-r--r--README.md242
-rw-r--r--build.zig27
-rwxr-xr-xci/azure/windows_upload2
-rw-r--r--cmake/Findclang.cmake2
-rw-r--r--deps/lld/wasm/OutputSections.cpp12
-rw-r--r--doc/docgen.zig55
-rw-r--r--doc/langref.html.in109
-rw-r--r--src-self-hosted/clang.zig866
-rw-r--r--src-self-hosted/compilation.zig10
-rw-r--r--src-self-hosted/main.zig18
-rw-r--r--src-self-hosted/scope.zig1
-rw-r--r--src-self-hosted/stage1.zig (renamed from std/special/fmt_runner.zig)209
-rw-r--r--src-self-hosted/translate_c.zig682
-rw-r--r--src-self-hosted/value.zig8
-rw-r--r--src/all_types.hpp13
-rw-r--r--src/analyze.cpp153
-rw-r--r--src/analyze.hpp4
-rw-r--r--src/ast_render.cpp6
-rw-r--r--src/ast_render.hpp2
-rw-r--r--src/bigint.cpp13
-rw-r--r--src/buffer.hpp1
-rw-r--r--src/c_tokenizer.cpp20
-rw-r--r--src/c_tokenizer.hpp3
-rw-r--r--src/cache_hash.cpp28
-rw-r--r--src/codegen.cpp509
-rw-r--r--src/codegen.hpp4
-rw-r--r--src/compiler.cpp8
-rw-r--r--src/compiler.hpp4
-rw-r--r--src/error.cpp4
-rw-r--r--src/error.hpp50
-rw-r--r--src/ir.cpp379
-rw-r--r--src/ir.hpp2
-rw-r--r--src/ir_print.cpp9
-rw-r--r--src/libc_installation.cpp36
-rw-r--r--src/libc_installation.hpp3
-rw-r--r--src/link.cpp308
-rw-r--r--src/list.hpp2
-rw-r--r--src/main.cpp169
-rw-r--r--src/os.cpp53
-rw-r--r--src/os.hpp6
-rw-r--r--src/parser.cpp114
-rw-r--r--src/target.cpp27
-rw-r--r--src/target.hpp2
-rw-r--r--src/translate_c.cpp3219
-rw-r--r--src/translate_c.hpp6
-rw-r--r--src/userland.cpp44
-rw-r--r--src/userland.h120
-rw-r--r--src/util.cpp10
-rw-r--r--src/util.hpp4
-rw-r--r--src/zig_clang.cpp1717
-rw-r--r--src/zig_clang.h801
-rw-r--r--std/array_list.zig38
-rw-r--r--std/build.zig27
-rw-r--r--std/c.zig6
-rw-r--r--std/c/freebsd.zig32
-rw-r--r--std/c/linux.zig4
-rw-r--r--std/c/netbsd.zig32
-rw-r--r--std/crypto/chacha20.zig5
-rw-r--r--std/debug.zig630
-rw-r--r--std/debug/failing_allocator.zig18
-rw-r--r--std/debug/leb128.zig228
-rw-r--r--std/dwarf.zig4
-rw-r--r--std/dynamic_library.zig83
-rw-r--r--std/elf.zig5
-rw-r--r--std/fmt.zig108
-rw-r--r--std/hash_map.zig83
-rw-r--r--std/heap.zig478
-rw-r--r--std/io.zig41
-rw-r--r--std/io/c_out_stream.zig48
-rw-r--r--std/io/seekable_stream.zig16
-rw-r--r--std/io/test.zig (renamed from std/io_test.zig)13
-rw-r--r--std/json.zig4
-rw-r--r--std/json/test.zig1904
-rw-r--r--std/json_test.zig1904
-rw-r--r--std/math/acos.zig10
-rw-r--r--std/math/acosh.zig12
-rw-r--r--std/math/asin.zig12
-rw-r--r--std/math/asinh.zig14
-rw-r--r--std/math/atan.zig12
-rw-r--r--std/math/atan2.zig42
-rw-r--r--std/math/atanh.zig14
-rw-r--r--std/math/big.zig2
-rw-r--r--std/math/big/int.zig786
-rw-r--r--std/math/big/rational.zig938
-rw-r--r--std/math/cbrt.zig14
-rw-r--r--std/math/ceil.zig14
-rw-r--r--std/math/complex.zig12
-rw-r--r--std/math/complex/abs.zig1
-rw-r--r--std/math/complex/acos.zig1
-rw-r--r--std/math/complex/acosh.zig1
-rw-r--r--std/math/complex/arg.zig1
-rw-r--r--std/math/complex/asin.zig1
-rw-r--r--std/math/complex/asinh.zig1
-rw-r--r--std/math/complex/atan.zig7
-rw-r--r--std/math/complex/atanh.zig1
-rw-r--r--std/math/complex/conj.zig1
-rw-r--r--std/math/complex/cos.zig1
-rw-r--r--std/math/complex/cosh.zig7
-rw-r--r--std/math/complex/exp.zig7
-rw-r--r--std/math/complex/ldexp.zig7
-rw-r--r--std/math/complex/log.zig1
-rw-r--r--std/math/complex/pow.zig1
-rw-r--r--std/math/complex/proj.zig1
-rw-r--r--std/math/complex/sin.zig1
-rw-r--r--std/math/complex/sinh.zig7
-rw-r--r--std/math/complex/sqrt.zig8
-rw-r--r--std/math/complex/tan.zig1
-rw-r--r--std/math/complex/tanh.zig7
-rw-r--r--std/math/copysign.zig7
-rw-r--r--std/math/cos.zig146
-rw-r--r--std/math/cosh.zig14
-rw-r--r--std/math/exp.zig12
-rw-r--r--std/math/exp2.zig12
-rw-r--r--std/math/expm1.zig17
-rw-r--r--std/math/expo2.zig7
-rw-r--r--std/math/fabs.zig12
-rw-r--r--std/math/floor.zig14
-rw-r--r--std/math/fma.zig10
-rw-r--r--std/math/frexp.zig15
-rw-r--r--std/math/hypot.zig16
-rw-r--r--std/math/ilogb.zig14
-rw-r--r--std/math/inf.zig1
-rw-r--r--std/math/isfinite.zig1
-rw-r--r--std/math/isinf.zig3
-rw-r--r--std/math/isnan.zig6
-rw-r--r--std/math/isnormal.zig1
-rw-r--r--std/math/ln.zig16
-rw-r--r--std/math/log.zig7
-rw-r--r--std/math/log10.zig16
-rw-r--r--std/math/log1p.zig18
-rw-r--r--std/math/log2.zig16
-rw-r--r--std/math/modf.zig13
-rw-r--r--std/math/nan.zig6
-rw-r--r--std/math/pow.zig96
-rw-r--r--std/math/powi.zig22
-rw-r--r--std/math/round.zig14
-rw-r--r--std/math/scalbn.zig7
-rw-r--r--std/math/signbit.zig1
-rw-r--r--std/math/sin.zig160
-rw-r--r--std/math/sinh.zig14
-rw-r--r--std/math/sqrt.zig14
-rw-r--r--std/math/tan.zig154
-rw-r--r--std/math/tanh.zig14
-rw-r--r--std/math/trunc.zig14
-rw-r--r--std/mem.zig52
-rw-r--r--std/os.zig118
-rw-r--r--std/os/darwin.zig2
-rw-r--r--std/os/file.zig28
-rw-r--r--std/os/linux.zig166
-rw-r--r--std/os/linux/arm64.zig19
-rw-r--r--std/os/linux/test.zig41
-rw-r--r--std/os/linux/tls.zig247
-rw-r--r--std/os/linux/x86_64.zig25
-rw-r--r--std/os/time.zig30
-rw-r--r--std/os/wasi.zig42
-rw-r--r--std/os/wasi/core.zig374
-rw-r--r--std/os/windows.zig31
-rw-r--r--std/os/windows/kernel32.zig3
-rw-r--r--std/packed_int_array.zig649
-rw-r--r--std/pdb.zig13
-rw-r--r--std/rand.zig4
-rw-r--r--std/special/bootstrap.zig74
-rw-r--r--std/special/build_runner.zig30
-rw-r--r--std/special/compiler_rt.zig687
-rw-r--r--std/special/compiler_rt/addXf3.zig4
-rw-r--r--std/special/compiler_rt/arm/aeabi_dcmp.zig108
-rw-r--r--std/special/compiler_rt/arm/aeabi_fcmp.zig108
-rw-r--r--std/special/compiler_rt/ashlti3.zig41
-rw-r--r--std/special/compiler_rt/ashlti3_test.zig46
-rw-r--r--std/special/compiler_rt/ashrti3.zig42
-rw-r--r--std/special/compiler_rt/ashrti3_test.zig58
-rw-r--r--std/special/compiler_rt/comparedf2.zig122
-rw-r--r--std/special/compiler_rt/comparedf2_test.zig101
-rw-r--r--std/special/compiler_rt/comparesf2.zig122
-rw-r--r--std/special/compiler_rt/comparesf2_test.zig101
-rw-r--r--std/special/compiler_rt/divti3.zig6
-rw-r--r--std/special/compiler_rt/extendXfYf2.zig14
-rw-r--r--std/special/compiler_rt/floatdidf.zig22
-rw-r--r--std/special/compiler_rt/floatdidf_test.zig53
-rw-r--r--std/special/compiler_rt/floatsiXf.zig109
-rw-r--r--std/special/compiler_rt/floatundidf.zig24
-rw-r--r--std/special/compiler_rt/floatundidf_test.zig50
-rw-r--r--std/special/compiler_rt/floatunsidf.zig33
-rw-r--r--std/special/compiler_rt/lshrti3.zig41
-rw-r--r--std/special/compiler_rt/lshrti3_test.zig46
-rw-r--r--std/special/compiler_rt/modti3.zig6
-rw-r--r--std/special/compiler_rt/mulodi4.zig44
-rw-r--r--std/special/compiler_rt/mulodi4_test.zig85
-rw-r--r--std/special/compiler_rt/muloti4.zig10
-rw-r--r--std/special/compiler_rt/multi3.zig6
-rw-r--r--std/special/compiler_rt/stack_probe.zig206
-rw-r--r--std/special/compiler_rt/truncXfYf2.zig4
-rw-r--r--std/special/compiler_rt/truncXfYf2_test.zig37
-rw-r--r--std/special/compiler_rt/udivmodti4.zig5
-rw-r--r--std/special/compiler_rt/udivti3.zig5
-rw-r--r--std/special/compiler_rt/umodti3.zig6
-rw-r--r--std/special/panic.zig7
-rw-r--r--std/special/test_runner.zig2
-rw-r--r--std/std.zig7
-rw-r--r--std/zig/ast.zig9
-rw-r--r--std/zig/parse.zig338
-rw-r--r--std/zig/parser_test.zig36
-rw-r--r--std/zig/render.zig7
-rw-r--r--test/compile_errors.zig113
-rw-r--r--test/runtime_safety.zig20
-rw-r--r--test/stage1/behavior.zig3
-rw-r--r--test/stage1/behavior/bit_shifting.zig10
-rw-r--r--test/stage1/behavior/bugs/1607.zig15
-rw-r--r--test/stage1/behavior/bugs/2114.zig19
-rw-r--r--test/stage1/behavior/bugs/2346.zig6
-rw-r--r--test/stage1/behavior/enum.zig39
-rw-r--r--test/stage1/behavior/math.zig7
-rw-r--r--test/stage1/behavior/pointers.zig50
-rw-r--r--test/stage1/behavior/sizeof_and_typeof.zig7
-rw-r--r--test/stage1/behavior/struct.zig22
-rw-r--r--test/stage1/behavior/syntax.zig8
-rw-r--r--test/stage1/behavior/union.zig37
-rw-r--r--test/tests.zig36
-rw-r--r--test/translate_c.zig215
220 files changed, 17655 insertions, 6432 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cbd1317bdb..ea367c00a2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,7 +15,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
set(ZIG_VERSION_MAJOR 0)
-set(ZIG_VERSION_MINOR 3)
+set(ZIG_VERSION_MINOR 4)
set(ZIG_VERSION_PATCH 0)
set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}")
@@ -50,10 +50,6 @@ option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead
find_package(llvm)
find_package(clang)
-if(MINGW)
- find_package(z3)
-endif()
-
if(APPLE AND ZIG_STATIC)
list(REMOVE_ITEM LLVM_LIBRARIES "-lz")
find_library(ZLIB NAMES z zlib libz)
@@ -62,6 +58,16 @@ endif()
set(ZIG_CPP_LIB_DIR "${CMAKE_BINARY_DIR}/zig_cpp")
+# Handle multi-config builds and place each into a common lib. The VS generator
+# for example will append a Debug folder by default if not explicitly specified.
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ZIG_CPP_LIB_DIR})
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ZIG_CPP_LIB_DIR})
+foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
+ string(TOUPPER ${CONFIG_TYPE} CONFIG_TYPE)
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_TYPE} ${ZIG_CPP_LIB_DIR})
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONFIG_TYPE} ${ZIG_CPP_LIB_DIR})
+endforeach(CONFIG_TYPE CMAKE_CONFIGURATION_TYPES)
+
if(ZIG_FORCE_EXTERNAL_LLD)
find_package(lld)
include_directories(${LLVM_INCLUDE_DIRS})
@@ -196,7 +202,7 @@ else()
if(MSVC)
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")
else()
- set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment")
+ set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Wno-comment")
if(MINGW)
set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")
endif()
@@ -257,7 +263,6 @@ else()
embedded_lld_wasm
embedded_lld_lib
)
- install(TARGETS embedded_lld_elf embedded_lld_coff embedded_lld_mingw embedded_lld_wasm embedded_lld_lib DESTINATION "${ZIG_CPP_LIB_DIR}")
endif()
# No patches have been applied to SoftFloat-3e
@@ -407,6 +412,12 @@ set(SOFTFLOAT_LIBRARIES embedded_softfloat)
find_package(Threads)
+# CMake doesn't let us create an empty executable, so we hang on to this one separately.
+set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp")
+
+# This is our shim which will be replaced by libuserland written in Zig.
+set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp")
+
set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/analyze.cpp"
"${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
@@ -423,7 +434,6 @@ set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
"${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
"${CMAKE_SOURCE_DIR}/src/link.cpp"
- "${CMAKE_SOURCE_DIR}/src/main.cpp"
"${CMAKE_SOURCE_DIR}/src/os.cpp"
"${CMAKE_SOURCE_DIR}/src/parser.cpp"
"${CMAKE_SOURCE_DIR}/src/range_set.cpp"
@@ -477,6 +487,7 @@ set(ZIG_STD_FILES
"crypto/x25519.zig"
"cstr.zig"
"debug.zig"
+ "debug/leb128.zig"
"debug/failing_allocator.zig"
"dwarf.zig"
"dynamic_library.zig"
@@ -507,6 +518,7 @@ set(ZIG_STD_FILES
"heap.zig"
"io.zig"
"io/seekable_stream.zig"
+ "io/c_out_stream.zig"
"json.zig"
"lazy_init.zig"
"linked_list.zig"
@@ -521,6 +533,7 @@ set(ZIG_STD_FILES
"math/atanh.zig"
"math/big.zig"
"math/big/int.zig"
+ "math/big/rational.zig"
"math/cbrt.zig"
"math/ceil.zig"
"math/complex.zig"
@@ -599,6 +612,7 @@ set(ZIG_STD_FILES
"os/linux.zig"
"os/linux/arm64.zig"
"os/linux/errno.zig"
+ "os/linux/tls.zig"
"os/linux/vdso.zig"
"os/linux/x86_64.zig"
"os/netbsd.zig"
@@ -606,6 +620,8 @@ set(ZIG_STD_FILES
"os/path.zig"
"os/time.zig"
"os/uefi.zig"
+ "os/wasi.zig"
+ "os/wasi/core.zig"
"os/windows.zig"
"os/windows/advapi32.zig"
"os/windows/error.zig"
@@ -615,6 +631,7 @@ set(ZIG_STD_FILES
"os/windows/shell32.zig"
"os/windows/util.zig"
"os/zen.zig"
+ "packed_int_array.zig"
"pdb.zig"
"priority_queue.zig"
"rand.zig"
@@ -628,10 +645,15 @@ set(ZIG_STD_FILES
"special/build_runner.zig"
"special/builtin.zig"
"special/compiler_rt.zig"
+ "special/compiler_rt/stack_probe.zig"
+ "special/compiler_rt/arm/aeabi_fcmp.zig"
+ "special/compiler_rt/arm/aeabi_dcmp.zig"
"special/compiler_rt/addXf3.zig"
"special/compiler_rt/aulldiv.zig"
"special/compiler_rt/aullrem.zig"
"special/compiler_rt/comparetf2.zig"
+ "special/compiler_rt/comparedf2.zig"
+ "special/compiler_rt/comparesf2.zig"
"special/compiler_rt/divsf3.zig"
"special/compiler_rt/divdf3.zig"
"special/compiler_rt/divti3.zig"
@@ -656,9 +678,13 @@ set(ZIG_STD_FILES
"special/compiler_rt/fixunstfdi.zig"
"special/compiler_rt/fixunstfsi.zig"
"special/compiler_rt/fixunstfti.zig"
+ "special/compiler_rt/floatdidf.zig"
+ "special/compiler_rt/floatsiXf.zig"
+ "special/compiler_rt/floatunsidf.zig"
"special/compiler_rt/floattidf.zig"
"special/compiler_rt/floattisf.zig"
"special/compiler_rt/floattitf.zig"
+ "special/compiler_rt/floatundidf.zig"
"special/compiler_rt/floatunditf.zig"
"special/compiler_rt/floatunsitf.zig"
"special/compiler_rt/floatuntidf.zig"
@@ -667,7 +693,11 @@ set(ZIG_STD_FILES
"special/compiler_rt/modti3.zig"
"special/compiler_rt/mulXf3.zig"
"special/compiler_rt/muloti4.zig"
+ "special/compiler_rt/mulodi4.zig"
"special/compiler_rt/multi3.zig"
+ "special/compiler_rt/ashlti3.zig"
+ "special/compiler_rt/ashrti3.zig"
+ "special/compiler_rt/lshrti3.zig"
"special/compiler_rt/negXf2.zig"
"special/compiler_rt/popcountdi2.zig"
"special/compiler_rt/truncXfYf2.zig"
@@ -676,7 +706,6 @@ set(ZIG_STD_FILES
"special/compiler_rt/udivmodti4.zig"
"special/compiler_rt/udivti3.zig"
"special/compiler_rt/umodti3.zig"
- "special/fmt_runner.zig"
"special/init-exe/build.zig"
"special/init-exe/src/main.zig"
"special/init-lib/build.zig"
@@ -6604,7 +6633,7 @@ endif()
if(MSVC)
set(EXE_CFLAGS "${EXE_CFLAGS}")
else()
- set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
+ set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
if(MINGW)
set(EXE_CFLAGS "${EXE_CFLAGS} -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")
endif()
@@ -6639,13 +6668,12 @@ set_target_properties(opt_c_util PROPERTIES
COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"
)
-add_executable(zig ${ZIG_SOURCES})
-set_target_properties(zig PROPERTIES
+add_library(compiler STATIC ${ZIG_SOURCES})
+set_target_properties(compiler PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS}
)
-
-target_link_libraries(zig LINK_PUBLIC
+target_link_libraries(compiler LINK_PUBLIC
zig_cpp
opt_c_util
${SOFTFLOAT_LIBRARIES}
@@ -6654,24 +6682,63 @@ target_link_libraries(zig LINK_PUBLIC
${LLVM_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
-
if(NOT MSVC)
- target_link_libraries(zig LINK_PUBLIC ${LIBXML2})
+ target_link_libraries(compiler LINK_PUBLIC ${LIBXML2})
endif()
if(MINGW)
- target_link_libraries(zig LINK_PUBLIC ${Z3_LIBRARIES})
+ find_library(Z3_LIBRARIES NAMES z3 z3.dll)
+ target_link_libraries(compiler LINK_PUBLIC ${Z3_LIBRARIES})
endif()
if(ZIG_DIA_GUIDS_LIB)
- target_link_libraries(zig LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
+ target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
endif()
if(MSVC OR MINGW)
- target_link_libraries(zig LINK_PUBLIC version)
+ target_link_libraries(compiler LINK_PUBLIC version)
endif()
+
+add_executable(zig0 "${ZIG_MAIN_SRC}" "${ZIG0_SHIM_SRC}")
+set_target_properties(zig0 PROPERTIES
+ COMPILE_FLAGS ${EXE_CFLAGS}
+ LINK_FLAGS ${EXE_LDFLAGS}
+)
+target_link_libraries(zig0 compiler)
+
+if(WIN32)
+ set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib")
+elseif(APPLE)
+ set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.o")
+else()
+ set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a")
+endif()
+add_custom_command(
+ OUTPUT "${LIBUSERLAND}"
+ COMMAND zig0 ARGS build
+ --override-std-dir std
+ --override-lib-dir "${CMAKE_SOURCE_DIR}"
+ libuserland
+ "-Doutput-dir=${CMAKE_BINARY_DIR}"
+ WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
+ DEPENDS
+ "${CMAKE_SOURCE_DIR}/src-self-hosted/stage1.zig"
+ "${CMAKE_SOURCE_DIR}/src-self-hosted/translate_c.zig"
+ "${CMAKE_SOURCE_DIR}/build.zig"
+)
+add_custom_target(userland_target DEPENDS "${LIBUSERLAND}")
+add_executable(zig "${ZIG_MAIN_SRC}")
+if(MINGW)
+ set(EXE_LDFLAGS "${EXE_LDFLAGS} -fstack-protector")
+endif()
+set_target_properties(zig PROPERTIES
+ COMPILE_FLAGS ${EXE_CFLAGS}
+ LINK_FLAGS ${EXE_LDFLAGS}
+)
+target_link_libraries(zig compiler "${LIBUSERLAND}")
+add_dependencies(zig userland_target)
install(TARGETS zig DESTINATION bin)
-install(TARGETS zig_cpp DESTINATION "${ZIG_CPP_LIB_DIR}")
+
foreach(file ${ZIG_C_HEADER_FILES})
get_filename_component(file_dir "${C_HEADERS_DEST}/${file}" DIRECTORY)
@@ -6697,7 +6764,3 @@ foreach(file ${ZIG_LIBCXX_FILES})
get_filename_component(file_dir "${LIBCXX_FILES_DEST}/${file}" DIRECTORY)
install(FILES "${CMAKE_SOURCE_DIR}/libcxx/${file}" DESTINATION "${file_dir}")
endforeach()
-
-install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/arg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
-install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/main.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
-install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/errmsg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
diff --git a/README.md b/README.md
index 77ed6d22c6..4ca79232d8 100644
--- a/README.md
+++ b/README.md
@@ -1,140 +1,15 @@
![ZIG](https://ziglang.org/zig-logo.svg)
-A programming language designed for robustness, optimality, and
-clarity.
-
-[Download & Documentation](https://ziglang.org/download/)
-
-## Feature Highlights
-
- * Small, simple language. Focus on debugging your application rather than
- debugging knowledge of your programming language.
- * Ships with a build system that obviates the need for a configure script
- or a makefile. In fact, existing C and C++ projects may choose to depend on
- Zig instead of e.g. cmake.
- * A fresh take on error handling which makes writing correct code easier than
- writing buggy code.
- * Debug mode optimizes for fast compilation time and crashing with a stack trace
- when undefined behavior *would* happen.
- * ReleaseFast mode produces heavily optimized code. What other projects call
- "Link Time Optimization" Zig does automatically.
- * Compatible with C libraries with no wrapper necessary. Directly include
- C .h files and get access to the functions and symbols therein.
- * Provides standard library which competes with the C standard library and is
- always compiled against statically in source form. Zig binaries do not
- depend on libc unless explicitly linked.
- * Optional type instead of null pointers.
- * Safe unions, tagged unions, and C ABI compatible unions.
- * Generics so that one can write efficient data structures that work for any
- data type.
- * No header files required. Top level declarations are entirely
- order-independent.
- * Compile-time code execution. Compile-time reflection.
- * Partial compile-time function evaluation which eliminates the need for
- a preprocessor or macros.
- * The binaries produced by Zig have complete debugging information so you can,
- for example, use GDB, MSVC, or LLDB to debug your software.
- * Built-in unit tests with `zig test`.
- * Friendly toward package maintainers. Reproducible build, bootstrapping
- process carefully documented. Issues filed by package maintainers are
- considered especially important.
- * Cross-compiling is a primary use case.
- * In addition to creating executables, creating a C library is a primary use
- case. You can export an auto-generated .h file.
-
-### Supported Targets
-
-#### Tier 1 Support
-
- * Not only can Zig generate machine code for these targets, but the standard
- library cross-platform abstractions have implementations for these targets.
- Thus it is practical to write a pure Zig application with no dependency on
- libc.
- * The CI server automatically tests these targets on every commit to master
- branch, and updates ziglang.org/download with links to pre-built binaries.
- * These targets have debug info capabilities and therefore produce stack
- traces on failed assertions.
- * ([coming soon](https://github.com/ziglang/zig/issues/514)) libc is available
- for this target even when cross compiling.
-
-#### Tier 2 Support
-
- * There may be some standard library implementations, but many abstractions
- will give an "Unsupported OS" compile error. One can link with libc or other
- libraries to fill in the gaps in the standard library.
- * These targets are known to work, but are not automatically tested, so there
- are occasional regressions.
- * Some tests may be disabled for these targets as we work toward Tier 1
- support.
-
-#### Tier 3 Support
-
- * The standard library has little to no knowledge of the existence of this
- target.
- * Because Zig is based on LLVM, it has the capability to build for these
- targets, and LLVM has the target enabled by default.
- * These targets are not frequently tested; one will likely need to contribute
- to Zig in order to build for these targets.
- * The Zig compiler might need to be updated with a few things such as
- - what sizes are the C integer types
- - C ABI calling convention for this target
- - bootstrap code and default panic handler
- * `zig targets` is guaranteed to include this target.
-
-#### Tier 4 Support
-
- * Support for these targets is entirely experimental.
- * LLVM may have the target as an experimental target, which means that you
- need to use Zig-provided binaries for the target to be available, or
- build LLVM from source with special configure flags. `zig targets` will
- display the target if it is available.
- * This target may be considered deprecated by an official party,
- [such as macosx/i386](https://support.apple.com/en-us/HT208436) in which
- case this target will remain forever stuck in Tier 4.
- * This target may only support `--emit asm` and cannot emit object files.
-
-#### Support Table
-
-| | freestanding | linux | macosx | windows | freebsd | netbsd | UEFI | other |
-|-------------|--------------|--------|--------|---------|---------|------- | -------|--------|
-|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 2 | Tier 3 |
-|i386 | Tier 2 | Tier 2 | Tier 4 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
-|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
-|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
-|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
-|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
-|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
-|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
-|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
-|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
-|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
-|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
-|wasm32 | Tier 3 | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
-|wasm64 | Tier 3 | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
-|avr | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | Tier 4 |
-|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | Tier 4 |
-|xcore | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|nvptx | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|msp430 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|r600 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|arc | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|tce | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|le | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|amdil | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|hsail | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|spir | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|kalimba | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|shave | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-|renderscript | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
-
-## Community
-
- * IRC: `#zig` on Freenode ([Channel Logs](https://irclog.whitequark.org/zig/)).
- * Reddit: [/r/zig](https://www.reddit.com/r/zig)
- * Email list: [~andrewrk/ziglang@lists.sr.ht](https://lists.sr.ht/%7Eandrewrk/ziglang)
-
-## Building
+Zig is an open-source programming language designed for **robustness**,
+**optimality**, and **maintainability**.
+
+## Resources
+
+ * [Introduction](https://ziglang.org/#Introduction)
+ * [Download & Documentation](https://ziglang.org/download)
+ * [Community](https://github.com/ziglang/zig/wiki/Community)
+
+## Building from Source
[![Build Status](https://dev.azure.com/ziglang/zig/_apis/build/status/ziglang.zig?branchName=master)](https://dev.azure.com/ziglang/zig/_build/latest?definitionId=1&branchName=master)
@@ -150,12 +25,14 @@ Note that you can
* cmake >= 2.8.5
* gcc >= 5.0.0 or clang >= 3.6.0
* LLVM, Clang, LLD development libraries == 8.x, compiled with the same gcc or clang version above
+ - Use the system package manager, or [build from source](https://github.com/ziglang/zig/wiki/How-to-build-LLVM,-libclang,-and-liblld-from-source#posix).
##### Windows
* cmake >= 2.8.5
* Microsoft Visual Studio 2017 (version 15.8)
* LLVM, Clang, LLD development libraries == 8.x, compiled with the same MSVC version above
+ - Use the [pre-built binaries](https://github.com/ziglang/zig/wiki/How-to-build-LLVM,-libclang,-and-liblld-from-source#pre-built-binaries) or [build from source](https://github.com/ziglang/zig/wiki/How-to-build-LLVM,-libclang,-and-liblld-from-source#windows).
#### Instructions
@@ -165,9 +42,7 @@ Note that you can
mkdir build
cd build
cmake ..
-make
make install
-bin/zig build --build-file ../build.zig test
```
##### MacOS
@@ -179,7 +54,6 @@ mkdir build
cd build
cmake .. -DCMAKE_PREFIX_PATH=/usr/local/Cellar/llvm/8.0.0
make install
-bin/zig build --build-file ../build.zig test
```
##### Windows
@@ -222,3 +96,95 @@ use stage 1.
```
./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast
```
+
+## Contributing
+
+### Start a Project Using Zig
+
+One of the best ways you can contribute to Zig is to start using it for a
+personal project. Here are some great examples:
+
+ * [Oxid](https://github.com/dbandstra/oxid) - arcade style game
+ * [TM35-Metronome](https://github.com/TM35-Metronome) - tools for modifying and randomizing Pokémon games
+ * [trOS](https://github.com/sjdh02/trOS) - tiny aarch64 baremetal OS thingy
+
+Without fail, these projects lead to discovering bugs and helping flesh out use
+cases, which lead to further design iterations of Zig. Importantly, each issue
+found this way comes with real world motivations, so it is easy to explain
+your reasoning behind proposals and feature requests.
+
+Ideally, such a project will help you to learn new skills and add something
+to your personal portfolio at the same time.
+
+### Spread the Word
+
+Another way to contribute is to write about Zig, or speak about Zig at a
+conference, or do either of those things for your project which uses Zig.
+Here are some examples:
+
+ * [Iterative Replacement of C with Zig](http://tiehuis.github.io/blog/zig1.html)
+ * [The Right Tool for the Right Job: Redis Modules & Zig](https://www.youtube.com/watch?v=eCHM8-_poZY)
+
+Zig is a brand new language, with no advertising budget. Word of mouth is the
+only way people find out about the project, and the more people hear about it,
+the more people will use it, and the better chance we have to take over the
+world.
+
+### Finding Contributor Friendly Issues
+
+Please note that issues labeled
+[Proposal](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aproposal)
+but do not also have the
+[Accepted](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aaccepted)
+label are still under consideration, and efforts to implement such a proposal
+have a high risk of being wasted. If you are interested in a proposal which is
+still under consideration, please express your interest in the issue tracker,
+providing extra insights and considerations that others have not yet expressed.
+The most highly regarded argument in such a discussion is a real world use case.
+
+The issue label
+[Contributor Friendly](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3A%22contributor+friendly%22)
+exists to help contributors find issues that are "limited in scope and/or
+knowledge of Zig internals."
+
+### Editing Source Code
+
+First, build the Stage 1 compiler as described in [the Building section](#building).
+
+When making changes to the standard library, be sure to edit the files in the
+`std` directory and not the installed copy in the build directory. If you add a
+new file to the standard library, you must also add the file path in
+CMakeLists.txt.
+
+To test changes, do the following from the build directory:
+
+1. Run `make install` (on POSIX) or
+ `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows).
+2. `bin/zig build --build-file ../build.zig test` (on POSIX) or
+ `bin\zig.exe build --build-file ..\build.zig test` (on Windows).
+
+That runs the whole test suite, which does a lot of extra testing that you
+likely won't always need, and can take upwards of 2 hours. This is what the
+CI server runs when you make a pull request.
+
+To save time, you can add the `--help` option to the `zig build` command and
+see what options are available. One of the most helpful ones is
+`-Dskip-release`. Adding this option to the command in step 2 above will take
+the time down from around 2 hours to about 6 minutes, and this is a good
+enough amount of testing before making a pull request.
+
+Another example is choosing a different set of things to test. For example,
+`test-std` instead of `test` will only run the standard library tests, and
+not the other ones. Combining this suggestion with the previous one, you could
+do this:
+
+`bin/zig build --build-file ../build.zig test-std -Dskip-release` (on POSIX) or
+`bin\zig.exe build --build-file ..\build.zig test-std -Dskip-release` (on Windows).
+
+This will run only the standard library tests, in debug mode only, for all
+targets (it will cross-compile the tests for non-native targets but not run
+them).
+
+When making changes to the compiler source code, the most helpful test step to
+run is `test-behavior`. When editing documentation it is `docs`. You can find
+this information and more in the `--help` menu.
diff --git a/build.zig b/build.zig
index 2dc9c671ec..274ea51436 100644
--- a/build.zig
+++ b/build.zig
@@ -65,6 +65,8 @@ pub fn build(b: *Builder) !void {
b.default_step.dependOn(&exe.step);
+ addLibUserlandStep(b);
+
const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;
const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;
const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release;
@@ -380,3 +382,28 @@ const Context = struct {
dia_guids_lib: []const u8,
llvm: LibraryDep,
};
+
+fn addLibUserlandStep(b: *Builder) void {
+ // Sadly macOS requires hacks to work around the buggy MACH-O linker code.
+ const artifact = if (builtin.os == .macosx)
+ b.addObject("userland", "src-self-hosted/stage1.zig")
+ else
+ b.addStaticLibrary("userland", "src-self-hosted/stage1.zig");
+ artifact.disable_gen_h = true;
+ if (builtin.os == .macosx) {
+ artifact.disable_stack_probing = true;
+ } else {
+ artifact.bundle_compiler_rt = true;
+ }
+ artifact.setTarget(builtin.arch, builtin.os, builtin.abi);
+ artifact.linkSystemLibrary("c");
+ const libuserland_step = b.step("libuserland", "Build the userland compiler library for use in stage1");
+ libuserland_step.dependOn(&artifact.step);
+
+ const output_dir = b.option(
+ []const u8,
+ "output-dir",
+ "For libuserland step, where to put the output",
+ ) orelse return;
+ artifact.setOutputDir(output_dir);
+}
diff --git a/ci/azure/windows_upload b/ci/azure/windows_upload
index 088294a180..8478be0e0b 100755
--- a/ci/azure/windows_upload
+++ b/ci/azure/windows_upload
@@ -6,7 +6,7 @@ set -e
if [ "${BUILD_REASON}" != "PullRequest" ]; then
cd "$ZIGBUILDDIR"
- rm release/*.lib
+ rm release/*.exe
mv ../LICENSE release/
mv ../zig-cache/langref.html release/
mv release/bin/zig.exe release/
diff --git a/cmake/Findclang.cmake b/cmake/Findclang.cmake
index 6747e489b4..5555485d89 100644
--- a/cmake/Findclang.cmake
+++ b/cmake/Findclang.cmake
@@ -44,7 +44,7 @@ else()
/usr/local/llvm80/include
/mingw64/include)
- macro(FIND_AND_ADD_CLANG_LIB _libname_)
+ macro(FIND_AND_ADD_CLANG_LIB _libname_)
string(TOUPPER ${_libname_} _prettylibname_)
find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_}
PATHS
diff --git a/deps/lld/wasm/OutputSections.cpp b/deps/lld/wasm/OutputSections.cpp
index 4123d63b74..6b7b18d4ca 100644
--- a/deps/lld/wasm/OutputSections.cpp
+++ b/deps/lld/wasm/OutputSections.cpp
@@ -111,8 +111,8 @@ void CodeSection::writeTo(uint8_t *Buf) {
memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());
// Write code section bodies
- parallelForEach(Functions,
- [&](const InputChunk *Chunk) { Chunk->writeTo(Buf); });
+ for (const InputChunk *Chunk : Functions)
+ Chunk->writeTo(Buf);
}
uint32_t CodeSection::numRelocations() const {
@@ -176,7 +176,7 @@ void DataSection::writeTo(uint8_t *Buf) {
// Write data section headers
memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());
- parallelForEach(Segments, [&](const OutputSegment *Segment) {
+ for (const OutputSegment *Segment : Segments) {
// Write data segment header
uint8_t *SegStart = Buf + Segment->SectionOffset;
memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
@@ -184,7 +184,7 @@ void DataSection::writeTo(uint8_t *Buf) {
// Write segment data payload
for (const InputChunk *Chunk : Segment->InputSegments)
Chunk->writeTo(Buf);
- });
+ }
}
uint32_t DataSection::numRelocations() const {
@@ -232,8 +232,8 @@ void CustomSection::writeTo(uint8_t *Buf) {
Buf += NameData.size();
// Write custom sections payload
- parallelForEach(InputSections,
- [&](const InputSection *Section) { Section->writeTo(Buf); });
+ for (const InputSection *Section : InputSections)
+ Section->writeTo(Buf);
}
uint32_t CustomSection::numRelocations() const {
diff --git a/doc/docgen.zig b/doc/docgen.zig
index 0c859e4a15..75c80cc528 100644
--- a/doc/docgen.zig
+++ b/doc/docgen.zig
@@ -265,6 +265,7 @@ const SeeAlsoItem = struct {
const ExpectedOutcome = enum {
Succeed,
Fail,
+ BuildFail,
};
const Code = struct {
@@ -468,6 +469,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Succeed };
} else if (mem.eql(u8, code_kind_str, "exe_err")) {
code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Fail };
+ } else if (mem.eql(u8, code_kind_str, "exe_build_err")) {
+ code_kind_id = Code.Id{ .Exe = ExpectedOutcome.BuildFail };
} else if (mem.eql(u8, code_kind_str, "test")) {
code_kind_id = Code.Id.Test;
} else if (mem.eql(u8, code_kind_str, "test_err")) {
@@ -509,6 +512,10 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
target_str = "x86_64-windows";
} else if (mem.eql(u8, end_tag_name, "target_linux_x86_64")) {
target_str = "x86_64-linux";
+ } else if (mem.eql(u8, end_tag_name, "target_wasm")) {
+ target_str = "wasm32-freestanding";
+ } else if (mem.eql(u8, end_tag_name, "target_wasi")) {
+ target_str = "wasm32-wasi";
} else if (mem.eql(u8, end_tag_name, "link_libc")) {
link_libc = true;
} else if (mem.eql(u8, end_tag_name, "code_end")) {
@@ -1025,6 +1032,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
tmp_dir_name,
"--name",
code.name,
+ "--color",
+ "on",
});
try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);
switch (code.mode) {
@@ -1059,14 +1068,52 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
}
if (code.target_str) |triple| {
try build_args.appendSlice([][]const u8{ "-target", triple });
+ if (!code.is_inline) {
+ try out.print(" -target {}", triple);
+ }
+ }
+ if (expected_outcome == .BuildFail) {
+ const result = try os.ChildProcess.exec(
+ allocator,
+ build_args.toSliceConst(),
+ null,
+ &env_map,
+ max_doc_file_size,
+ );
+ switch (result.term) {
+ os.ChildProcess.Term.Exited => |exit_code| {
+ if (exit_code == 0) {
+ warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
+ for (build_args.toSliceConst()) |arg|
+ warn("{} ", arg)
+ else
+ warn("\n");
+ return parseError(tokenizer, code.source_token, "example incorrectly compiled");
+ }
+ },
+ else => {
+ warn("{}\nThe following command crashed:\n", result.stderr);
+ for (build_args.toSliceConst()) |arg|
+ warn("{} ", arg)
+ else
+ warn("\n");
+ return parseError(tokenizer, code.source_token, "example compile crashed");
+ },
+ }
+ const escaped_stderr = try escapeHtml(allocator, result.stderr);
+ const colored_stderr = try termColor(allocator, escaped_stderr);
+ try out.print("\n{}</code></pre>\n", colored_stderr);
+ break :code_block;
}
_ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
if (code.target_str) |triple| {
- if (mem.startsWith(u8, triple, "x86_64-linux") and
+ if (mem.startsWith(u8, triple, "wasm32") or
+ mem.startsWith(u8, triple, "x86_64-linux") and
(builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64))
{
// skip execution
+ try out.print("</code></pre>\n");
break :code_block;
}
}
@@ -1130,6 +1177,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
}
if (code.target_str) |triple| {
try test_args.appendSlice([][]const u8{ "-target", triple });
+ try out.print(" -target {}", triple);
}
const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
const escaped_stderr = try escapeHtml(allocator, result.stderr);
@@ -1310,6 +1358,11 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
},
}
+ if (code.target_str) |triple| {
+ try build_args.appendSlice([][]const u8{ "-target", triple });
+ try out.print(" -target {}", triple);
+ }
+
if (maybe_error_match) |error_match| {
const result = try os.ChildProcess.exec(allocator, build_args.toSliceConst(), null, &env_map, max_doc_file_size);
switch (result.term) {
diff --git a/doc/langref.html.in b/doc/langref.html.in
index bb2a67c562..807fe7d6db 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -4,11 +4,12 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<title>Documentation - The Zig Programming Language</title>
+ <link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNSAxMCIgZmlsbD0iI2Y3YTQxZCI+PHBhdGggZD0iTTAsMSBIMy41IFYzIEgyIFY3IEgzLjY4MiBMMS44ODEsOSBIMCBaIE0xNSw5IEgxMS41IFY3IEgxMyBWMyBIMTEuMzE4IEwxMy4xMTksMSBIMTUgWiBNNCwxIEg5LjkxMiBMMTMuMzI4LDAuMDIxIEw3LjA0NSw3IEgxMSBWOSBINS4wODggTDEuNjcyLDkuOTc5IEw3Ljk1NSwzIEg0IFoiLz48L3N2Zz4="/>
<style type="text/css">
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
}
- a {
+ a:not(:hover) {
text-decoration: none;
}
table, th, td {
@@ -158,13 +159,15 @@
<div id="contents">
{#header_open|Introduction#}
<p>
- Zig is an open-source programming language designed for <strong>robustness</strong>,
- <strong>optimality</strong>, and <strong>clarity</strong>.
+ Zig is a general-purpose programming language designed for <strong>robustness</strong>,
+ <strong>optimality</strong>, and <strong>maintainability</strong>.
</p>
<ul>
<li><strong>Robust</strong> - behavior is correct even for edge cases such as out of memory.</li>
<li><strong>Optimal</strong> - write programs the best way they can behave and perform.</li>
- <li><strong>Clear</strong> - precisely communicate your intent to the compiler and other programmers. The language imposes a low overhead to reading code.</li>
+ <li><strong>Maintainable</strong> - precisely communicate intent to the compiler and other programmers.
+ The language imposes a low overhead to reading code and is resilient to changing requirements
+ and environments.</li>
</ul>
<p>
Often the most efficient way to learn something new is to see examples, so
@@ -3125,7 +3128,7 @@ test "while null capture" {
while (eventuallyNullSequence()) |value| {
sum2 += value;
} else {
- assert(sum1 == 3);
+ assert(sum2 == 3);
}
}
@@ -7180,14 +7183,6 @@ pub const FloatMode = enum {
{#see_also|Floating Point Operations#}
{#header_close#}
- {#header_open|@setGlobalLinkage#}
- <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>
- <p>
- {#syntax#}GlobalLinkage{#endsyntax#} can be found with {#syntax#}@import("builtin").GlobalLinkage{#endsyntax#}.
- </p>
- {#see_also|Compile Variables#}
- {#header_close#}
-
{#header_open|@setRuntimeSafety#}
<pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
<p>
@@ -7217,6 +7212,8 @@ test "@setRuntimeSafety" {
}
}
{#code_end#}
+ <p>Note: it is <a href="https://github.com/ziglang/zig/issues/978">planned</a> to replace
+ {#syntax#}@setRuntimeSafety{#endsyntax#} with <code>@optimizeFor</code></p>
{#header_close#}
@@ -7272,6 +7269,10 @@ test "@setRuntimeSafety" {
consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or
{#syntax#}@typeInfo(T).Int.bits{#endsyntax#}.
</p>
+ <p>
+ This function measures the size at runtime. For types that are disallowed at runtime, such as
+ {#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}.
+ </p>
{#see_also|@typeInfo#}
{#header_close#}
@@ -7360,20 +7361,30 @@ fn List(comptime T: type) type {
<pre>{#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}</pre>
<p>
This function truncates bits from an integer type, resulting in a smaller
- integer type.
+ or same-sized integer type.
</p>
<p>
- The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in
- {#link|ReleaseFast#} mode:
+ The following produces safety-checked {#link|Undefined Behavior#}:
</p>
- <pre>{#syntax#}const a: u16 = 0xabcd;
-const b: u8 = u8(a);{#endsyntax#}</pre>
+ {#code_begin|test_err|cast truncated bits#}
+test "integer cast panic" {
+ var a: u16 = 0xabcd;
+ var b: u8 = @intCast(u8, a);
+}
+ {#code_end#}
<p>
However this is well defined and working code:
</p>
- <pre>{#syntax#}const a: u16 = 0xabcd;
-const b: u8 = @truncate(u8, a);
-// b is now 0xcd{#endsyntax#}</pre>
+ {#code_begin|test|truncate#}
+const std = @import("std");
+const assert = std.debug.assert;
+
+test "integer truncation" {
+ var a: u16 = 0xabcd;
+ var b: u8 = @truncate(u8, a);
+ assert(b == 0xcd);
+}
+ {#code_end#}
<p>
This function always truncates the significant bits of the integer, regardless
of endianness on the target platform.
@@ -8840,20 +8851,21 @@ export fn add(a: i32, b: i32) i32 {
return a + b;
}
{#code_end#}
- <p>To make a shared library:</p>
+ <p>To make a static library:</p>
<pre><code class="shell">$ zig build-lib mathtest.zig
</code></pre>
- <p>To make a static library:</p>
- <pre><code class="shell">$ zig build-lib mathtest.zig --static
+ <p>To make a shared library:</p>
+ <pre><code class="shell">$ zig build-lib mathtest.zig -dynamic
</code></pre>
<p>Here is an example with the {#link|Zig Build System#}:</p>
<p class="file">test.c</p>
<pre><code class="cpp">// This header is generated by zig from mathtest.zig
#include "mathtest.h"
-#include &lt;assert.h&gt;
+#include &lt;stdio.h&gt;
int main(int argc, char **argv) {
- assert(add(42, 1337) == 1379);
+ int32_t result = add(42, 1337);
+ printf("%d\n", result);
return 0;
}</code></pre>
<p class="file">build.zig</p>
@@ -8863,10 +8875,10 @@ const Builder = @import("std").build.Builder;
pub fn build(b: *Builder) void {
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
- const exe = b.addCExecutable("test");
- exe.addCompileFlags([][]const u8{"-std=c99"});
- exe.addSourceFile("test.c");
+ const exe = b.addExecutable("test", null);
+ exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
exe.linkLibrary(lib);
+ exe.linkSystemLibrary("c");
b.default_step.dependOn(&exe.step);
@@ -8877,10 +8889,9 @@ pub fn build(b: *Builder) void {
}
{#code_end#}
<p class="file">terminal</p>
- <pre><code class="shell">$ zig build
-$ ./test
-$ echo $?
-0</code></pre>
+ <pre><code class="shell">$ zig build test
+1379
+</code></pre>
{#see_also|export#}
{#header_close#}
{#header_open|Mixing Object Files#}
@@ -8947,6 +8958,33 @@ all your base are belong to us</code></pre>
{#see_also|Targets|Zig Build System#}
{#header_close#}
{#header_close#}
+ {#header_open|WebAssembly#}
+ {#header_open|Freestanding#}
+ {#code_begin|exe|wasm#}
+ {#target_wasm#}
+extern fn print(i32) void;
+
+export fn add(a: i32, b: i32) void {
+ print(a + b);
+}
+ {#code_end#}
+ {#header_close#}
+ {#header_open|WASI#}
+ {#code_begin|exe|wasi#}
+ {#target_wasi#}
+const std = @import("std");
+
+pub fn main() !void {
+ const args = try std.os.argsAlloc(std.heap.wasm_allocator);
+ defer std.os.argsFree(std.heap.wasm_allocator, args);
+
+ for (args) |arg, i| {
+ std.debug.warn("{}: {}\n", i, arg);
+ }
+}
+ {#code_end#}
+ {#header_close#}
+ {#header_close#}
{#header_open|Targets#}
<p>
Zig supports generating code for all targets that LLVM supports. Here is
@@ -9430,8 +9468,6 @@ PrimaryExpr
IfExpr &lt;- IfPrefix Expr (KEYWORD_else Payload? Expr)?
-LabeledExpr &lt;- BlockLabel? (Block / LoopExpr)
-
Block &lt;- LBRACE Statement* RBRACE
LoopExpr &lt;- KEYWORD_inline? (ForExpr / WhileExpr)
@@ -9440,6 +9476,8 @@ ForExpr &lt;- ForPrefix Expr (KEYWORD_else Expr)?
WhileExpr &lt;- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
+CurlySuffixExpr &lt;- TypeExpr InitList?
+
InitList
&lt;- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
/ LBRACE Expr (COMMA Expr)* COMMA? RBRACE
@@ -9457,6 +9495,7 @@ PrimaryTypeExpr
&lt;- BUILTINIDENTIFIER FnCallArguments
/ CHAR_LITERAL
/ ContainerDecl
+ / DOT IDENTIFIER
/ ErrorSetDecl
/ FLOAT
/ FnProto
diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig
new file mode 100644
index 0000000000..92fe7b7cd3
--- /dev/null
+++ b/src-self-hosted/clang.zig
@@ -0,0 +1,866 @@
+pub const struct_ZigClangAPValue = @OpaqueType();
+pub const struct_ZigClangAPSInt = @OpaqueType();
+pub const struct_ZigClangASTContext = @OpaqueType();
+pub const struct_ZigClangASTUnit = @OpaqueType();
+pub const struct_ZigClangArraySubscriptExpr = @OpaqueType();
+pub const struct_ZigClangArrayType = @OpaqueType();
+pub const struct_ZigClangAttributedType = @OpaqueType();
+pub const struct_ZigClangBinaryOperator = @OpaqueType();
+pub const struct_ZigClangBreakStmt = @OpaqueType();
+pub const struct_ZigClangBuiltinType = @OpaqueType();
+pub const struct_ZigClangCStyleCastExpr = @OpaqueType();
+pub const struct_ZigClangCallExpr = @OpaqueType();
+pub const struct_ZigClangCaseStmt = @OpaqueType();
+pub const struct_ZigClangCompoundAssignOperator = @OpaqueType();
+pub const ZigClangCompoundStmt = @OpaqueType();
+pub const struct_ZigClangConditionalOperator = @OpaqueType();
+pub const struct_ZigClangConstantArrayType = @OpaqueType();
+pub const struct_ZigClangContinueStmt = @OpaqueType();
+pub const struct_ZigClangDecayedType = @OpaqueType();
+pub const struct_ZigClangDecl = @OpaqueType();
+pub const struct_ZigClangDeclRefExpr = @OpaqueType();
+pub const struct_ZigClangDeclStmt = @OpaqueType();
+pub const struct_ZigClangDefaultStmt = @OpaqueType();
+pub const struct_ZigClangDiagnosticOptions = @OpaqueType();
+pub const struct_ZigClangDiagnosticsEngine = @OpaqueType();
+pub const struct_ZigClangDoStmt = @OpaqueType();
+pub const struct_ZigClangElaboratedType = @OpaqueType();
+pub const struct_ZigClangEnumConstantDecl = @OpaqueType();
+pub const struct_ZigClangEnumDecl = @OpaqueType();
+pub const struct_ZigClangEnumType = @OpaqueType();
+pub const struct_ZigClangExpr = @OpaqueType();
+pub const struct_ZigClangFieldDecl = @OpaqueType();
+pub const struct_ZigClangFileID = @OpaqueType();
+pub const struct_ZigClangForStmt = @OpaqueType();
+pub const struct_ZigClangFullSourceLoc = @OpaqueType();
+pub const ZigClangFunctionDecl = @OpaqueType();
+pub const struct_ZigClangFunctionProtoType = @OpaqueType();
+pub const struct_ZigClangIfStmt = @OpaqueType();
+pub const struct_ZigClangImplicitCastExpr = @OpaqueType();
+pub const struct_ZigClangIncompleteArrayType = @OpaqueType();
+pub const struct_ZigClangIntegerLiteral = @OpaqueType();
+pub const struct_ZigClangMacroDefinitionRecord = @OpaqueType();
+pub const struct_ZigClangMemberExpr = @OpaqueType();
+pub const struct_ZigClangNamedDecl = @OpaqueType();
+pub const struct_ZigClangNone = @OpaqueType();
+pub const struct_ZigClangPCHContainerOperations = @OpaqueType();
+pub const struct_ZigClangParenExpr = @OpaqueType();
+pub const struct_ZigClangParenType = @OpaqueType();
+pub const struct_ZigClangParmVarDecl = @OpaqueType();
+pub const struct_ZigClangPointerType = @OpaqueType();
+pub const struct_ZigClangPreprocessedEntity = @OpaqueType();
+pub const struct_ZigClangRecordDecl = @OpaqueType();
+pub const struct_ZigClangRecordType = @OpaqueType();
+pub const struct_ZigClangReturnStmt = @OpaqueType();
+pub const struct_ZigClangSkipFunctionBodiesScope = @OpaqueType();
+pub const struct_ZigClangSourceManager = @OpaqueType();
+pub const struct_ZigClangSourceRange = @OpaqueType();
+pub const struct_ZigClangStmt = @OpaqueType();
+pub const struct_ZigClangStringLiteral = @OpaqueType();
+pub const struct_ZigClangStringRef = @OpaqueType();
+pub const struct_ZigClangSwitchStmt = @OpaqueType();
+pub const struct_ZigClangTagDecl = @OpaqueType();
+pub const struct_ZigClangType = @OpaqueType();
+pub const struct_ZigClangTypedefNameDecl = @OpaqueType();
+pub const struct_ZigClangTypedefType = @OpaqueType();
+pub const struct_ZigClangUnaryExprOrTypeTraitExpr = @OpaqueType();
+pub const struct_ZigClangUnaryOperator = @OpaqueType();
+pub const struct_ZigClangValueDecl = @OpaqueType();
+pub const struct_ZigClangVarDecl = @OpaqueType();
+pub const struct_ZigClangWhileStmt = @OpaqueType();
+pub const ZigClangFunctionType = @OpaqueType();
+
+pub const ZigClangBO = extern enum {
+ PtrMemD,
+ PtrMemI,
+ Mul,
+ Div,
+ Rem,
+ Add,
+ Sub,
+ Shl,
+ Shr,
+ Cmp,
+ LT,
+ GT,
+ LE,
+ GE,
+ EQ,
+ NE,
+ And,
+ Xor,
+ Or,
+ LAnd,
+ LOr,
+ Assign,
+ MulAssign,
+ DivAssign,
+ RemAssign,
+ AddAssign,
+ SubAssign,
+ ShlAssign,
+ ShrAssign,
+ AndAssign,
+ XorAssign,
+ OrAssign,
+ Comma,
+};
+
+pub const ZigClangUO = extern enum {
+ PostInc,
+ PostDec,
+ PreInc,
+ PreDec,
+ AddrOf,
+ Deref,
+ Plus,
+ Minus,
+ Not,
+ LNot,
+ Real,
+ Imag,
+ Extension,
+ Coawait,
+};
+
+pub const ZigClangTypeClass = extern enum {
+ Builtin,
+ Complex,
+ Pointer,
+ BlockPointer,
+ LValueReference,
+ RValueReference,
+ MemberPointer,
+ ConstantArray,
+ IncompleteArray,
+ VariableArray,
+ DependentSizedArray,
+ DependentSizedExtVector,
+ DependentAddressSpace,
+ Vector,
+ DependentVector,
+ ExtVector,
+ FunctionProto,
+ FunctionNoProto,
+ UnresolvedUsing,
+ Paren,
+ Typedef,
+ Adjusted,
+ Decayed,
+ TypeOfExpr,
+ TypeOf,
+ Decltype,
+ UnaryTransform,
+ Record,
+ Enum,
+ Elaborated,
+ Attributed,
+ TemplateTypeParm,
+ SubstTemplateTypeParm,
+ SubstTemplateTypeParmPack,
+ TemplateSpecialization,
+ Auto,
+ DeducedTemplateSpecialization,
+ InjectedClassName,
+ DependentName,
+ DependentTemplateSpecialization,
+ PackExpansion,
+ ObjCTypeParam,
+ ObjCObject,
+ ObjCInterface,
+ ObjCObjectPointer,
+ Pipe,
+ Atomic,
+};
+
+pub const ZigClangStmtClass = extern enum {
+ NoStmtClass = 0,
+ GCCAsmStmtClass = 1,
+ MSAsmStmtClass = 2,
+ AttributedStmtClass = 3,
+ BreakStmtClass = 4,
+ CXXCatchStmtClass = 5,
+ CXXForRangeStmtClass = 6,
+ CXXTryStmtClass = 7,
+ CapturedStmtClass = 8,
+ CompoundStmtClass = 9,
+ ContinueStmtClass = 10,
+ CoreturnStmtClass = 11,
+ CoroutineBodyStmtClass = 12,
+ DeclStmtClass = 13,
+ DoStmtClass = 14,
+ BinaryConditionalOperatorClass = 15,
+ ConditionalOperatorClass = 16,
+ AddrLabelExprClass = 17,
+ ArrayInitIndexExprClass = 18,
+ ArrayInitLoopExprClass = 19,
+ ArraySubscriptExprClass = 20,
+ ArrayTypeTraitExprClass = 21,
+ AsTypeExprClass = 22,
+ AtomicExprClass = 23,
+ BinaryOperatorClass = 24,
+ CompoundAssignOperatorClass = 25,
+ BlockExprClass = 26,
+ CXXBindTemporaryExprClass = 27,
+ CXXBoolLiteralExprClass = 28,
+ CXXConstructExprClass = 29,
+ CXXTemporaryObjectExprClass = 30,
+ CXXDefaultArgExprClass = 31,
+ CXXDefaultInitExprClass = 32,
+ CXXDeleteExprClass = 33,
+ CXXDependentScopeMemberExprClass = 34,
+ CXXFoldExprClass = 35,
+ CXXInheritedCtorInitExprClass = 36,
+ CXXNewExprClass = 37,
+ CXXNoexceptExprClass = 38,
+ CXXNullPtrLiteralExprClass = 39,
+ CXXPseudoDestructorExprClass = 40,
+ CXXScalarValueInitExprClass = 41,
+ CXXStdInitializerListExprClass = 42,
+ CXXThisExprClass = 43,
+ CXXThrowExprClass = 44,
+ CXXTypeidExprClass = 45,
+ CXXUnresolvedConstructExprClass = 46,
+ CXXUuidofExprClass = 47,
+ CallExprClass = 48,
+ CUDAKernelCallExprClass = 49,
+ CXXMemberCallExprClass = 50,
+ CXXOperatorCallExprClass = 51,
+ UserDefinedLiteralClass = 52,
+ CStyleCastExprClass = 53,
+ CXXFunctionalCastExprClass = 54,
+ CXXConstCastExprClass = 55,
+ CXXDynamicCastExprClass = 56,
+ CXXReinterpretCastExprClass = 57,
+ CXXStaticCastExprClass = 58,
+ ObjCBridgedCastExprClass = 59,
+ ImplicitCastExprClass = 60,
+ CharacterLiteralClass = 61,
+ ChooseExprClass = 62,
+ CompoundLiteralExprClass = 63,
+ ConvertVectorExprClass = 64,
+ CoawaitExprClass = 65,
+ CoyieldExprClass = 66,
+ DeclRefExprClass = 67,
+ DependentCoawaitExprClass = 68,
+ DependentScopeDeclRefExprClass = 69,
+ DesignatedInitExprClass = 70,
+ DesignatedInitUpdateExprClass = 71,
+ ExpressionTraitExprClass = 72,
+ ExtVectorElementExprClass = 73,
+ FixedPointLiteralClass = 74,
+ FloatingLiteralClass = 75,
+ ConstantExprClass = 76,
+ ExprWithCleanupsClass = 77,
+ FunctionParmPackExprClass = 78,
+ GNUNullExprClass = 79,
+ GenericSelectionExprClass = 80,
+ ImaginaryLiteralClass = 81,
+ ImplicitValueInitExprClass = 82,
+ InitListExprClass = 83,
+ IntegerLiteralClass = 84,
+ LambdaExprClass = 85,
+ MSPropertyRefExprClass = 86,
+ MSPropertySubscriptExprClass = 87,
+ MaterializeTemporaryExprClass = 88,
+ MemberExprClass = 89,
+ NoInitExprClass = 90,
+ OMPArraySectionExprClass = 91,
+ ObjCArrayLiteralClass = 92,
+ ObjCAvailabilityCheckExprClass = 93,
+ ObjCBoolLiteralExprClass = 94,
+ ObjCBoxedExprClass = 95,
+ ObjCDictionaryLiteralClass = 96,
+ ObjCEncodeExprClass = 97,
+ ObjCIndirectCopyRestoreExprClass = 98,
+ ObjCIsaExprClass = 99,
+ ObjCIvarRefExprClass = 100,
+ ObjCMessageExprClass = 101,
+ ObjCPropertyRefExprClass = 102,
+ ObjCProtocolExprClass = 103,
+ ObjCSelectorExprClass = 104,
+ ObjCStringLiteralClass = 105,
+ ObjCSubscriptRefExprClass = 106,
+ OffsetOfExprClass = 107,
+ OpaqueValueExprClass = 108,
+ UnresolvedLookupExprClass = 109,
+ UnresolvedMemberExprClass = 110,
+ PackExpansionExprClass = 111,
+ ParenExprClass = 112,
+ ParenListExprClass = 113,
+ PredefinedExprClass = 114,
+ PseudoObjectExprClass = 115,
+ ShuffleVectorExprClass = 116,
+ SizeOfPackExprClass = 117,
+ StmtExprClass = 118,
+ StringLiteralClass = 119,
+ SubstNonTypeTemplateParmExprClass = 120,
+ SubstNonTypeTemplateParmPackExprClass = 121,
+ TypeTraitExprClass = 122,
+ TypoExprClass = 123,
+ UnaryExprOrTypeTraitExprClass = 124,
+ UnaryOperatorClass = 125,
+ VAArgExprClass = 126,
+ ForStmtClass = 127,
+ GotoStmtClass = 128,
+ IfStmtClass = 129,
+ IndirectGotoStmtClass = 130,
+ LabelStmtClass = 131,
+ MSDependentExistsStmtClass = 132,
+ NullStmtClass = 133,
+ OMPAtomicDirectiveClass = 134,
+ OMPBarrierDirectiveClass = 135,
+ OMPCancelDirectiveClass = 136,
+ OMPCancellationPointDirectiveClass = 137,
+ OMPCriticalDirectiveClass = 138,
+ OMPFlushDirectiveClass = 139,
+ OMPDistributeDirectiveClass = 140,
+ OMPDistributeParallelForDirectiveClass = 141,
+ OMPDistributeParallelForSimdDirectiveClass = 142,
+ OMPDistributeSimdDirectiveClass = 143,
+ OMPForDirectiveClass = 144,
+ OMPForSimdDirectiveClass = 145,
+ OMPParallelForDirectiveClass = 146,
+ OMPParallelForSimdDirectiveClass = 147,
+ OMPSimdDirectiveClass = 148,
+ OMPTargetParallelForSimdDirectiveClass = 149,
+ OMPTargetSimdDirectiveClass = 150,
+ OMPTargetTeamsDistributeDirectiveClass = 151,
+ OMPTargetTeamsDistributeParallelForDirectiveClass = 152,
+ OMPTargetTeamsDistributeParallelForSimdDirectiveClass = 153,
+ OMPTargetTeamsDistributeSimdDirectiveClass = 154,
+ OMPTaskLoopDirectiveClass = 155,
+ OMPTaskLoopSimdDirectiveClass = 156,
+ OMPTeamsDistributeDirectiveClass = 157,
+ OMPTeamsDistributeParallelForDirectiveClass = 158,
+ OMPTeamsDistributeParallelForSimdDirectiveClass = 159,
+ OMPTeamsDistributeSimdDirectiveClass = 160,
+ OMPMasterDirectiveClass = 161,
+ OMPOrderedDirectiveClass = 162,
+ OMPParallelDirectiveClass = 163,
+ OMPParallelSectionsDirectiveClass = 164,
+ OMPSectionDirectiveClass = 165,
+ OMPSectionsDirectiveClass = 166,
+ OMPSingleDirectiveClass = 167,
+ OMPTargetDataDirectiveClass = 168,
+ OMPTargetDirectiveClass = 169,
+ OMPTargetEnterDataDirectiveClass = 170,
+ OMPTargetExitDataDirectiveClass = 171,
+ OMPTargetParallelDirectiveClass = 172,
+ OMPTargetParallelForDirectiveClass = 173,
+ OMPTargetTeamsDirectiveClass = 174,
+ OMPTargetUpdateDirectiveClass = 175,
+ OMPTaskDirectiveClass = 176,
+ OMPTaskgroupDirectiveClass = 177,
+ OMPTaskwaitDirectiveClass = 178,
+ OMPTaskyieldDirectiveClass = 179,
+ OMPTeamsDirectiveClass = 180,
+ ObjCAtCatchStmtClass = 181,
+ ObjCAtFinallyStmtClass = 182,
+ ObjCAtSynchronizedStmtClass = 183,
+ ObjCAtThrowStmtClass = 184,
+ ObjCAtTryStmtClass = 185,
+ ObjCAutoreleasePoolStmtClass = 186,
+ ObjCForCollectionStmtClass = 187,
+ ReturnStmtClass = 188,
+ SEHExceptStmtClass = 189,
+ SEHFinallyStmtClass = 190,
+ SEHLeaveStmtClass = 191,
+ SEHTryStmtClass = 192,
+ CaseStmtClass = 193,
+ DefaultStmtClass = 194,
+ SwitchStmtClass = 195,
+ WhileStmtClass = 196,
+};
+
+pub const ZigClangCK = extern enum {
+ Dependent,
+ BitCast,
+ LValueBitCast,
+ LValueToRValue,
+ NoOp,
+ BaseToDerived,
+ DerivedToBase,
+ UncheckedDerivedToBase,
+ Dynamic,
+ ToUnion,
+ ArrayToPointerDecay,
+ FunctionToPointerDecay,
+ NullToPointer,
+ NullToMemberPointer,
+ BaseToDerivedMemberPointer,
+ DerivedToBaseMemberPointer,
+ MemberPointerToBoolean,
+ ReinterpretMemberPointer,
+ UserDefinedConversion,
+ ConstructorConversion,
+ IntegralToPointer,
+ PointerToIntegral,
+ PointerToBoolean,
+ ToVoid,
+ VectorSplat,
+ IntegralCast,
+ IntegralToBoolean,
+ IntegralToFloating,
+ FixedPointCast,
+ FixedPointToBoolean,
+ FloatingToIntegral,
+ FloatingToBoolean,
+ BooleanToSignedIntegral,
+ FloatingCast,
+ CPointerToObjCPointerCast,
+ BlockPointerToObjCPointerCast,
+ AnyPointerToBlockPointerCast,
+ ObjCObjectLValueCast,
+ FloatingRealToComplex,
+ FloatingComplexToReal,
+ FloatingComplexToBoolean,
+ FloatingComplexCast,
+ FloatingComplexToIntegralComplex,
+ IntegralRealToComplex,
+ IntegralComplexToReal,
+ IntegralComplexToBoolean,
+ IntegralComplexCast,
+ IntegralComplexToFloatingComplex,
+ ARCProduceObject,
+ ARCConsumeObject,
+ ARCReclaimReturnedObject,
+ ARCExtendBlockObject,
+ AtomicToNonAtomic,
+ NonAtomicToAtomic,
+ CopyAndAutoreleaseBlockObject,
+ BuiltinFnToFnPtr,
+ ZeroToOCLOpaqueType,
+ AddressSpaceConversion,
+ IntToOCLSampler,
+};
+
+pub const ZigClangAPValueKind = extern enum {
+ Uninitialized,
+ Int,
+ Float,
+ ComplexInt,
+ ComplexFloat,
+ LValue,
+ Vector,
+ Array,
+ Struct,
+ Union,
+ MemberPointer,
+ AddrLabelDiff,
+};
+
+pub extern fn ZigClangSourceManager_getSpellingLoc(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
+pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*]const u8;
+pub extern fn ZigClangSourceManager_getSpellingLineNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
+pub extern fn ZigClangSourceManager_getSpellingColumnNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
+pub extern fn ZigClangSourceManager_getCharacterData(arg0: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8;
+pub extern fn ZigClangASTContext_getPointerType(arg0: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType;
+pub extern fn ZigClangASTUnit_getASTContext(arg0: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext;
+pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
+pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;
+pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) ?*const struct_ZigClangRecordDecl;
+pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;
+pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
+pub extern fn ZigClangEnumDecl_getCanonicalDecl(arg0: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
+pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(arg0: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;
+pub extern fn ZigClangRecordDecl_getDefinition(arg0: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangRecordDecl;
+pub extern fn ZigClangEnumDecl_getDefinition(arg0: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangEnumDecl;
+pub extern fn ZigClangRecordDecl_getLocation(arg0: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation;
+pub extern fn ZigClangEnumDecl_getLocation(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangSourceLocation;
+pub extern fn ZigClangTypedefNameDecl_getLocation(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangSourceLocation;
+pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSourceLocation;
+pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
+pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool;
+pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
+pub extern fn ZigClangEnumDecl_getIntegerType(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
+pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
+pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
+pub extern fn ZigClangTypedefType_getDecl(arg0: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
+pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
+pub extern fn ZigClangQualType_getCanonicalType(arg0: struct_ZigClangQualType) struct_ZigClangQualType;
+pub extern fn ZigClangQualType_getTypePtr(self: struct_ZigClangQualType) *const struct_ZigClangType;
+pub extern fn ZigClangQualType_addConst(arg0: [*c]struct_ZigClangQualType) void;
+pub extern fn ZigClangQualType_eq(arg0: struct_ZigClangQualType, arg1: struct_ZigClangQualType) bool;
+pub extern fn ZigClangQualType_isConstQualified(arg0: struct_ZigClangQualType) bool;
+pub extern fn ZigClangQualType_isVolatileQualified(arg0: struct_ZigClangQualType) bool;
+pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType) bool;
+pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
+pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
+pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
+pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
+pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
+pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
+pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass;
+pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType;
+pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation;
+pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
+pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;
+pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
+pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) ?*const struct_ZigClangAPValue;
+pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPValue;
+pub extern fn ZigClangAPValue_getArraySize(self: ?*const struct_ZigClangAPValue) c_uint;
+pub extern fn ZigClangAPValue_getLValueBase(self: ?*const struct_ZigClangAPValue) struct_ZigClangAPValueLValueBase;
+pub extern fn ZigClangAPSInt_isSigned(self: ?*const struct_ZigClangAPSInt) bool;
+pub extern fn ZigClangAPSInt_isNegative(self: ?*const struct_ZigClangAPSInt) bool;
+pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const struct_ZigClangAPSInt;
+pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
+pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64;
+pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
+pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
+pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void;
+
+pub extern fn ZigClangFunctionDecl_getType(self: *const ZigClangFunctionDecl) struct_ZigClangQualType;
+pub extern fn ZigClangFunctionDecl_getLocation(self: *const ZigClangFunctionDecl) struct_ZigClangSourceLocation;
+pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bool;
+pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass;
+pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;
+pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt;
+
+pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;
+
+pub extern fn ZigClangFunctionType_getNoReturnAttr(self: *const ZigClangFunctionType) bool;
+pub extern fn ZigClangFunctionType_getCallConv(self: *const ZigClangFunctionType) ZigClangCallingConv;
+pub extern fn ZigClangFunctionType_getReturnType(self: *const ZigClangFunctionType) ZigClangQualType;
+
+pub extern fn ZigClangFunctionProtoType_isVariadic(self: *const struct_ZigClangFunctionProtoType) bool;
+pub extern fn ZigClangFunctionProtoType_getNumParams(self: *const struct_ZigClangFunctionProtoType) c_uint;
+pub extern fn ZigClangFunctionProtoType_getParamType(self: *const struct_ZigClangFunctionProtoType, i: c_uint) ZigClangQualType;
+
+pub const ZigClangSourceLocation = struct_ZigClangSourceLocation;
+pub const ZigClangQualType = struct_ZigClangQualType;
+pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase;
+pub const ZigClangAPValue = struct_ZigClangAPValue;
+pub const ZigClangAPSInt = struct_ZigClangAPSInt;
+pub const ZigClangASTContext = struct_ZigClangASTContext;
+pub const ZigClangASTUnit = struct_ZigClangASTUnit;
+pub const ZigClangArraySubscriptExpr = struct_ZigClangArraySubscriptExpr;
+pub const ZigClangArrayType = struct_ZigClangArrayType;
+pub const ZigClangAttributedType = struct_ZigClangAttributedType;
+pub const ZigClangBinaryOperator = struct_ZigClangBinaryOperator;
+pub const ZigClangBreakStmt = struct_ZigClangBreakStmt;
+pub const ZigClangBuiltinType = struct_ZigClangBuiltinType;
+pub const ZigClangCStyleCastExpr = struct_ZigClangCStyleCastExpr;
+pub const ZigClangCallExpr = struct_ZigClangCallExpr;
+pub const ZigClangCaseStmt = struct_ZigClangCaseStmt;
+pub const ZigClangCompoundAssignOperator = struct_ZigClangCompoundAssignOperator;
+pub const ZigClangConditionalOperator = struct_ZigClangConditionalOperator;
+pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType;
+pub const ZigClangContinueStmt = struct_ZigClangContinueStmt;
+pub const ZigClangDecayedType = struct_ZigClangDecayedType;
+pub const ZigClangDecl = struct_ZigClangDecl;
+pub const ZigClangDeclRefExpr = struct_ZigClangDeclRefExpr;
+pub const ZigClangDeclStmt = struct_ZigClangDeclStmt;
+pub const ZigClangDefaultStmt = struct_ZigClangDefaultStmt;
+pub const ZigClangDiagnosticOptions = struct_ZigClangDiagnosticOptions;
+pub const ZigClangDiagnosticsEngine = struct_ZigClangDiagnosticsEngine;
+pub const ZigClangDoStmt = struct_ZigClangDoStmt;
+pub const ZigClangElaboratedType = struct_ZigClangElaboratedType;
+pub const ZigClangEnumConstantDecl = struct_ZigClangEnumConstantDecl;
+pub const ZigClangEnumDecl = struct_ZigClangEnumDecl;
+pub const ZigClangEnumType = struct_ZigClangEnumType;
+pub const ZigClangExpr = struct_ZigClangExpr;
+pub const ZigClangFieldDecl = struct_ZigClangFieldDecl;
+pub const ZigClangFileID = struct_ZigClangFileID;
+pub const ZigClangForStmt = struct_ZigClangForStmt;
+pub const ZigClangFullSourceLoc = struct_ZigClangFullSourceLoc;
+pub const ZigClangFunctionProtoType = struct_ZigClangFunctionProtoType;
+pub const ZigClangIfStmt = struct_ZigClangIfStmt;
+pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr;
+pub const ZigClangIncompleteArrayType = struct_ZigClangIncompleteArrayType;
+pub const ZigClangIntegerLiteral = struct_ZigClangIntegerLiteral;
+pub const ZigClangMacroDefinitionRecord = struct_ZigClangMacroDefinitionRecord;
+pub const ZigClangMemberExpr = struct_ZigClangMemberExpr;
+pub const ZigClangNamedDecl = struct_ZigClangNamedDecl;
+pub const ZigClangNone = struct_ZigClangNone;
+pub const ZigClangPCHContainerOperations = struct_ZigClangPCHContainerOperations;
+pub const ZigClangParenExpr = struct_ZigClangParenExpr;
+pub const ZigClangParenType = struct_ZigClangParenType;
+pub const ZigClangParmVarDecl = struct_ZigClangParmVarDecl;
+pub const ZigClangPointerType = struct_ZigClangPointerType;
+pub const ZigClangPreprocessedEntity = struct_ZigClangPreprocessedEntity;
+pub const ZigClangRecordDecl = struct_ZigClangRecordDecl;
+pub const ZigClangRecordType = struct_ZigClangRecordType;
+pub const ZigClangReturnStmt = struct_ZigClangReturnStmt;
+pub const ZigClangSkipFunctionBodiesScope = struct_ZigClangSkipFunctionBodiesScope;
+pub const ZigClangSourceManager = struct_ZigClangSourceManager;
+pub const ZigClangSourceRange = struct_ZigClangSourceRange;
+pub const ZigClangStmt = struct_ZigClangStmt;
+pub const ZigClangStringLiteral = struct_ZigClangStringLiteral;
+pub const ZigClangStringRef = struct_ZigClangStringRef;
+pub const ZigClangSwitchStmt = struct_ZigClangSwitchStmt;
+pub const ZigClangTagDecl = struct_ZigClangTagDecl;
+pub const ZigClangType = struct_ZigClangType;
+pub const ZigClangTypedefNameDecl = struct_ZigClangTypedefNameDecl;
+pub const ZigClangTypedefType = struct_ZigClangTypedefType;
+pub const ZigClangUnaryExprOrTypeTraitExpr = struct_ZigClangUnaryExprOrTypeTraitExpr;
+pub const ZigClangUnaryOperator = struct_ZigClangUnaryOperator;
+pub const ZigClangValueDecl = struct_ZigClangValueDecl;
+pub const ZigClangVarDecl = struct_ZigClangVarDecl;
+pub const ZigClangWhileStmt = struct_ZigClangWhileStmt;
+
+pub const struct_ZigClangSourceLocation = extern struct {
+ ID: c_uint,
+};
+
+pub const Stage2ErrorMsg = extern struct {
+ filename_ptr: ?[*]const u8,
+ filename_len: usize,
+ msg_ptr: [*]const u8,
+ msg_len: usize,
+ // valid until the ASTUnit is freed
+ source: ?[*]const u8,
+ // 0 based
+ line: c_uint,
+ // 0 based
+ column: c_uint,
+ // byte offset into source
+ offset: c_uint,
+};
+pub extern fn ZigClangErrorMsg_delete(ptr: [*c]Stage2ErrorMsg, len: usize) void;
+
+pub extern fn ZigClangLoadFromCommandLine(
+ args_begin: [*]?[*]const u8,
+ args_end: [*]?[*]const u8,
+ errors_ptr: *[*]Stage2ErrorMsg,
+ errors_len: *usize,
+ resources_path: [*c]const u8,
+) ?*ZigClangASTUnit;
+
+pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind;
+pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*]const u8;
+
+pub const ZigClangDeclKind = extern enum {
+ AccessSpec,
+ Block,
+ Captured,
+ ClassScopeFunctionSpecialization,
+ Empty,
+ Export,
+ ExternCContext,
+ FileScopeAsm,
+ Friend,
+ FriendTemplate,
+ Import,
+ LinkageSpec,
+ Label,
+ Namespace,
+ NamespaceAlias,
+ ObjCCompatibleAlias,
+ ObjCCategory,
+ ObjCCategoryImpl,
+ ObjCImplementation,
+ ObjCInterface,
+ ObjCProtocol,
+ ObjCMethod,
+ ObjCProperty,
+ BuiltinTemplate,
+ ClassTemplate,
+ FunctionTemplate,
+ TypeAliasTemplate,
+ VarTemplate,
+ TemplateTemplateParm,
+ Enum,
+ Record,
+ CXXRecord,
+ ClassTemplateSpecialization,
+ ClassTemplatePartialSpecialization,
+ TemplateTypeParm,
+ ObjCTypeParam,
+ TypeAlias,
+ Typedef,
+ UnresolvedUsingTypename,
+ Using,
+ UsingDirective,
+ UsingPack,
+ UsingShadow,
+ ConstructorUsingShadow,
+ Binding,
+ Field,
+ ObjCAtDefsField,
+ ObjCIvar,
+ Function,
+ CXXDeductionGuide,
+ CXXMethod,
+ CXXConstructor,
+ CXXConversion,
+ CXXDestructor,
+ MSProperty,
+ NonTypeTemplateParm,
+ Var,
+ Decomposition,
+ ImplicitParam,
+ OMPCapturedExpr,
+ ParmVar,
+ VarTemplateSpecialization,
+ VarTemplatePartialSpecialization,
+ EnumConstant,
+ IndirectField,
+ OMPDeclareReduction,
+ UnresolvedUsingValue,
+ OMPRequires,
+ OMPThreadPrivate,
+ ObjCPropertyImpl,
+ PragmaComment,
+ PragmaDetectMismatch,
+ StaticAssert,
+ TranslationUnit,
+};
+
+pub const struct_ZigClangQualType = extern struct {
+ ptr: ?*c_void,
+};
+
+pub const ZigClangBuiltinTypeKind = extern enum {
+ OCLImage1dRO,
+ OCLImage1dArrayRO,
+ OCLImage1dBufferRO,
+ OCLImage2dRO,
+ OCLImage2dArrayRO,
+ OCLImage2dDepthRO,
+ OCLImage2dArrayDepthRO,
+ OCLImage2dMSAARO,
+ OCLImage2dArrayMSAARO,
+ OCLImage2dMSAADepthRO,
+ OCLImage2dArrayMSAADepthRO,
+ OCLImage3dRO,
+ OCLImage1dWO,
+ OCLImage1dArrayWO,
+ OCLImage1dBufferWO,
+ OCLImage2dWO,
+ OCLImage2dArrayWO,
+ OCLImage2dDepthWO,
+ OCLImage2dArrayDepthWO,
+ OCLImage2dMSAAWO,
+ OCLImage2dArrayMSAAWO,
+ OCLImage2dMSAADepthWO,
+ OCLImage2dArrayMSAADepthWO,
+ OCLImage3dWO,
+ OCLImage1dRW,
+ OCLImage1dArrayRW,
+ OCLImage1dBufferRW,
+ OCLImage2dRW,
+ OCLImage2dArrayRW,
+ OCLImage2dDepthRW,
+ OCLImage2dArrayDepthRW,
+ OCLImage2dMSAARW,
+ OCLImage2dArrayMSAARW,
+ OCLImage2dMSAADepthRW,
+ OCLImage2dArrayMSAADepthRW,
+ OCLImage3dRW,
+ OCLIntelSubgroupAVCMcePayload,
+ OCLIntelSubgroupAVCImePayload,
+ OCLIntelSubgroupAVCRefPayload,
+ OCLIntelSubgroupAVCSicPayload,
+ OCLIntelSubgroupAVCMceResult,
+ OCLIntelSubgroupAVCImeResult,
+ OCLIntelSubgroupAVCRefResult,
+ OCLIntelSubgroupAVCSicResult,
+ OCLIntelSubgroupAVCImeResultSingleRefStreamout,
+ OCLIntelSubgroupAVCImeResultDualRefStreamout,
+ OCLIntelSubgroupAVCImeSingleRefStreamin,
+ OCLIntelSubgroupAVCImeDualRefStreamin,
+ Void,
+ Bool,
+ Char_U,
+ UChar,
+ WChar_U,
+ Char8,
+ Char16,
+ Char32,
+ UShort,
+ UInt,
+ ULong,
+ ULongLong,
+ UInt128,
+ Char_S,
+ SChar,
+ WChar_S,
+ Short,
+ Int,
+ Long,
+ LongLong,
+ Int128,
+ ShortAccum,
+ Accum,
+ LongAccum,
+ UShortAccum,
+ UAccum,
+ ULongAccum,
+ ShortFract,
+ Fract,
+ LongFract,
+ UShortFract,
+ UFract,
+ ULongFract,
+ SatShortAccum,
+ SatAccum,
+ SatLongAccum,
+ SatUShortAccum,
+ SatUAccum,
+ SatULongAccum,
+ SatShortFract,
+ SatFract,
+ SatLongFract,
+ SatUShortFract,
+ SatUFract,
+ SatULongFract,
+ Half,
+ Float,
+ Double,
+ LongDouble,
+ Float16,
+ Float128,
+ NullPtr,
+ ObjCId,
+ ObjCClass,
+ ObjCSel,
+ OCLSampler,
+ OCLEvent,
+ OCLClkEvent,
+ OCLQueue,
+ OCLReserveID,
+ Dependent,
+ Overload,
+ BoundMember,
+ PseudoObject,
+ UnknownAny,
+ BuiltinFn,
+ ARCUnbridgedCast,
+ OMPArraySection,
+};
+
+pub const ZigClangCallingConv = extern enum {
+ C,
+ X86StdCall,
+ X86FastCall,
+ X86ThisCall,
+ X86VectorCall,
+ X86Pascal,
+ Win64,
+ X86_64SysV,
+ X86RegCall,
+ AAPCS,
+ AAPCS_VFP,
+ IntelOclBicc,
+ SpirFunction,
+ OpenCLKernel,
+ Swift,
+ PreserveMost,
+ PreserveAll,
+ AArch64VectorCall,
+};
+
+pub const ZigClangStorageClass = extern enum {
+ None,
+ Extern,
+ Static,
+ PrivateExtern,
+ Auto,
+ Register,
+};
+
+pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt;
+
+pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
+pub extern fn ZigClangCompoundStmt_body_end(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig
index 478edce020..7a30bbad98 100644
--- a/src-self-hosted/compilation.zig
+++ b/src-self-hosted/compilation.zig
@@ -569,9 +569,9 @@ pub const Compilation = struct {
'i', 'u' => blk: {
for (name[1..]) |byte|
switch (byte) {
- '0'...'9' => {},
- else => break :blk,
- };
+ '0'...'9' => {},
+ else => break :blk,
+ };
const is_signed = name[0] == 'i';
const bit_count = std.fmt.parseUnsigned(u32, name[1..], 10) catch |err| switch (err) {
error.Overflow => return error.Overflow,
@@ -841,11 +841,9 @@ pub const Compilation = struct {
};
errdefer self.gpa().free(source_code);
- const tree = try self.gpa().create(ast.Tree);
- tree.* = try std.zig.parse(self.gpa(), source_code);
+ const tree = try std.zig.parse(self.gpa(), source_code);
errdefer {
tree.deinit();
- self.gpa().destroy(tree);
}
break :blk try Scope.AstTree.create(self, tree, root_scope);
diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig
index 4c3edf6d5d..cbbf73f3f5 100644
--- a/src-self-hosted/main.zig
+++ b/src-self-hosted/main.zig
@@ -625,7 +625,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size);
defer allocator.free(source_code);
- var tree = std.zig.parse(allocator, source_code) catch |err| {
+ const tree = std.zig.parse(allocator, source_code) catch |err| {
try stderr.print("error parsing stdin: {}\n", err);
os.exit(1);
};
@@ -633,7 +633,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
var error_it = tree.errors.iterator(0);
while (error_it.next()) |parse_error| {
- const msg = try errmsg.Msg.createFromParseError(allocator, parse_error, &tree, "<stdin>");
+ const msg = try errmsg.Msg.createFromParseError(allocator, parse_error, tree, "<stdin>");
defer msg.destroy();
try msg.printToFile(stderr_file, color);
@@ -642,12 +642,12 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
os.exit(1);
}
if (flags.present("check")) {
- const anything_changed = try std.zig.render(allocator, io.null_out_stream, &tree);
+ const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
const code = if (anything_changed) u8(1) else u8(0);
os.exit(code);
}
- _ = try std.zig.render(allocator, stdout, &tree);
+ _ = try std.zig.render(allocator, stdout, tree);
return;
}
@@ -768,7 +768,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
};
defer fmt.loop.allocator.free(source_code);
- var tree = std.zig.parse(fmt.loop.allocator, source_code) catch |err| {
+ const tree = std.zig.parse(fmt.loop.allocator, source_code) catch |err| {
try stderr.print("error parsing file '{}': {}\n", file_path, err);
fmt.any_error = true;
return;
@@ -777,7 +777,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
var error_it = tree.errors.iterator(0);
while (error_it.next()) |parse_error| {
- const msg = try errmsg.Msg.createFromParseError(fmt.loop.allocator, parse_error, &tree, file_path);
+ const msg = try errmsg.Msg.createFromParseError(fmt.loop.allocator, parse_error, tree, file_path);
defer fmt.loop.allocator.destroy(msg);
try msg.printToFile(stderr_file, fmt.color);
@@ -788,7 +788,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
}
if (check_mode) {
- const anything_changed = try std.zig.render(fmt.loop.allocator, io.null_out_stream, &tree);
+ const anything_changed = try std.zig.render(fmt.loop.allocator, io.null_out_stream, tree);
if (anything_changed) {
try stderr.print("{}\n", file_path);
fmt.any_error = true;
@@ -798,7 +798,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
const baf = try io.BufferedAtomicFile.create(fmt.loop.allocator, file_path);
defer baf.destroy();
- const anything_changed = try std.zig.render(fmt.loop.allocator, baf.stream(), &tree);
+ const anything_changed = try std.zig.render(fmt.loop.allocator, baf.stream(), tree);
if (anything_changed) {
try stderr.print("{}\n", file_path);
try baf.finish();
@@ -858,7 +858,7 @@ fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
try stdout.write(usage);
}
-const info_zen =
+pub const info_zen =
\\
\\ * Communicate intent precisely.
\\ * Edge cases matter.
diff --git a/src-self-hosted/scope.zig b/src-self-hosted/scope.zig
index 9a84ad256e..4ff3e303a2 100644
--- a/src-self-hosted/scope.zig
+++ b/src-self-hosted/scope.zig
@@ -163,7 +163,6 @@ pub const Scope = struct {
pub fn destroy(self: *AstTree, comp: *Compilation) void {
comp.gpa().free(self.tree.source);
self.tree.deinit();
- comp.gpa().destroy(self.tree);
comp.gpa().destroy(self);
}
diff --git a/std/special/fmt_runner.zig b/src-self-hosted/stage1.zig
index f0ed6704ed..da2dcb414c 100644
--- a/std/special/fmt_runner.zig
+++ b/src-self-hosted/stage1.zig
@@ -1,32 +1,148 @@
+// This is Zig code that is used by both stage1 and stage2.
+// The prototypes in src/userland.h must match these definitions.
+
const std = @import("std");
const builtin = @import("builtin");
-const os = std.os;
-const io = std.io;
-const mem = std.mem;
-const Allocator = mem.Allocator;
-const ArrayList = std.ArrayList;
-const Buffer = std.Buffer;
+// ABI warning
+export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
+ const info_zen = @import("main.zig").info_zen;
+ ptr.* = &info_zen;
+ len.* = info_zen.len;
+}
+
+// ABI warning
+export fn stage2_panic(ptr: [*]const u8, len: usize) void {
+ @panic(ptr[0..len]);
+}
+
+// ABI warning
+const TranslateMode = extern enum {
+ import,
+ translate,
+};
+
+// ABI warning
+const Error = extern enum {
+ None,
+ OutOfMemory,
+ InvalidFormat,
+ SemanticAnalyzeFail,
+ AccessDenied,
+ Interrupted,
+ SystemResources,
+ FileNotFound,
+ FileSystem,
+ FileTooBig,
+ DivByZero,
+ Overflow,
+ PathAlreadyExists,
+ Unexpected,
+ ExactDivRemainder,
+ NegativeDenominator,
+ ShiftedOutOneBits,
+ CCompileErrors,
+ EndOfFile,
+ IsDir,
+ NotDir,
+ UnsupportedOperatingSystem,
+ SharingViolation,
+ PipeBusy,
+ PrimitiveTypeNotFound,
+ CacheUnavailable,
+ PathTooLong,
+ CCompilerCannotFindFile,
+ ReadingDepFile,
+ InvalidDepFile,
+ MissingArchitecture,
+ MissingOperatingSystem,
+ UnknownArchitecture,
+ UnknownOperatingSystem,
+ UnknownABI,
+ InvalidFilename,
+ DiskQuota,
+ DiskSpace,
+ UnexpectedWriteFailure,
+ UnexpectedSeekFailure,
+ UnexpectedFileTruncationFailure,
+ Unimplemented,
+ OperationAborted,
+ BrokenPipe,
+ NoSpaceLeft,
+};
+
+const FILE = std.c.FILE;
const ast = std.zig.ast;
+const translate_c = @import("translate_c.zig");
+
+/// Args should have a null terminating last arg.
+export fn stage2_translate_c(
+ out_ast: **ast.Tree,
+ out_errors_ptr: *[*]translate_c.ClangErrMsg,
+ out_errors_len: *usize,
+ args_begin: [*]?[*]const u8,
+ args_end: [*]?[*]const u8,
+ mode: TranslateMode,
+ resources_path: [*]const u8,
+) Error {
+ var errors: []translate_c.ClangErrMsg = undefined;
+ out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, switch (mode) {
+ .import => translate_c.Mode.import,
+ .translate => translate_c.Mode.translate,
+ }, &errors, resources_path) catch |err| switch (err) {
+ // TODO after https://github.com/ziglang/zig/issues/769 we can remove error.UnsupportedType
+ error.SemanticAnalyzeFail, error.UnsupportedType => {
+ out_errors_ptr.* = errors.ptr;
+ out_errors_len.* = errors.len;
+ return Error.CCompileErrors;
+ },
+ error.OutOfMemory => return Error.OutOfMemory,
+ };
+ return Error.None;
+}
-const arg = @import("fmt/arg.zig");
-const self_hosted_main = @import("fmt/main.zig");
-const Args = arg.Args;
-const Flag = arg.Flag;
-const errmsg = @import("fmt/errmsg.zig");
+export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void {
+ translate_c.freeErrors(errors_ptr[0..errors_len]);
+}
-var stderr_file: os.File = undefined;
-var stderr: *io.OutStream(os.File.WriteError) = undefined;
-var stdout: *io.OutStream(os.File.WriteError) = undefined;
+export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
+ const c_out_stream = &std.io.COutStream.init(output_file).stream;
+ _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {
+ error.SystemResources => return Error.SystemResources,
+ error.OperationAborted => return Error.OperationAborted,
+ error.BrokenPipe => return Error.BrokenPipe,
+ error.DiskQuota => return Error.DiskQuota,
+ error.FileTooBig => return Error.FileTooBig,
+ error.NoSpaceLeft => return Error.NoSpaceLeft,
+ error.AccessDenied => return Error.AccessDenied,
+ error.OutOfMemory => return Error.OutOfMemory,
+ error.Unexpected => return Error.Unexpected,
+ error.InputOutput => return Error.FileSystem,
+ };
+ return Error.None;
+}
+
+// TODO: just use the actual self-hosted zig fmt. Until the coroutine rewrite, we use a blocking implementation.
+export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int {
+ if (std.debug.runtime_safety) {
+ fmtMain(argc, argv) catch unreachable;
+ } else {
+ fmtMain(argc, argv) catch |e| {
+ std.debug.warn("{}\n", @errorName(e));
+ return -1;
+ };
+ }
+ return 0;
+}
-// This brings `zig fmt` to stage 1.
-pub fn main() !void {
- // Here we use an ArenaAllocator backed by a DirectAllocator because `zig fmt` is a short-lived,
- // one shot program. We don't need to waste time freeing memory and finding places to squish
- // bytes into. So we free everything all at once at the very end.
- var direct_allocator = std.heap.DirectAllocator.init();
- var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
- const allocator = &arena.allocator;
+fn fmtMain(argc: c_int, argv: [*]const [*]const u8) !void {
+ const allocator = std.heap.c_allocator;
+ var args_list = std.ArrayList([]const u8).init(allocator);
+ const argc_usize = @intCast(usize, argc);
+ var arg_i: usize = 0;
+ while (arg_i < argc_usize) : (arg_i += 1) {
+ try args_list.append(std.mem.toSliceConst(u8, argv[arg_i]));
+ }
var stdout_file = try std.io.getStdOut();
var stdout_out_stream = stdout_file.outStream();
@@ -35,9 +151,9 @@ pub fn main() !void {
stderr_file = try std.io.getStdErr();
var stderr_out_stream = stderr_file.outStream();
stderr = &stderr_out_stream.stream;
- const args = try std.os.argsAlloc(allocator);
- var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args[1..]);
+ const args = args_list.toSliceConst();
+ var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args[2..]);
defer flags.deinit();
if (flags.present("help")) {
@@ -71,7 +187,7 @@ pub fn main() !void {
const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
defer allocator.free(source_code);
- var tree = std.zig.parse(allocator, source_code) catch |err| {
+ const tree = std.zig.parse(allocator, source_code) catch |err| {
try stderr.print("error parsing stdin: {}\n", err);
os.exit(1);
};
@@ -79,18 +195,18 @@ pub fn main() !void {
var error_it = tree.errors.iterator(0);
while (error_it.next()) |parse_error| {
- try printErrMsgToFile(allocator, parse_error, &tree, "<stdin>", stderr_file, color);
+ try printErrMsgToFile(allocator, parse_error, tree, "<stdin>", stderr_file, color);
}
if (tree.errors.len != 0) {
os.exit(1);
}
if (flags.present("check")) {
- const anything_changed = try std.zig.render(allocator, io.null_out_stream, &tree);
+ const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
const code = if (anything_changed) u8(1) else u8(0);
os.exit(code);
}
- _ = try std.zig.render(allocator, stdout, &tree);
+ _ = try std.zig.render(allocator, stdout, tree);
return;
}
@@ -166,7 +282,7 @@ fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void
};
defer fmt.allocator.free(source_code);
- var tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
+ const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
try stderr.print("error parsing file '{}': {}\n", file_path, err);
fmt.any_error = true;
return;
@@ -175,7 +291,7 @@ fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void
var error_it = tree.errors.iterator(0);
while (error_it.next()) |parse_error| {
- try printErrMsgToFile(fmt.allocator, parse_error, &tree, file_path, stderr_file, fmt.color);
+ try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color);
}
if (tree.errors.len != 0) {
fmt.any_error = true;
@@ -183,17 +299,16 @@ fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void
}
if (check_mode) {
- const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, &tree);
+ const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree);
if (anything_changed) {
try stderr.print("{}\n", file_path);
fmt.any_error = true;
}
} else {
- // TODO make this evented
const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
defer baf.destroy();
- const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), &tree);
+ const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree);
if (anything_changed) {
try stderr.print("{}\n", file_path);
try baf.finish();
@@ -210,9 +325,14 @@ const Fmt = struct {
const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
};
-fn printErrMsgToFile(allocator: *mem.Allocator, parse_error: *const ast.Error, tree: *ast.Tree,
- path: []const u8, file: os.File, color: errmsg.Color,) !void
-{
+fn printErrMsgToFile(
+ allocator: *mem.Allocator,
+ parse_error: *const ast.Error,
+ tree: *ast.Tree,
+ path: []const u8,
+ file: os.File,
+ color: errmsg.Color,
+) !void {
const color_on = switch (color) {
errmsg.Color.Auto => file.isTty(),
errmsg.Color.On => true,
@@ -258,3 +378,20 @@ fn printErrMsgToFile(allocator: *mem.Allocator, parse_error: *const ast.Error, t
try stream.writeByteNTimes('~', last_token.end - first_token.start);
try stream.write("\n");
}
+
+const os = std.os;
+const io = std.io;
+const mem = std.mem;
+const Allocator = mem.Allocator;
+const ArrayList = std.ArrayList;
+const Buffer = std.Buffer;
+
+const arg = @import("arg.zig");
+const self_hosted_main = @import("main.zig");
+const Args = arg.Args;
+const Flag = arg.Flag;
+const errmsg = @import("errmsg.zig");
+
+var stderr_file: os.File = undefined;
+var stderr: *io.OutStream(os.File.WriteError) = undefined;
+var stdout: *io.OutStream(os.File.WriteError) = undefined;
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
new file mode 100644
index 0000000000..703f907907
--- /dev/null
+++ b/src-self-hosted/translate_c.zig
@@ -0,0 +1,682 @@
+// This is the userland implementation of translate-c which will be used by both stage1
+// and stage2. Currently the only way it is used is with `zig translate-c-2`.
+
+const std = @import("std");
+const builtin = @import("builtin");
+const assert = std.debug.assert;
+const ast = std.zig.ast;
+const Token = std.zig.Token;
+use @import("clang.zig");
+
+pub const Mode = enum {
+ import,
+ translate,
+};
+
+// TODO merge with Type.Fn.CallingConvention
+const CallingConvention = builtin.TypeInfo.CallingConvention;
+
+pub const ClangErrMsg = Stage2ErrorMsg;
+
+pub const Error = error{
+ OutOfMemory,
+ UnsupportedType,
+};
+pub const TransError = error{
+ OutOfMemory,
+ UnsupportedTranslation,
+};
+
+const DeclTable = std.HashMap(usize, void, addrHash, addrEql);
+
+fn addrHash(x: usize) u32 {
+ switch (@typeInfo(usize).Int.bits) {
+ 32 => return x,
+ // pointers are usually aligned so we ignore the bits that are probably all 0 anyway
+ // usually the larger bits of addr space are unused so we just chop em off
+ 64 => return @truncate(u32, x >> 4),
+ else => @compileError("unreachable"),
+ }
+}
+
+fn addrEql(a: usize, b: usize) bool {
+ return a == b;
+}
+
+const Scope = struct {
+ id: Id,
+ parent: ?*Scope,
+
+ const Id = enum {
+ Switch,
+ Var,
+ Block,
+ Root,
+ While,
+ };
+ const Switch = struct {
+ base: Scope,
+ };
+
+ const Var = struct {
+ base: Scope,
+ c_name: []const u8,
+ zig_name: []const u8,
+ };
+
+ const Block = struct {
+ base: Scope,
+ block_node: *ast.Node.Block,
+
+ /// Don't forget to set rbrace token later
+ fn create(c: *Context, parent: *Scope, lbrace_tok: ast.TokenIndex) !*Block {
+ const block = try c.a().create(Block);
+ block.* = Block{
+ .base = Scope{
+ .id = Id.Block,
+ .parent = parent,
+ },
+ .block_node = try c.a().create(ast.Node.Block),
+ };
+ block.block_node.* = ast.Node.Block{
+ .base = ast.Node{ .id = ast.Node.Id.Block },
+ .label = null,
+ .lbrace = lbrace_tok,
+ .statements = ast.Node.Block.StatementList.init(c.a()),
+ .rbrace = undefined,
+ };
+ return block;
+ }
+ };
+
+ const Root = struct {
+ base: Scope,
+ };
+
+ const While = struct {
+ base: Scope,
+ };
+};
+
+const TransResult = struct {
+ node: *ast.Node,
+ node_scope: *Scope,
+ child_scope: *Scope,
+};
+
+const Context = struct {
+ tree: *ast.Tree,
+ source_buffer: *std.Buffer,
+ err: Error,
+ source_manager: *ZigClangSourceManager,
+ decl_table: DeclTable,
+ global_scope: *Scope.Root,
+ mode: Mode,
+
+ fn a(c: *Context) *std.mem.Allocator {
+ return &c.tree.arena_allocator.allocator;
+ }
+
+ /// Convert a null-terminated C string to a slice allocated in the arena
+ fn str(c: *Context, s: [*]const u8) ![]u8 {
+ return std.mem.dupe(c.a(), u8, std.mem.toSliceConst(u8, s));
+ }
+
+ /// Convert a clang source location to a file:line:column string
+ fn locStr(c: *Context, loc: ZigClangSourceLocation) ![]u8 {
+ const spelling_loc = ZigClangSourceManager_getSpellingLoc(c.source_manager, loc);
+ const filename_c = ZigClangSourceManager_getFilename(c.source_manager, spelling_loc);
+ const filename = if (filename_c) |s| try c.str(s) else ([]const u8)("(no file)");
+
+ const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc);
+ const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc);
+ return std.fmt.allocPrint(c.a(), "{}:{}:{}", filename, line, column);
+ }
+};
+
+pub fn translate(
+ backing_allocator: *std.mem.Allocator,
+ args_begin: [*]?[*]const u8,
+ args_end: [*]?[*]const u8,
+ mode: Mode,
+ errors: *[]ClangErrMsg,
+ resources_path: [*]const u8,
+) !*ast.Tree {
+ const ast_unit = ZigClangLoadFromCommandLine(
+ args_begin,
+ args_end,
+ &errors.ptr,
+ &errors.len,
+ resources_path,
+ ) orelse {
+ if (errors.len == 0) return error.OutOfMemory;
+ return error.SemanticAnalyzeFail;
+ };
+ defer ZigClangASTUnit_delete(ast_unit);
+
+ var tree_arena = std.heap.ArenaAllocator.init(backing_allocator);
+ errdefer tree_arena.deinit();
+ var arena = &tree_arena.allocator;
+
+ const root_node = try arena.create(ast.Node.Root);
+ root_node.* = ast.Node.Root{
+ .base = ast.Node{ .id = ast.Node.Id.Root },
+ .decls = ast.Node.Root.DeclList.init(arena),
+ .doc_comments = null,
+ // initialized with the eof token at the end
+ .eof_token = undefined,
+ };
+
+ const tree = try arena.create(ast.Tree);
+ tree.* = ast.Tree{
+ .source = undefined, // need to use Buffer.toOwnedSlice later
+ .root_node = root_node,
+ .arena_allocator = undefined,
+ .tokens = ast.Tree.TokenList.init(arena),
+ .errors = ast.Tree.ErrorList.init(arena),
+ };
+ tree.arena_allocator = tree_arena;
+ arena = &tree.arena_allocator.allocator;
+
+ var source_buffer = try std.Buffer.initSize(arena, 0);
+
+ var context = Context{
+ .tree = tree,
+ .source_buffer = &source_buffer,
+ .source_manager = ZigClangASTUnit_getSourceManager(ast_unit),
+ .err = undefined,
+ .decl_table = DeclTable.init(arena),
+ .global_scope = try arena.create(Scope.Root),
+ .mode = mode,
+ };
+ context.global_scope.* = Scope.Root{
+ .base = Scope{
+ .id = Scope.Id.Root,
+ .parent = null,
+ },
+ };
+
+ if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) {
+ return context.err;
+ }
+
+ _ = try appendToken(&context, .Eof, "");
+ tree.source = source_buffer.toOwnedSlice();
+ if (false) {
+ std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source);
+ var i: usize = 0;
+ while (i < tree.tokens.len) : (i += 1) {
+ const token = tree.tokens.at(i);
+ std.debug.warn("{}\n", token);
+ }
+ }
+ return tree;
+}
+
+extern fn declVisitorC(context: ?*c_void, decl: *const ZigClangDecl) bool {
+ const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
+ declVisitor(c, decl) catch |err| {
+ c.err = err;
+ return false;
+ };
+ return true;
+}
+
+fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
+ switch (ZigClangDecl_getKind(decl)) {
+ .Function => {
+ return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
+ },
+ .Typedef => {
+ try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs");
+ },
+ .Enum => {
+ try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums");
+ },
+ .Record => {
+ try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs");
+ },
+ .Var => {
+ try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for variables");
+ },
+ else => {
+ const decl_name = try c.str(ZigClangDecl_getDeclKindName(decl));
+ try emitWarning(c, ZigClangDecl_getLocation(decl), "ignoring {} declaration", decl_name);
+ },
+ }
+}
+
+fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
+ if (try c.decl_table.put(@ptrToInt(fn_decl), {})) |_| return; // Avoid processing this decl twice
+ const rp = makeRestorePoint(c);
+ const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));
+ const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
+ const fn_qt = ZigClangFunctionDecl_getType(fn_decl);
+ const fn_type = ZigClangQualType_getTypePtr(fn_qt);
+ var scope = &c.global_scope.base;
+ const has_body = ZigClangFunctionDecl_hasBody(fn_decl);
+ const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl);
+ const decl_ctx = FnDeclContext{
+ .fn_name = fn_name,
+ .has_body = has_body,
+ .storage_class = storage_class,
+ .scope = &scope,
+ .is_export = switch (storage_class) {
+ .None => has_body,
+ .Extern, .Static => false,
+ .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern"),
+ .Auto => unreachable, // Not legal on functions
+ .Register => unreachable, // Not legal on functions
+ },
+ };
+ const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
+ .FunctionProto => blk: {
+ const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);
+ break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
+ error.UnsupportedType => {
+ return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
+ },
+ error.OutOfMemory => return error.OutOfMemory,
+ };
+ },
+ .FunctionNoProto => blk: {
+ const fn_no_proto_type = @ptrCast(*const ZigClangFunctionType, fn_type);
+ break :blk transFnNoProto(rp, fn_no_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
+ error.UnsupportedType => {
+ return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
+ },
+ error.OutOfMemory => return error.OutOfMemory,
+ };
+ },
+ else => unreachable,
+ };
+
+ if (!decl_ctx.has_body) {
+ const semi_tok = try appendToken(c, .Semicolon, ";");
+ return addTopLevelDecl(c, fn_name, &proto_node.base);
+ }
+
+ // actual function definition with body
+ const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
+ const result = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.UnsupportedTranslation => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"),
+ };
+ assert(result.node.id == ast.Node.Id.Block);
+ proto_node.body_node = result.node;
+
+ return addTopLevelDecl(c, fn_name, &proto_node.base);
+}
+
+const ResultUsed = enum {
+ used,
+ unused,
+};
+
+const LRValue = enum {
+ l_value,
+ r_value,
+};
+
+fn transStmt(
+ rp: RestorePoint,
+ scope: *Scope,
+ stmt: *const ZigClangStmt,
+ result_used: ResultUsed,
+ lrvalue: LRValue,
+) !TransResult {
+ const sc = ZigClangStmt_getStmtClass(stmt);
+ switch (sc) {
+ .CompoundStmtClass => return transCompoundStmt(rp, scope, @ptrCast(*const ZigClangCompoundStmt, stmt)),
+ else => {
+ return revertAndWarn(
+ rp,
+ error.UnsupportedTranslation,
+ ZigClangStmt_getBeginLoc(stmt),
+ "TODO implement translation of stmt class {}",
+ @tagName(sc),
+ );
+ },
+ }
+}
+
+fn transCompoundStmtInline(
+ rp: RestorePoint,
+ parent_scope: *Scope,
+ stmt: *const ZigClangCompoundStmt,
+ block_node: *ast.Node.Block,
+) TransError!TransResult {
+ var it = ZigClangCompoundStmt_body_begin(stmt);
+ const end_it = ZigClangCompoundStmt_body_end(stmt);
+ var scope = parent_scope;
+ while (it != end_it) : (it += 1) {
+ const result = try transStmt(rp, scope, it.*, .unused, .r_value);
+ scope = result.child_scope;
+ try block_node.statements.push(result.node);
+ }
+ return TransResult{
+ .node = &block_node.base,
+ .child_scope = scope,
+ .node_scope = scope,
+ };
+}
+
+fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) !TransResult {
+ const lbrace_tok = try appendToken(rp.c, .LBrace, "{");
+ const block_scope = try Scope.Block.create(rp.c, scope, lbrace_tok);
+ const inline_result = try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);
+ block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
+ return TransResult{
+ .node = &block_scope.block_node.base,
+ .node_scope = inline_result.node_scope,
+ .child_scope = inline_result.child_scope,
+ };
+}
+
+fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void {
+ try c.tree.root_node.decls.push(decl_node);
+}
+
+fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) Error!*ast.Node {
+ return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
+}
+
+fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType {
+ const canon = ZigClangQualType_getCanonicalType(qt);
+ return ZigClangQualType_getTypePtr(canon);
+}
+
+const RestorePoint = struct {
+ c: *Context,
+ token_index: ast.TokenIndex,
+ src_buf_index: usize,
+
+ fn activate(self: RestorePoint) void {
+ self.c.tree.tokens.shrink(self.token_index);
+ self.c.source_buffer.shrink(self.src_buf_index);
+ }
+};
+
+fn makeRestorePoint(c: *Context) RestorePoint {
+ return RestorePoint{
+ .c = c,
+ .token_index = c.tree.tokens.len,
+ .src_buf_index = c.source_buffer.len(),
+ };
+}
+
+fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSourceLocation) Error!*ast.Node {
+ switch (ZigClangType_getTypeClass(ty)) {
+ .Builtin => {
+ const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
+ switch (ZigClangBuiltinType_getKind(builtin_ty)) {
+ .Void => return appendIdentifier(rp.c, "c_void"),
+ .Bool => return appendIdentifier(rp.c, "bool"),
+ .Char_U, .UChar, .Char_S, .Char8 => return appendIdentifier(rp.c, "u8"),
+ .SChar => return appendIdentifier(rp.c, "i8"),
+ .UShort => return appendIdentifier(rp.c, "c_ushort"),
+ .UInt => return appendIdentifier(rp.c, "c_uint"),
+ .ULong => return appendIdentifier(rp.c, "c_ulong"),
+ .ULongLong => return appendIdentifier(rp.c, "c_ulonglong"),
+ .Short => return appendIdentifier(rp.c, "c_short"),
+ .Int => return appendIdentifier(rp.c, "c_int"),
+ .Long => return appendIdentifier(rp.c, "c_long"),
+ .LongLong => return appendIdentifier(rp.c, "c_longlong"),
+ .UInt128 => return appendIdentifier(rp.c, "u128"),
+ .Int128 => return appendIdentifier(rp.c, "i128"),
+ .Float => return appendIdentifier(rp.c, "f32"),
+ .Double => return appendIdentifier(rp.c, "f64"),
+ .Float128 => return appendIdentifier(rp.c, "f128"),
+ .Float16 => return appendIdentifier(rp.c, "f16"),
+ .LongDouble => return appendIdentifier(rp.c, "c_longdouble"),
+ else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type"),
+ }
+ },
+ .FunctionProto => {
+ const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
+ const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null);
+ return &fn_proto.base;
+ },
+ else => {
+ const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
+ return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", type_name);
+ },
+ }
+}
+
+const FnDeclContext = struct {
+ fn_name: []const u8,
+ has_body: bool,
+ storage_class: ZigClangStorageClass,
+ scope: **Scope,
+ is_export: bool,
+};
+
+fn transCC(
+ rp: RestorePoint,
+ fn_ty: *const ZigClangFunctionType,
+ source_loc: ZigClangSourceLocation,
+) !CallingConvention {
+ const clang_cc = ZigClangFunctionType_getCallConv(fn_ty);
+ switch (clang_cc) {
+ .C => return CallingConvention.C,
+ .X86StdCall => return CallingConvention.Stdcall,
+ else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: {}", @tagName(clang_cc)),
+ }
+}
+
+fn transFnProto(
+ rp: RestorePoint,
+ fn_proto_ty: *const ZigClangFunctionProtoType,
+ source_loc: ZigClangSourceLocation,
+ fn_decl_context: ?FnDeclContext,
+) !*ast.Node.FnProto {
+ const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);
+ const cc = try transCC(rp, fn_ty, source_loc);
+ const is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty);
+ const param_count: usize = ZigClangFunctionProtoType_getNumParams(fn_proto_ty);
+ var i: usize = 0;
+ while (i < param_count) : (i += 1) {
+ return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO: implement parameters for FunctionProto in transType");
+ }
+
+ return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
+}
+
+fn transFnNoProto(
+ rp: RestorePoint,
+ fn_ty: *const ZigClangFunctionType,
+ source_loc: ZigClangSourceLocation,
+ fn_decl_context: ?FnDeclContext,
+) !*ast.Node.FnProto {
+ const cc = try transCC(rp, fn_ty, source_loc);
+ const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true;
+ return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
+}
+
+fn finishTransFnProto(
+ rp: RestorePoint,
+ fn_ty: *const ZigClangFunctionType,
+ source_loc: ZigClangSourceLocation,
+ fn_decl_context: ?FnDeclContext,
+ is_var_args: bool,
+ cc: CallingConvention,
+) !*ast.Node.FnProto {
+ const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
+
+ // TODO check for always_inline attribute
+ // TODO check for align attribute
+
+ // pub extern fn name(...) T
+ const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub");
+ const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;
+ const extern_export_inline_tok = if (is_export)
+ try appendToken(rp.c, .Keyword_export, "export")
+ else if (cc == .C)
+ try appendToken(rp.c, .Keyword_extern, "extern")
+ else
+ null;
+ const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn");
+ const name_tok = if (fn_decl_context) |ctx| try appendToken(rp.c, .Identifier, ctx.fn_name) else null;
+ const lparen_tok = try appendToken(rp.c, .LParen, "(");
+ const var_args_tok = if (is_var_args) try appendToken(rp.c, .Ellipsis3, "...") else null;
+ const rparen_tok = try appendToken(rp.c, .RParen, ")");
+
+ const return_type_node = blk: {
+ if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) {
+ break :blk try appendIdentifier(rp.c, "noreturn");
+ } else {
+ const return_qt = ZigClangFunctionType_getReturnType(fn_ty);
+ if (ZigClangType_isVoidType(qualTypeCanon(return_qt))) {
+ break :blk try appendIdentifier(rp.c, "void");
+ } else {
+ break :blk transQualType(rp, return_qt, source_loc) catch |err| switch (err) {
+ error.UnsupportedType => {
+ try emitWarning(rp.c, source_loc, "unsupported function proto return type");
+ return err;
+ },
+ error.OutOfMemory => return error.OutOfMemory,
+ };
+ }
+ }
+ };
+
+ const fn_proto = try rp.c.a().create(ast.Node.FnProto);
+ fn_proto.* = ast.Node.FnProto{
+ .base = ast.Node{ .id = ast.Node.Id.FnProto },
+ .doc_comments = null,
+ .visib_token = pub_tok,
+ .fn_token = fn_tok,
+ .name_token = name_tok,
+ .params = ast.Node.FnProto.ParamList.init(rp.c.a()),
+ .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node },
+ .var_args_token = null, // TODO this field is broken in the AST data model
+ .extern_export_inline_token = extern_export_inline_tok,
+ .cc_token = cc_tok,
+ .async_attr = null,
+ .body_node = null,
+ .lib_name = null,
+ .align_expr = null,
+ .section_expr = null,
+ };
+ if (is_var_args) {
+ const var_arg_node = try rp.c.a().create(ast.Node.ParamDecl);
+ var_arg_node.* = ast.Node.ParamDecl{
+ .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
+ .doc_comments = null,
+ .comptime_token = null,
+ .noalias_token = null,
+ .name_token = null,
+ .type_node = undefined,
+ .var_args_token = var_args_tok,
+ };
+ try fn_proto.params.push(&var_arg_node.base);
+ }
+ return fn_proto;
+}
+
+fn revertAndWarn(
+ rp: RestorePoint,
+ err: var,
+ source_loc: ZigClangSourceLocation,
+ comptime format: []const u8,
+ args: ...,
+) (@typeOf(err) || error{OutOfMemory}) {
+ rp.activate();
+ try emitWarning(rp.c, source_loc, format, args);
+ return err;
+}
+
+fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []const u8, args: ...) !void {
+ _ = try appendTokenFmt(c, .LineComment, "// {}: warning: " ++ format, c.locStr(loc), args);
+}
+
+fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: ...) !void {
+ // const name = @compileError(msg);
+ const const_tok = try appendToken(c, .Keyword_const, "const");
+ const name_tok = try appendToken(c, .Identifier, name);
+ const eq_tok = try appendToken(c, .Equal, "=");
+ const builtin_tok = try appendToken(c, .Builtin, "@compileError");
+ const lparen_tok = try appendToken(c, .LParen, "(");
+ const msg_tok = try appendTokenFmt(c, .StringLiteral, "\"" ++ format ++ "\"", args);
+ const rparen_tok = try appendToken(c, .RParen, ")");
+ const semi_tok = try appendToken(c, .Semicolon, ";");
+
+ const msg_node = try c.a().create(ast.Node.StringLiteral);
+ msg_node.* = ast.Node.StringLiteral{
+ .base = ast.Node{ .id = ast.Node.Id.StringLiteral },
+ .token = msg_tok,
+ };
+
+ const call_node = try c.a().create(ast.Node.BuiltinCall);
+ call_node.* = ast.Node.BuiltinCall{
+ .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
+ .builtin_token = builtin_tok,
+ .params = ast.Node.BuiltinCall.ParamList.init(c.a()),
+ .rparen_token = rparen_tok,
+ };
+ try call_node.params.push(&msg_node.base);
+
+ const var_decl_node = try c.a().create(ast.Node.VarDecl);
+ var_decl_node.* = ast.Node.VarDecl{
+ .base = ast.Node{ .id = ast.Node.Id.VarDecl },
+ .doc_comments = null,
+ .visib_token = null,
+ .thread_local_token = null,
+ .name_token = name_tok,
+ .eq_token = eq_tok,
+ .mut_token = const_tok,
+ .comptime_token = null,
+ .extern_export_token = null,
+ .lib_name = null,
+ .type_node = null,
+ .align_node = null,
+ .section_node = null,
+ .init_node = &call_node.base,
+ .semicolon_token = semi_tok,
+ };
+ try c.tree.root_node.decls.push(&var_decl_node.base);
+}
+
+fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex {
+ return appendTokenFmt(c, token_id, "{}", bytes);
+}
+
+fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !ast.TokenIndex {
+ const S = struct {
+ fn callback(context: *Context, bytes: []const u8) error{OutOfMemory}!void {
+ return context.source_buffer.append(bytes);
+ }
+ };
+ const start_index = c.source_buffer.len();
+ errdefer c.source_buffer.shrink(start_index);
+
+ try std.fmt.format(c, error{OutOfMemory}, S.callback, format, args);
+ const end_index = c.source_buffer.len();
+ const token_index = c.tree.tokens.len;
+ const new_token = try c.tree.tokens.addOne();
+ errdefer c.tree.tokens.shrink(token_index);
+
+ new_token.* = Token{
+ .id = token_id,
+ .start = start_index,
+ .end = end_index,
+ };
+ try c.source_buffer.appendByte('\n');
+
+ return token_index;
+}
+
+fn appendIdentifier(c: *Context, name: []const u8) !*ast.Node {
+ const token_index = try appendToken(c, .Identifier, name);
+ const identifier = try c.a().create(ast.Node.Identifier);
+ identifier.* = ast.Node.Identifier{
+ .base = ast.Node{ .id = ast.Node.Id.Identifier },
+ .token = token_index,
+ };
+ return &identifier.base;
+}
+
+pub fn freeErrors(errors: []ClangErrMsg) void {
+ ZigClangErrorMsg_delete(errors.ptr, errors.len);
+}
diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig
index d8c0f7b5c8..f1c7fc0b50 100644
--- a/src-self-hosted/value.zig
+++ b/src-self-hosted/value.zig
@@ -538,21 +538,21 @@ pub const Value = struct {
switch (self.base.typ.id) {
Type.Id.Int => {
const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
- if (self.big_int.len == 0) {
+ if (self.big_int.len() == 0) {
return llvm.ConstNull(type_ref);
}
- const unsigned_val = if (self.big_int.len == 1) blk: {
+ const unsigned_val = if (self.big_int.len() == 1) blk: {
break :blk llvm.ConstInt(type_ref, self.big_int.limbs[0], @boolToInt(false));
} else if (@sizeOf(std.math.big.Limb) == @sizeOf(u64)) blk: {
break :blk llvm.ConstIntOfArbitraryPrecision(
type_ref,
- @intCast(c_uint, self.big_int.len),
+ @intCast(c_uint, self.big_int.len()),
@ptrCast([*]u64, self.big_int.limbs.ptr),
);
} else {
@compileError("std.math.Big.Int.Limb size does not match LLVM");
};
- return if (self.big_int.positive) unsigned_val else llvm.ConstNeg(unsigned_val);
+ return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val);
},
Type.Id.ComptimeInt => unreachable,
else => unreachable,
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 92faad1e03..ecc0d1a9bb 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -55,7 +55,7 @@ struct IrExecutable {
size_t mem_slot_count;
size_t next_debug_id;
size_t *backward_branch_count;
- size_t backward_branch_quota;
+ size_t *backward_branch_quota;
ZigFn *fn_entry;
Buf *c_import_buf;
AstNode *source_node;
@@ -1350,6 +1350,7 @@ struct ZigFn {
IrExecutable ir_executable;
IrExecutable analyzed_executable;
size_t prealloc_bbc;
+ size_t prealloc_backward_branch_quota;
AstNode **param_source_nodes;
Buf **param_names;
@@ -1855,10 +1856,13 @@ struct CodeGen {
bool strip_debug_symbols;
bool is_test_build;
bool is_single_threaded;
+ bool want_single_threaded;
bool linker_rdynamic;
bool each_lib_rpath;
bool is_dummy_so;
bool disable_gen_h;
+ bool bundle_compiler_rt;
+ bool disable_stack_probing;
Buf *mmacosx_version_min;
Buf *mios_version_min;
@@ -2291,6 +2295,7 @@ enum IrInstructionId {
IrInstructionIdVectorToArray,
IrInstructionIdArrayToVector,
IrInstructionIdAssertZero,
+ IrInstructionIdAssertNonNull,
};
struct IrInstruction {
@@ -3480,6 +3485,12 @@ struct IrInstructionAssertZero {
IrInstruction *target;
};
+struct IrInstructionAssertNonNull {
+ IrInstruction base;
+
+ IrInstruction *target;
+};
+
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 394364c68f..57244aba6a 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -969,8 +969,9 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no
Buf *type_name)
{
size_t backward_branch_count = 0;
+ size_t backward_branch_quota = default_backward_branch_quota;
return ir_eval_const_value(g, scope, node, type_entry,
- &backward_branch_count, default_backward_branch_quota,
+ &backward_branch_count, &backward_branch_quota,
nullptr, nullptr, node, type_name, nullptr, nullptr);
}
@@ -1907,6 +1908,18 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
return ErrorNone;
}
+static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) {
+ // Only integer types are allowed by the C ABI
+ if(ty->id != ZigTypeIdInt)
+ return false;
+
+ // According to the ANSI C standard the enumeration type should be either a
+ // signed char, a signed integer or an unsigned one. But GCC/Clang allow
+ // other integral types as a compiler extension so let's accomodate them
+ // aswell.
+ return type_allowed_in_extern(g, ty);
+}
+
static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
assert(enum_type->id == ZigTypeIdEnum);
@@ -1964,7 +1977,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
enum_type->abi_size = tag_int_type->abi_size;
enum_type->abi_align = tag_int_type->abi_align;
- // TODO: Are extern enums allowed to have an init_arg_expr?
if (decl_node->data.container_decl.init_arg_expr != nullptr) {
ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
if (type_is_invalid(wanted_tag_int_type)) {
@@ -1973,24 +1985,29 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
enum_type->data.enumeration.is_invalid = true;
add_node_error(g, decl_node->data.container_decl.init_arg_expr,
buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
- } else if (wanted_tag_int_type->data.integral.is_signed) {
- enum_type->data.enumeration.is_invalid = true;
- add_node_error(g, decl_node->data.container_decl.init_arg_expr,
- buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
- } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) {
+ } else if (enum_type->data.enumeration.layout == ContainerLayoutExtern &&
+ !type_is_valid_extern_enum_tag(g, wanted_tag_int_type)) {
enum_type->data.enumeration.is_invalid = true;
- add_node_error(g, decl_node->data.container_decl.init_arg_expr,
- buf_sprintf("'%s' too small to hold all bits; must be at least '%s'",
- buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name)));
+ ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr,
+ buf_sprintf("'%s' is not a valid tag type for an extern enum",
+ buf_ptr(&wanted_tag_int_type->name)));
+ add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr,
+ buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid"));
} else {
tag_int_type = wanted_tag_int_type;
}
}
+
enum_type->data.enumeration.tag_int_type = tag_int_type;
enum_type->size_in_bits = tag_int_type->size_in_bits;
enum_type->abi_size = tag_int_type->abi_size;
enum_type->abi_align = tag_int_type->abi_align;
+ BigInt bi_one;
+ bigint_init_unsigned(&bi_one, 1);
+
+ TypeEnumField *last_enum_field = nullptr;
+
for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
@@ -2016,60 +2033,58 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
AstNode *tag_value = field_node->data.struct_field.value;
- // In this first pass we resolve explicit tag values.
- // In a second pass we will fill in the unspecified ones.
if (tag_value != nullptr) {
+ // A user-specified value is available
ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
if (type_is_invalid(result->type)) {
enum_type->data.enumeration.is_invalid = true;
continue;
}
+
assert(result->special != ConstValSpecialRuntime);
- assert(result->type->id == ZigTypeIdInt ||
- result->type->id == ZigTypeIdComptimeInt);
- auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
- if (entry == nullptr) {
- bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
+ assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt);
+
+ bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
+ } else {
+ // No value was explicitly specified: allocate the last value + 1
+ // or, if this is the first element, zero
+ if (last_enum_field != nullptr) {
+ bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one);
} else {
- Buf *val_buf = buf_alloc();
- bigint_append_buf(val_buf, &result->data.x_bigint, 10);
+ bigint_init_unsigned(&type_enum_field->value, 0);
+ }
- ErrorMsg *msg = add_node_error(g, tag_value,
- buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
- add_error_note(g, msg, entry->value,
- buf_sprintf("other occurrence here"));
+ // Make sure we can represent this number with tag_int_type
+ if (!bigint_fits_in_bits(&type_enum_field->value,
+ tag_int_type->size_in_bits,
+ tag_int_type->data.integral.is_signed)) {
enum_type->data.enumeration.is_invalid = true;
- continue;
+
+ Buf *val_buf = buf_alloc();
+ bigint_append_buf(val_buf, &type_enum_field->value, 10);
+ add_node_error(g, field_node,
+ buf_sprintf("enumeration value %s too large for type '%s'",
+ buf_ptr(val_buf), buf_ptr(&tag_int_type->name)));
+
+ break;
}
}
- }
- // Now iterate again and populate the unspecified tag values
- uint32_t next_maybe_unoccupied_index = 0;
+ // Make sure the value is unique
+ auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
+ if (entry != nullptr) {
+ enum_type->data.enumeration.is_invalid = true;
- for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
- AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
- TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
- AstNode *tag_value = field_node->data.struct_field.value;
+ Buf *val_buf = buf_alloc();
+ bigint_append_buf(val_buf, &type_enum_field->value, 10);
- if (tag_value == nullptr) {
- if (occupied_tag_values.size() == 0) {
- bigint_init_unsigned(&type_enum_field->value, next_maybe_unoccupied_index);
- next_maybe_unoccupied_index += 1;
- } else {
- BigInt proposed_value;
- for (;;) {
- bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index);
- next_maybe_unoccupied_index += 1;
- auto entry = occupied_tag_values.put_unique(proposed_value, field_node);
- if (entry != nullptr) {
- continue;
- }
- break;
- }
- bigint_init_bigint(&type_enum_field->value, &proposed_value);
- }
+ ErrorMsg *msg = add_node_error(g, field_node,
+ buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
+ add_error_note(g, msg, entry->value,
+ buf_sprintf("other occurrence here"));
}
+
+ last_enum_field = type_enum_field;
}
enum_type->data.enumeration.zero_bits_loop_flag = false;
@@ -2607,7 +2622,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
return ErrorNone;
}
-static void get_fully_qualified_decl_name(Buf *buf, Tld *tld) {
+static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, bool is_test) {
buf_resize(buf, 0);
Scope *scope = tld->parent_scope;
@@ -2617,15 +2632,23 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld) {
ScopeDecls *decls_scope = reinterpret_cast<ScopeDecls *>(scope);
buf_append_buf(buf, &decls_scope->container_type->name);
if (buf_len(buf) != 0) buf_append_char(buf, NAMESPACE_SEP_CHAR);
- buf_append_buf(buf, tld->name);
+ if (is_test) {
+ buf_append_str(buf, "test \"");
+ buf_append_buf(buf, tld->name);
+ buf_append_char(buf, '"');
+ } else {
+ buf_append_buf(buf, tld->name);
+ }
}
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) {
ZigFn *fn_entry = allocate<ZigFn>(1);
+ fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota;
+
fn_entry->codegen = g;
fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc;
- fn_entry->analyzed_executable.backward_branch_quota = default_backward_branch_quota;
+ fn_entry->analyzed_executable.backward_branch_quota = &fn_entry->prealloc_backward_branch_quota;
fn_entry->analyzed_executable.fn_entry = fn_entry;
fn_entry->ir_executable.fn_entry = fn_entry;
fn_entry->fn_inline = inline_value;
@@ -2726,7 +2749,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
if (fn_proto->is_export || is_extern) {
buf_init_from_buf(&fn_table_entry->symbol_name, tld_fn->base.name);
} else {
- get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base);
+ get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, false);
}
if (fn_proto->is_export) {
@@ -2787,7 +2810,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
} else if (source_node->type == NodeTypeTestDecl) {
ZigFn *fn_table_entry = create_fn_raw(g, FnInlineAuto);
- get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base);
+ get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, true);
tld_fn->fn_entry = fn_table_entry;
@@ -3722,7 +3745,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
}
if (g->verbose_ir) {
fprintf(stderr, "\n");
- ast_render(g, stderr, fn_table_entry->body_node, 4);
+ ast_render(stderr, fn_table_entry->body_node, 4);
fprintf(stderr, "\n{ // (IR)\n");
ir_print(g, stderr, &fn_table_entry->ir_executable, 4);
fprintf(stderr, "}\n");
@@ -5155,11 +5178,10 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {
TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);
assert(field != nullptr);
- if (type_has_bits(field->type_entry)) {
- zig_panic("TODO const expr analyze union field value for equality");
- } else {
+ if (!type_has_bits(field->type_entry))
return true;
- }
+ assert(find_union_field_by_tag(a->type, &union2->tag) != nullptr);
+ return const_values_equal(g, union1->payload, union2->payload);
}
return false;
}
@@ -6070,7 +6092,7 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents) {
if (g->enable_cache) {
return cache_add_file_fetch(&g->cache_hash, resolved_path, contents);
} else {
- return os_fetch_file_path(resolved_path, contents, false);
+ return os_fetch_file_path(resolved_path, contents);
}
}
@@ -7222,3 +7244,16 @@ ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type) {
assertNoError(type_resolve(g, type, ResolveStatusLLVMFull));
return type->llvm_di_type;
}
+
+void src_assert(bool ok, AstNode *source_node) {
+ if (ok) return;
+ if (source_node == nullptr) {
+ fprintf(stderr, "when analyzing (unknown source location): ");
+ } else {
+ fprintf(stderr, "when analyzing %s:%u:%u: ",
+ buf_ptr(source_node->owner->data.structure.root_struct->path),
+ (unsigned)source_node->line + 1, (unsigned)source_node->column + 1);
+ }
+ const char *msg = "assertion failed";
+ stage2_panic(msg, strlen(msg));
+}
diff --git a/src/analyze.hpp b/src/analyze.hpp
index a3246fdf4d..d55733482f 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -247,4 +247,8 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type);
ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);
+void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c);
+
+void src_assert(bool ok, AstNode *source_node);
+
#endif
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 16f2aafa78..95ae216f70 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -296,7 +296,6 @@ void ast_print(FILE *f, AstNode *node, int indent) {
struct AstRender {
- CodeGen *codegen;
int indent;
int indent_size;
FILE *f;
@@ -633,7 +632,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
if (is_printable(c)) {
fprintf(ar->f, "'%c'", c);
} else {
- fprintf(ar->f, "'\\x%x'", (int)c);
+ fprintf(ar->f, "'\\x%02x'", (int)c);
}
break;
}
@@ -1170,9 +1169,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
}
-void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size) {
+void ast_render(FILE *f, AstNode *node, int indent_size) {
AstRender ar = {0};
- ar.codegen = codegen;
ar.f = f;
ar.indent_size = indent_size;
ar.indent = 0;
diff --git a/src/ast_render.hpp b/src/ast_render.hpp
index 1652156eee..cf70b04694 100644
--- a/src/ast_render.hpp
+++ b/src/ast_render.hpp
@@ -15,6 +15,6 @@
void ast_print(FILE *f, AstNode *node, int indent);
-void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
+void ast_render(FILE *f, AstNode *node, int indent_size);
#endif
diff --git a/src/bigint.cpp b/src/bigint.cpp
index d3178c35c6..da53a2b129 100644
--- a/src/bigint.cpp
+++ b/src/bigint.cpp
@@ -1395,7 +1395,7 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {
uint64_t shift_amt = bigint_as_unsigned(op2);
if (op1->digit_count == 1) {
- dest->data.digit = op1_digits[0] >> shift_amt;
+ dest->data.digit = (shift_amt < 64) ? op1_digits[0] >> shift_amt : 0;
dest->digit_count = 1;
dest->is_negative = op1->is_negative;
bigint_normalize(dest);
@@ -1410,12 +1410,19 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {
}
dest->digit_count = op1->digit_count - digit_shift_count;
- dest->data.digits = allocate<uint64_t>(dest->digit_count);
+ uint64_t *digits;
+ if (dest->digit_count == 1) {
+ digits = &dest->data.digit;
+ } else {
+ digits = allocate<uint64_t>(dest->digit_count);
+ dest->data.digits = digits;
+ }
+
uint64_t carry = 0;
for (size_t op_digit_index = op1->digit_count - 1;;) {
uint64_t digit = op1_digits[op_digit_index];
size_t dest_digit_index = op_digit_index - digit_shift_count;
- dest->data.digits[dest_digit_index] = carry | (digit >> leftover_shift_count);
+ digits[dest_digit_index] = carry | (digit >> leftover_shift_count);
carry = digit << (64 - leftover_shift_count);
if (dest_digit_index == 0) { break; }
diff --git a/src/buffer.hpp b/src/buffer.hpp
index 789abea3e9..082d584e2c 100644
--- a/src/buffer.hpp
+++ b/src/buffer.hpp
@@ -10,7 +10,6 @@
#include "list.hpp"
-#include <assert.h>
#include <stdint.h>
#include <ctype.h>
#include <stdarg.h>
diff --git a/src/c_tokenizer.cpp b/src/c_tokenizer.cpp
index 40ae8ceafe..55fde19003 100644
--- a/src/c_tokenizer.cpp
+++ b/src/c_tokenizer.cpp
@@ -124,6 +124,8 @@ static void begin_token(CTokenize *ctok, CTokId id) {
case CTokIdAsterisk:
case CTokIdBang:
case CTokIdTilde:
+ case CTokIdShl:
+ case CTokIdLt:
break;
}
}
@@ -223,6 +225,10 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
begin_token(ctok, CTokIdDot);
end_token(ctok);
break;
+ case '<':
+ begin_token(ctok, CTokIdLt);
+ ctok->state = CTokStateGotLt;
+ break;
case '(':
begin_token(ctok, CTokIdLParen);
end_token(ctok);
@@ -251,6 +257,19 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
return mark_error(ctok);
}
break;
+ case CTokStateGotLt:
+ switch (*c) {
+ case '<':
+ ctok->cur_tok->id = CTokIdShl;
+ end_token(ctok);
+ ctok->state = CTokStateStart;
+ break;
+ default:
+ end_token(ctok);
+ ctok->state = CTokStateStart;
+ continue;
+ }
+ break;
case CTokStateFloat:
switch (*c) {
case '.':
@@ -791,6 +810,7 @@ found_end_of_macro:
case CTokStateNumLitIntSuffixL:
case CTokStateNumLitIntSuffixUL:
case CTokStateNumLitIntSuffixLL:
+ case CTokStateGotLt:
end_token(ctok);
break;
case CTokStateFloat:
diff --git a/src/c_tokenizer.hpp b/src/c_tokenizer.hpp
index d7c9e53bcf..eaca09098f 100644
--- a/src/c_tokenizer.hpp
+++ b/src/c_tokenizer.hpp
@@ -25,6 +25,8 @@ enum CTokId {
CTokIdAsterisk,
CTokIdBang,
CTokIdTilde,
+ CTokIdShl,
+ CTokIdLt,
};
enum CNumLitSuffix {
@@ -78,6 +80,7 @@ enum CTokState {
CTokStateNumLitIntSuffixL,
CTokStateNumLitIntSuffixLL,
CTokStateNumLitIntSuffixUL,
+ CTokStateGotLt,
};
struct CTokenize {
diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp
index 1f25a9982e..2a0810eced 100644
--- a/src/cache_hash.cpp
+++ b/src/cache_hash.cpp
@@ -256,10 +256,10 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents
}
if ((err = hash_file(chf->bin_digest, this_file, contents))) {
- os_file_close(this_file);
+ os_file_close(&this_file);
return err;
}
- os_file_close(this_file);
+ os_file_close(&this_file);
blake2b_update(&ch->blake, chf->bin_digest, 48);
@@ -300,7 +300,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
Buf line_buf = BUF_INIT;
buf_resize(&line_buf, 512);
if ((err = os_file_read_all(ch->manifest_file, &line_buf))) {
- os_file_close(ch->manifest_file);
+ os_file_close(&ch->manifest_file);
return err;
}
@@ -389,14 +389,14 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
OsFileAttr actual_attr;
if ((err = os_file_open_r(chf->path, &this_file, &actual_attr))) {
fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));
- os_file_close(ch->manifest_file);
+ os_file_close(&ch->manifest_file);
return ErrorCacheUnavailable;
}
if (chf->attr.mtime.sec == actual_attr.mtime.sec &&
chf->attr.mtime.nsec == actual_attr.mtime.nsec &&
chf->attr.inode == actual_attr.inode)
{
- os_file_close(this_file);
+ os_file_close(&this_file);
} else {
// we have to recompute the digest.
// later we'll rewrite the manifest with the new mtime/digest values
@@ -411,11 +411,11 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
uint8_t actual_digest[48];
if ((err = hash_file(actual_digest, this_file, nullptr))) {
- os_file_close(this_file);
- os_file_close(ch->manifest_file);
+ os_file_close(&this_file);
+ os_file_close(&ch->manifest_file);
return err;
}
- os_file_close(this_file);
+ os_file_close(&this_file);
if (memcmp(chf->bin_digest, actual_digest, 48) != 0) {
memcpy(chf->bin_digest, actual_digest, 48);
// keep going until we have the input file digests
@@ -433,12 +433,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
CacheHashFile *chf = &ch->files.at(file_i);
if ((err = populate_file_hash(ch, chf, nullptr))) {
fprintf(stderr, "Unable to hash %s: %s\n", buf_ptr(chf->path), err_str(err));
- os_file_close(ch->manifest_file);
+ os_file_close(&ch->manifest_file);
return ErrorCacheUnavailable;
}
}
- if (return_code != ErrorNone) {
- os_file_close(ch->manifest_file);
+ if (return_code != ErrorNone && return_code != ErrorInvalidFormat) {
+ os_file_close(&ch->manifest_file);
}
return return_code;
}
@@ -453,7 +453,7 @@ Error cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents) {
CacheHashFile *chf = ch->files.add_one();
chf->path = resolved_path;
if ((err = populate_file_hash(ch, chf, contents))) {
- os_file_close(ch->manifest_file);
+ os_file_close(&ch->manifest_file);
return err;
}
@@ -469,7 +469,7 @@ Error cache_add_file(CacheHash *ch, Buf *path) {
Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {
Error err;
Buf *contents = buf_alloc();
- if ((err = os_fetch_file_path(dep_file_path, contents, false))) {
+ if ((err = os_fetch_file_path(dep_file_path, contents))) {
if (verbose) {
fprintf(stderr, "unable to read .d file: %s\n", err_str(err));
}
@@ -586,6 +586,6 @@ void cache_release(CacheHash *ch) {
}
}
- os_file_close(ch->manifest_file);
+ os_file_close(&ch->manifest_file);
}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 568344fc09..d21ada1b23 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -19,6 +19,7 @@
#include "target.hpp"
#include "util.hpp"
#include "zig_llvm.h"
+#include "userland.h"
#include <stdio.h>
#include <errno.h>
@@ -92,7 +93,7 @@ static const char *symbols_that_llvm_depends_on[] = {
};
CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
- OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir,
+ OutType out_type, BuildMode build_mode, Buf *override_lib_dir, Buf *override_std_dir,
ZigLibCInstallation *libc, Buf *cache_dir)
{
CodeGen *g = allocate<CodeGen>(1);
@@ -100,19 +101,24 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
codegen_add_time_event(g, "Initialize");
g->libc = libc;
- g->zig_lib_dir = zig_lib_dir;
g->zig_target = target;
g->cache_dir = cache_dir;
+ if (override_lib_dir == nullptr) {
+ g->zig_lib_dir = get_zig_lib_dir();
+ } else {
+ g->zig_lib_dir = override_lib_dir;
+ }
+
if (override_std_dir == nullptr) {
g->zig_std_dir = buf_alloc();
- os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
+ os_path_join(g->zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
} else {
g->zig_std_dir = override_std_dir;
}
g->zig_c_headers_dir = buf_alloc();
- os_path_join(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir);
+ os_path_join(g->zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir);
g->build_mode = build_mode;
g->out_type = out_type;
@@ -393,6 +399,15 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
}
}
+static void add_probe_stack_attr(CodeGen *g, LLVMValueRef fn_val) {
+ // Windows already emits its own stack probes
+ if (!g->disable_stack_probing && g->zig_target->os != OsWindows &&
+ (g->zig_target->arch == ZigLLVM_x86 ||
+ g->zig_target->arch == ZigLLVM_x86_64)) {
+ addLLVMFnAttrStr(fn_val, "probe-stack", "__zig_probe_stack");
+ }
+}
+
static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {
switch (id) {
case GlobalLinkageIdInternal:
@@ -424,7 +439,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
}
static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
- if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) {
+ if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows && g->is_dynamic) {
LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
}
}
@@ -495,6 +510,14 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
auto entry = g->exported_symbol_names.maybe_get(symbol_name);
if (entry == nullptr) {
fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);
+
+ if (target_is_wasm(g->zig_target)) {
+ assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
+ AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto;
+ if (fn_proto-> is_extern && fn_proto->lib_name != nullptr ) {
+ addLLVMFnAttrStr(fn_table_entry->llvm_value, "wasm-import-module", buf_ptr(fn_proto->lib_name));
+ }
+ }
} else {
assert(entry->value->id == TldIdFn);
TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value);
@@ -573,6 +596,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");
addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");
}
+
+ add_probe_stack_attr(g, fn_table_entry->llvm_value);
}
} else {
maybe_import_dll(g, fn_table_entry->llvm_value, linkage);
@@ -983,10 +1008,19 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace
LLVMBuildUnreachable(g->builder);
}
+// TODO update most callsites to call gen_assertion instead of this
static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) {
gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr);
}
+static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstruction *source_instruction) {
+ if (ir_want_runtime_safety(g, source_instruction)) {
+ gen_safety_crash(g, msg_id);
+ } else {
+ LLVMBuildUnreachable(g->builder);
+ }
+}
+
static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
if (g->stacksave_fn_val)
return g->stacksave_fn_val;
@@ -1022,7 +1056,7 @@ static LLVMValueRef get_write_register_fn_val(CodeGen *g) {
// !0 = !{!"sp\00"}
LLVMTypeRef param_types[] = {
- LLVMMetadataTypeInContext(LLVMGetGlobalContext()),
+ LLVMMetadataTypeInContext(LLVMGetGlobalContext()),
LLVMIntType(g->pointer_size_bytes * 8),
};
@@ -1541,11 +1575,19 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_array, offset_ptr_indices, 2);
Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false);
- LLVMTypeRef arg_types[] = {
- get_llvm_type(g, g->ptr_to_stack_trace_type),
- get_llvm_type(g, g->err_tag_type),
- };
- LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
+ LLVMTypeRef fn_type_ref;
+ if (g->have_err_ret_tracing) {
+ LLVMTypeRef arg_types[] = {
+ get_llvm_type(g, g->ptr_to_stack_trace_type),
+ get_llvm_type(g, g->err_tag_type),
+ };
+ fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
+ } else {
+ LLVMTypeRef arg_types[] = {
+ get_llvm_type(g, g->err_tag_type),
+ };
+ fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);
+ }
LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);
addLLVMFnAttr(fn_val, "noreturn");
addLLVMFnAttr(fn_val, "cold");
@@ -1567,7 +1609,15 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
LLVMPositionBuilderAtEnd(g->builder, entry_block);
ZigLLVMClearCurrentDebugLocation(g->builder);
- LLVMValueRef err_val = LLVMGetParam(fn_val, 1);
+ LLVMValueRef err_ret_trace_arg;
+ LLVMValueRef err_val;
+ if (g->have_err_ret_tracing) {
+ err_ret_trace_arg = LLVMGetParam(fn_val, 0);
+ err_val = LLVMGetParam(fn_val, 1);
+ } else {
+ err_ret_trace_arg = nullptr;
+ err_val = LLVMGetParam(fn_val, 0);
+ }
LLVMValueRef err_table_indices[] = {
LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
@@ -1589,7 +1639,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
LLVMValueRef global_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, global_slice, slice_len_index, "");
gen_store(g, full_buf_len, global_slice_len_field_ptr, u8_ptr_type);
- gen_panic(g, global_slice, LLVMGetParam(fn_val, 0));
+ gen_panic(g, global_slice, err_ret_trace_arg);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
@@ -1625,17 +1675,26 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) {
static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {
LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);
- LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);
- if (err_ret_trace_val == nullptr) {
- ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
- err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type));
+ LLVMValueRef call_instruction;
+ if (g->have_err_ret_tracing) {
+ LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);
+ if (err_ret_trace_val == nullptr) {
+ ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
+ err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type));
+ }
+ LLVMValueRef args[] = {
+ err_ret_trace_val,
+ err_val,
+ };
+ call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2,
+ get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
+ } else {
+ LLVMValueRef args[] = {
+ err_val,
+ };
+ call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 1,
+ get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
}
- LLVMValueRef args[] = {
- err_ret_trace_val,
- err_val,
- };
- LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2, get_llvm_cc(g, CallingConventionUnspecified),
- ZigLLVM_FnInlineAuto, "");
LLVMSetTailCall(call_instruction, true);
LLVMBuildUnreachable(g->builder);
}
@@ -3452,6 +3511,15 @@ static bool want_valgrind_support(CodeGen *g) {
zig_unreachable();
}
+static void gen_valgrind_undef(CodeGen *g, LLVMValueRef dest_ptr, LLVMValueRef byte_count) {
+ static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
+ ZigType *usize = g->builtin_types.entry_usize;
+ LLVMValueRef zero = LLVMConstInt(usize->llvm_type, 0, false);
+ LLVMValueRef req = LLVMConstInt(usize->llvm_type, VG_USERREQ__MAKE_MEM_UNDEFINED, false);
+ LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->llvm_type, "");
+ gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero);
+}
+
static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
assert(type_has_bits(value_type));
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, value_type));
@@ -3466,11 +3534,7 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_
ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
// then tell valgrind that the memory is undefined even though we just memset it
if (want_valgrind_support(g)) {
- static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
- LLVMValueRef zero = LLVMConstInt(usize->llvm_type, 0, false);
- LLVMValueRef req = LLVMConstInt(usize->llvm_type, VG_USERREQ__MAKE_MEM_UNDEFINED, false);
- LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->llvm_type, "");
- gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero);
+ gen_valgrind_undef(g, dest_ptr, byte_count);
}
}
@@ -3480,14 +3544,14 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
if (!type_has_bits(ptr_type))
return nullptr;
- bool have_init_expr = !value_is_all_undef(&instruction->value->value);
+ bool have_init_expr = !value_is_all_undef(&instruction->value->value);
if (have_init_expr) {
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
LLVMValueRef value = ir_llvm_value(g, instruction->value);
gen_assign_raw(g, ptr, ptr_type, value);
} else if (ir_want_runtime_safety(g, &instruction->base)) {
gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
- ir_llvm_value(g, instruction->ptr));
+ ir_llvm_value(g, instruction->ptr));
}
return nullptr;
}
@@ -3690,7 +3754,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
}
FnWalk fn_walk = {};
fn_walk.id = FnWalkIdCall;
- fn_walk.data.call.inst = instruction;
+ fn_walk.data.call.inst = instruction;
fn_walk.data.call.is_var_args = is_var_args;
fn_walk.data.call.gen_param_values = &gen_param_values;
walk_function_params(g, fn_type, &fn_walk);
@@ -3710,7 +3774,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
LLVMCallConv llvm_cc = get_llvm_cc(g, cc);
LLVMValueRef result;
-
+
if (instruction->new_stack == nullptr) {
result = ZigLLVMBuildCall(g->builder, fn_val,
gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");
@@ -3968,19 +4032,19 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
}
static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueRef maybe_handle) {
- assert(maybe_type->id == ZigTypeIdOptional);
+ assert(maybe_type->id == ZigTypeIdOptional ||
+ (maybe_type->id == ZigTypeIdPointer && maybe_type->data.pointer.allow_zero));
+
ZigType *child_type = maybe_type->data.maybe.child_type;
- if (!type_has_bits(child_type)) {
+ if (!type_has_bits(child_type))
return maybe_handle;
- } else {
- bool is_scalar = !handle_is_ptr(maybe_type);
- if (is_scalar) {
- return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), "");
- } else {
- LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
- return gen_load_untyped(g, maybe_field_ptr, 0, false, "");
- }
- }
+
+ bool is_scalar = !handle_is_ptr(maybe_type);
+ if (is_scalar)
+ return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), "");
+
+ LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
+ return gen_load_untyped(g, maybe_field_ptr, 0, false, "");
}
static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable,
@@ -4001,8 +4065,8 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec
if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
- LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);
LLVMPositionBuilderAtEnd(g->builder, fail_block);
@@ -4190,7 +4254,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
LLVMTypeRef tag_int_llvm_type = get_llvm_type(g, tag_int_type);
LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0),
&tag_int_llvm_type, 1, false);
-
+
Buf *fn_name = get_mangled_name(g, buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name)), false);
LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
@@ -4490,17 +4554,27 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrI
static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrInstructionMemset *instruction) {
LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr);
- LLVMValueRef char_val = ir_llvm_value(g, instruction->byte);
LLVMValueRef len_val = ir_llvm_value(g, instruction->count);
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
-
LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
ZigType *ptr_type = instruction->dest_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
- ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, char_val, len_val, get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile);
+ bool val_is_undef = value_is_all_undef(&instruction->byte->value);
+ LLVMValueRef fill_char;
+ if (val_is_undef) {
+ fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
+ } else {
+ fill_char = ir_llvm_value(g, instruction->byte);
+ }
+ ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, fill_char, len_val, get_ptr_align(g, ptr_type),
+ ptr_type->data.pointer.is_volatile);
+
+ if (val_is_undef && want_valgrind_support(g)) {
+ gen_valgrind_undef(g, dest_ptr_casted, len_val);
+ }
return nullptr;
}
@@ -5422,6 +5496,31 @@ static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,
return nullptr;
}
+static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutable *executable,
+ IrInstructionAssertNonNull *instruction)
+{
+ LLVMValueRef target = ir_llvm_value(g, instruction->target);
+ ZigType *target_type = instruction->target->value.type;
+
+ if (target_type->id == ZigTypeIdPointer) {
+ assert(target_type->data.pointer.ptr_len == PtrLenC);
+ LLVMValueRef non_null_bit = LLVMBuildICmp(g->builder, LLVMIntNE, target,
+ LLVMConstNull(get_llvm_type(g, target_type)), "");
+
+ LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "AssertNonNullFail");
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "AssertNonNullOk");
+ LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);
+
+ LLVMPositionBuilderAtEnd(g->builder, fail_block);
+ gen_assertion(g, PanicMsgIdUnwrapOptionalFail, &instruction->base);
+
+ LLVMPositionBuilderAtEnd(g->builder, ok_block);
+ } else {
+ zig_unreachable();
+ }
+ return nullptr;
+}
+
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
AstNode *source_node = instruction->source_node;
Scope *scope = instruction->scope;
@@ -5676,6 +5775,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
case IrInstructionIdAssertZero:
return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction);
+ case IrInstructionIdAssertNonNull:
+ return ir_render_assert_non_null(g, executable, (IrInstructionAssertNonNull *)instruction);
case IrInstructionIdResizeSlice:
return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);
}
@@ -6585,7 +6686,7 @@ static void validate_inline_fns(CodeGen *g) {
}
static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
- if (var->is_thread_local && !g->is_single_threaded) {
+ if (var->is_thread_local && (!g->is_single_threaded || var->linkage != VarLinkageInternal)) {
LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
}
}
@@ -6905,7 +7006,7 @@ static void do_code_gen(CodeGen *g) {
ir_render(g, fn_table_entry);
}
-
+
assert(!g->errors.length);
if (buf_len(&g->global_asm) != 0) {
@@ -6942,6 +7043,11 @@ static void zig_llvm_emit_output(CodeGen *g) {
}
validate_inline_fns(g);
g->link_objects.append(output_path);
+ if (g->bundle_compiler_rt && (g->out_type == OutTypeObj ||
+ (g->out_type == OutTypeLib && !g->is_dynamic)))
+ {
+ zig_link_add_compiler_rt(g);
+ }
break;
case EmitFileTypeAssembly:
@@ -7337,9 +7443,26 @@ static bool detect_pic(CodeGen *g) {
zig_unreachable();
}
+static bool detect_single_threaded(CodeGen *g) {
+ if (g->want_single_threaded)
+ return true;
+ if (target_is_single_threaded(g->zig_target)) {
+ return true;
+ }
+ return false;
+}
+
+static bool detect_err_ret_tracing(CodeGen *g) {
+ return !target_is_wasm(g->zig_target) &&
+ g->build_mode != BuildModeFastRelease &&
+ g->build_mode != BuildModeSmallRelease;
+}
+
Buf *codegen_generate_builtin_source(CodeGen *g) {
g->have_dynamic_link = detect_dynamic_link(g);
g->have_pic = detect_pic(g);
+ g->is_single_threaded = detect_single_threaded(g);
+ g->have_err_ret_tracing = detect_err_ret_tracing(g);
Buf *contents = buf_alloc();
@@ -7696,7 +7819,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
assert(ContainerLayoutAuto == 0);
assert(ContainerLayoutExtern == 1);
assert(ContainerLayoutPacked == 2);
-
+
assert(CallingConventionUnspecified == 0);
assert(CallingConventionC == 1);
assert(CallingConventionCold == 2);
@@ -7814,7 +7937,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
Buf *contents;
if (hit) {
contents = buf_alloc();
- if ((err = os_fetch_file_path(builtin_zig_path, contents, false))) {
+ if ((err = os_fetch_file_path(builtin_zig_path, contents))) {
fprintf(stderr, "Unable to open '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err));
exit(1);
}
@@ -7844,6 +7967,12 @@ static void init(CodeGen *g) {
g->have_dynamic_link = detect_dynamic_link(g);
g->have_pic = detect_pic(g);
+ g->is_single_threaded = detect_single_threaded(g);
+ g->have_err_ret_tracing = detect_err_ret_tracing(g);
+
+ if (target_is_single_threaded(g->zig_target)) {
+ g->is_single_threaded = true;
+ }
if (g->is_test_build) {
g->subsystem = TargetSubsystemConsole;
@@ -7953,8 +8082,6 @@ static void init(CodeGen *g) {
}
}
- g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease && g->build_mode != BuildModeSmallRelease;
-
define_builtin_fns(g);
Error err;
if ((err = define_builtin_compile_vars(g))) {
@@ -8093,7 +8220,126 @@ static void detect_libc(CodeGen *g) {
}
}
-AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {
+// does not add the "cc" arg
+void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c) {
+ if (translate_c) {
+ args.append("-x");
+ args.append("c");
+ }
+
+ if (out_dep_path != nullptr) {
+ args.append("-MD");
+ args.append("-MV");
+ args.append("-MF");
+ args.append(out_dep_path);
+ }
+
+ args.append("-nostdinc");
+ args.append("-fno-spell-checking");
+
+ if (translate_c) {
+ // this gives us access to preprocessing entities, presumably at
+ // the cost of performance
+ args.append("-Xclang");
+ args.append("-detailed-preprocessing-record");
+ } else {
+ switch (g->err_color) {
+ case ErrColorAuto:
+ break;
+ case ErrColorOff:
+ args.append("-fno-color-diagnostics");
+ args.append("-fno-caret-diagnostics");
+ break;
+ case ErrColorOn:
+ args.append("-fcolor-diagnostics");
+ args.append("-fcaret-diagnostics");
+ break;
+ }
+ }
+
+ args.append("-isystem");
+ args.append(buf_ptr(g->zig_c_headers_dir));
+
+ for (size_t i = 0; i < g->libc_include_dir_len; i += 1) {
+ Buf *include_dir = g->libc_include_dir_list[i];
+ args.append("-isystem");
+ args.append(buf_ptr(include_dir));
+ }
+
+ if (g->zig_target->is_native) {
+ args.append("-march=native");
+ } else {
+ args.append("-target");
+ args.append(buf_ptr(&g->triple_str));
+ }
+ if (g->zig_target->os == OsFreestanding) {
+ args.append("-ffreestanding");
+ }
+
+ if (!g->strip_debug_symbols) {
+ args.append("-g");
+ }
+
+ switch (g->build_mode) {
+ case BuildModeDebug:
+ // windows c runtime requires -D_DEBUG if using debug libraries
+ args.append("-D_DEBUG");
+
+ if (g->libc_link_lib != nullptr) {
+ args.append("-fstack-protector-strong");
+ args.append("--param");
+ args.append("ssp-buffer-size=4");
+ } else {
+ args.append("-fno-stack-protector");
+ }
+ args.append("-fno-omit-frame-pointer");
+ break;
+ case BuildModeSafeRelease:
+ // See the comment in the BuildModeFastRelease case for why we pass -O2 rather
+ // than -O3 here.
+ args.append("-O2");
+ if (g->libc_link_lib != nullptr) {
+ args.append("-D_FORTIFY_SOURCE=2");
+ args.append("-fstack-protector-strong");
+ args.append("--param");
+ args.append("ssp-buffer-size=4");
+ } else {
+ args.append("-fno-stack-protector");
+ }
+ args.append("-fomit-frame-pointer");
+ break;
+ case BuildModeFastRelease:
+ args.append("-DNDEBUG");
+ // Here we pass -O2 rather than -O3 because, although we do the equivalent of
+ // -O3 in Zig code, the justification for the difference here is that Zig
+ // has better detection and prevention of undefined behavior, so -O3 is safer for
+ // Zig code than it is for C code. Also, C programmers are used to their code
+ // running in -O2 and thus the -O3 path has been tested less.
+ args.append("-O2");
+ args.append("-fno-stack-protector");
+ args.append("-fomit-frame-pointer");
+ break;
+ case BuildModeSmallRelease:
+ args.append("-DNDEBUG");
+ args.append("-Os");
+ args.append("-fno-stack-protector");
+ args.append("-fomit-frame-pointer");
+ break;
+ }
+
+ if (target_supports_fpic(g->zig_target) && g->have_pic) {
+ args.append("-fPIC");
+ }
+
+ for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
+ args.append(g->clang_argv[arg_i]);
+ }
+
+
+}
+
+void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation) {
+ Error err;
Buf *src_basename = buf_alloc();
Buf *src_dirname = buf_alloc();
os_path_split(full_path, src_dirname, src_basename);
@@ -8105,13 +8351,47 @@ AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {
init(g);
- ZigList<ErrorMsg *> errors = {0};
+ Stage2TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ?
+ Stage2TranslateModeImport : Stage2TranslateModeTranslate;
+
+
+ ZigList<const char *> clang_argv = {0};
+ add_cc_args(g, clang_argv, nullptr, true);
+
+ clang_argv.append(buf_ptr(full_path));
+
+ if (g->verbose_cc) {
+ fprintf(stderr, "clang");
+ for (size_t i = 0; i < clang_argv.length; i += 1) {
+ fprintf(stderr, " %s", clang_argv.at(i));
+ }
+ fprintf(stderr, "\n");
+ }
+
+ clang_argv.append(nullptr); // to make the [start...end] argument work
+
+ const char *resources_path = buf_ptr(g->zig_c_headers_dir);
+ Stage2ErrorMsg *errors_ptr;
+ size_t errors_len;
+ Stage2Ast *ast;
AstNode *root_node;
- Error err = parse_h_file(&root_node, &errors, buf_ptr(full_path), g, nullptr);
- if (err == ErrorCCompileErrors && errors.length > 0) {
- for (size_t i = 0; i < errors.length; i += 1) {
- ErrorMsg *err_msg = errors.at(i);
+ if (use_userland_implementation) {
+ err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
+ &clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path);
+ } else {
+ err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(),
+ trans_mode, resources_path);
+ }
+
+ if (err == ErrorCCompileErrors && errors_len > 0) {
+ for (size_t i = 0; i < errors_len; i += 1) {
+ Stage2ErrorMsg *clang_err = &errors_ptr[i];
+ ErrorMsg *err_msg = err_msg_create_with_offset(
+ clang_err->filename_ptr ?
+ buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(),
+ clang_err->line, clang_err->column, clang_err->offset, clang_err->source,
+ buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len));
print_err_msg(err_msg, g->err_color);
}
exit(1);
@@ -8122,7 +8402,12 @@ AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {
exit(1);
}
- return root_node;
+
+ if (use_userland_implementation) {
+ stage2_render_ast(ast, out_file);
+ } else {
+ ast_render(out_file, root_node, 4);
+ }
}
static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) {
@@ -8233,7 +8518,7 @@ static void gen_root_source(CodeGen *g) {
Error err;
// No need for using the caching system for this file fetch because it is handled
// separately.
- if ((err = os_fetch_file_path(resolved_path, source_code, true))) {
+ if ((err = os_fetch_file_path(resolved_path, source_code))) {
fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(resolved_path), err_str(err));
exit(1);
}
@@ -8308,7 +8593,7 @@ static void gen_global_asm(CodeGen *g) {
Buf *asm_file = g->assembly_files.at(i);
// No need to use the caching system for these fetches because they
// are handled separately.
- if ((err = os_fetch_file_path(asm_file, &contents, false))) {
+ if ((err = os_fetch_file_path(asm_file, &contents))) {
zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err));
}
buf_append_buf(&g->global_asm, &contents);
@@ -8441,90 +8726,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
args.append("cc");
Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));
- args.append("-MD");
- args.append("-MV");
- args.append("-MF");
- args.append(buf_ptr(out_dep_path));
-
- args.append("-nostdinc");
- args.append("-fno-spell-checking");
-
- switch (g->err_color) {
- case ErrColorAuto:
- break;
- case ErrColorOff:
- args.append("-fno-color-diagnostics");
- args.append("-fno-caret-diagnostics");
- break;
- case ErrColorOn:
- args.append("-fcolor-diagnostics");
- args.append("-fcaret-diagnostics");
- break;
- }
-
- args.append("-isystem");
- args.append(buf_ptr(g->zig_c_headers_dir));
-
- for (size_t i = 0; i < g->libc_include_dir_len; i += 1) {
- Buf *include_dir = g->libc_include_dir_list[i];
- args.append("-isystem");
- args.append(buf_ptr(include_dir));
- }
-
- if (g->zig_target->is_native) {
- args.append("-march=native");
- } else {
- args.append("-target");
- args.append(buf_ptr(&g->triple_str));
- }
-
- if (!g->strip_debug_symbols) {
- args.append("-g");
- }
-
- switch (g->build_mode) {
- case BuildModeDebug:
- if (g->libc_link_lib != nullptr) {
- args.append("-fstack-protector-strong");
- args.append("--param");
- args.append("ssp-buffer-size=4");
- } else {
- args.append("-fno-stack-protector");
- }
- args.append("-fno-omit-frame-pointer");
- break;
- case BuildModeSafeRelease:
- // See the comment in the BuildModeFastRelease case for why we pass -O2 rather
- // than -O3 here.
- args.append("-O2");
- if (g->libc_link_lib != nullptr) {
- args.append("-D_FORTIFY_SOURCE=2");
- args.append("-fstack-protector-strong");
- args.append("--param");
- args.append("ssp-buffer-size=4");
- } else {
- args.append("-fno-stack-protector");
- }
- args.append("-fomit-frame-pointer");
- break;
- case BuildModeFastRelease:
- args.append("-DNDEBUG");
- // Here we pass -O2 rather than -O3 because, although we do the equivalent of
- // -O3 in Zig code, the justification for the difference here is that Zig
- // has better detection and prevention of undefined behavior, so -O3 is safer for
- // Zig code than it is for C code. Also, C programmers are used to their code
- // running in -O2 and thus the -O3 path has been tested less.
- args.append("-O2");
- args.append("-fno-stack-protector");
- args.append("-fomit-frame-pointer");
- break;
- case BuildModeSmallRelease:
- args.append("-DNDEBUG");
- args.append("-Os");
- args.append("-fno-stack-protector");
- args.append("-fomit-frame-pointer");
- break;
- }
+ add_cc_args(g, args, buf_ptr(out_dep_path), false);
args.append("-o");
args.append(buf_ptr(out_obj_path));
@@ -8532,19 +8734,10 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
args.append("-c");
args.append(buf_ptr(c_source_file));
- if (target_supports_fpic(g->zig_target) && g->have_pic) {
- args.append("-fPIC");
- }
-
- for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
- args.append(g->clang_argv[arg_i]);
- }
-
for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {
args.append(c_file->args.at(arg_i));
}
-
if (g->verbose_cc) {
print_zig_cc_cmd("zig", &args);
}
@@ -9158,6 +9351,8 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_bool(ch, g->linker_rdynamic);
cache_bool(ch, g->each_lib_rpath);
cache_bool(ch, g->disable_gen_h);
+ cache_bool(ch, g->bundle_compiler_rt);
+ cache_bool(ch, g->disable_stack_probing);
cache_bool(ch, want_valgrind_support(g));
cache_bool(ch, g->have_pic);
cache_bool(ch, g->have_dynamic_link);
@@ -9268,6 +9463,8 @@ void codegen_build_and_link(CodeGen *g) {
g->have_dynamic_link = detect_dynamic_link(g);
g->have_pic = detect_pic(g);
+ g->is_single_threaded = detect_single_threaded(g);
+ g->have_err_ret_tracing = detect_err_ret_tracing(g);
detect_libc(g);
detect_dynamic_linker(g);
diff --git a/src/codegen.hpp b/src/codegen.hpp
index 3befca2de5..47c0097e4b 100644
--- a/src/codegen.hpp
+++ b/src/codegen.hpp
@@ -12,6 +12,7 @@
#include "errmsg.hpp"
#include "target.hpp"
#include "libc_installation.hpp"
+#include "userland.h"
#include <stdio.h>
@@ -43,6 +44,7 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc
void codegen_add_time_event(CodeGen *g, const char *name);
void codegen_print_timing_report(CodeGen *g, FILE *f);
void codegen_link(CodeGen *g);
+void zig_link_add_compiler_rt(CodeGen *g);
void codegen_build_and_link(CodeGen *g);
ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path,
@@ -50,7 +52,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
void codegen_add_assembly(CodeGen *g, Buf *path);
void codegen_add_object(CodeGen *g, Buf *object_path);
-AstNode *codegen_translate_c(CodeGen *g, Buf *path);
+void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation);
Buf *codegen_generate_builtin_source(CodeGen *g);
diff --git a/src/compiler.cpp b/src/compiler.cpp
index af62173db7..8bfe87bfcd 100644
--- a/src/compiler.cpp
+++ b/src/compiler.cpp
@@ -179,24 +179,24 @@ Buf *get_zig_lib_dir(void) {
return &saved_lib_dir;
}
-Buf *get_zig_std_dir() {
+Buf *get_zig_std_dir(Buf *zig_lib_dir) {
if (saved_std_dir.list.length != 0) {
return &saved_std_dir;
}
buf_resize(&saved_std_dir, 0);
- os_path_join(get_zig_lib_dir(), buf_create_from_str("std"), &saved_std_dir);
+ os_path_join(zig_lib_dir, buf_create_from_str("std"), &saved_std_dir);
return &saved_std_dir;
}
-Buf *get_zig_special_dir() {
+Buf *get_zig_special_dir(Buf *zig_lib_dir) {
if (saved_special_dir.list.length != 0) {
return &saved_special_dir;
}
buf_resize(&saved_special_dir, 0);
- os_path_join(get_zig_std_dir(), buf_sprintf("special"), &saved_special_dir);
+ os_path_join(get_zig_std_dir(zig_lib_dir), buf_sprintf("special"), &saved_special_dir);
return &saved_special_dir;
}
diff --git a/src/compiler.hpp b/src/compiler.hpp
index f2788b9998..4d682ba2fa 100644
--- a/src/compiler.hpp
+++ b/src/compiler.hpp
@@ -16,7 +16,7 @@ Error get_compiler_id(Buf **result);
Buf *get_self_dynamic_linker_path(void);
Buf *get_zig_lib_dir(void);
-Buf *get_zig_special_dir(void);
-Buf *get_zig_std_dir(void);
+Buf *get_zig_special_dir(Buf *zig_lib_dir);
+Buf *get_zig_std_dir(Buf *zig_lib_dir);
#endif
diff --git a/src/error.cpp b/src/error.cpp
index 84b78aba1b..69676f9cf5 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -50,6 +50,10 @@ const char *err_str(Error err) {
case ErrorUnexpectedWriteFailure: return "unexpected write failure";
case ErrorUnexpectedSeekFailure: return "unexpected seek failure";
case ErrorUnexpectedFileTruncationFailure: return "unexpected file truncation failure";
+ case ErrorUnimplemented: return "unimplemented";
+ case ErrorOperationAborted: return "operation aborted";
+ case ErrorBrokenPipe: return "broken pipe";
+ case ErrorNoSpaceLeft: return "no space left";
}
return "(invalid error)";
}
diff --git a/src/error.hpp b/src/error.hpp
index d943703268..3ff36e1a5f 100644
--- a/src/error.hpp
+++ b/src/error.hpp
@@ -8,56 +8,10 @@
#ifndef ERROR_HPP
#define ERROR_HPP
-#include <assert.h>
-
-enum Error {
- ErrorNone,
- ErrorNoMem,
- ErrorInvalidFormat,
- ErrorSemanticAnalyzeFail,
- ErrorAccess,
- ErrorInterrupted,
- ErrorSystemResources,
- ErrorFileNotFound,
- ErrorFileSystem,
- ErrorFileTooBig,
- ErrorDivByZero,
- ErrorOverflow,
- ErrorPathAlreadyExists,
- ErrorUnexpected,
- ErrorExactDivRemainder,
- ErrorNegativeDenominator,
- ErrorShiftedOutOneBits,
- ErrorCCompileErrors,
- ErrorEndOfFile,
- ErrorIsDir,
- ErrorNotDir,
- ErrorUnsupportedOperatingSystem,
- ErrorSharingViolation,
- ErrorPipeBusy,
- ErrorPrimitiveTypeNotFound,
- ErrorCacheUnavailable,
- ErrorPathTooLong,
- ErrorCCompilerCannotFindFile,
- ErrorReadingDepFile,
- ErrorInvalidDepFile,
- ErrorMissingArchitecture,
- ErrorMissingOperatingSystem,
- ErrorUnknownArchitecture,
- ErrorUnknownOperatingSystem,
- ErrorUnknownABI,
- ErrorInvalidFilename,
- ErrorDiskQuota,
- ErrorDiskSpace,
- ErrorUnexpectedWriteFailure,
- ErrorUnexpectedSeekFailure,
- ErrorUnexpectedFileTruncationFailure,
-};
+#include "userland.h"
const char *err_str(Error err);
-static inline void assertNoError(Error err) {
- assert(err == ErrorNone);
-}
+#define assertNoError(err) assert((err) == ErrorNone);
#endif
diff --git a/src/ir.cpp b/src/ir.cpp
index c572e3c885..e89d30232e 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -188,6 +188,19 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
assert(get_src_ptr_type(const_val->type) != nullptr);
assert(const_val->special == ConstValSpecialStatic);
ConstExprValue *result;
+
+ switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {
+ case OnePossibleValueInvalid:
+ zig_unreachable();
+ case OnePossibleValueYes:
+ result = create_const_vals(1);
+ result->type = const_val->type->data.pointer.child_type;
+ result->special = ConstValSpecialStatic;
+ return result;
+ case OnePossibleValueNo:
+ break;
+ }
+
switch (const_val->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
zig_unreachable();
@@ -356,6 +369,18 @@ static void ir_ref_var(ZigVar *var) {
var->ref_count += 1;
}
+ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) {
+ ConstExprValue *result = ir_eval_const_value(ira->codegen, scope, node, ira->codegen->builtin_types.entry_type,
+ ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, nullptr,
+ node, nullptr, ira->new_irb.exec, nullptr);
+
+ if (type_is_invalid(result->type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ assert(result->special != ConstValSpecialRuntime);
+ return result->data.x_type;
+}
+
static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) {
IrBasicBlock *result = allocate<IrBasicBlock>(1);
result->scope = scope;
@@ -978,6 +1003,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertZero *) {
return IrInstructionIdAssertZero;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *) {
+ return IrInstructionIdAssertNonNull;
+}
+
template<typename T>
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@@ -3012,6 +3041,19 @@ static IrInstruction *ir_build_assert_zero(IrAnalyze *ira, IrInstruction *source
return &instruction->base;
}
+static IrInstruction *ir_build_assert_non_null(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *target)
+{
+ IrInstructionAssertNonNull *instruction = ir_build_instruction<IrInstructionAssertNonNull>(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ira->codegen->builtin_types.entry_void;
+ instruction->target = target;
+
+ ir_ref_instruction(target, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
results[ReturnKindError] = 0;
@@ -5391,10 +5433,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
add_node_error(irb->codegen, variable_declaration->section_expr,
buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol)));
}
- if (variable_declaration->threadlocal_tok != nullptr) {
- add_token_error(irb->codegen, node->owner, variable_declaration->threadlocal_tok,
- buf_sprintf("function-local variable '%s' cannot be threadlocal", buf_ptr(variable_declaration->symbol)));
- }
+
+ // Parser should ensure that this never happens
+ assert(variable_declaration->threadlocal_tok == nullptr);
// Temporarily set the name of the IrExecutable to the VariableDeclaration
// so that the struct or enum from the init expression inherits the name.
@@ -5767,8 +5808,10 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
IrInstruction *body_result = ir_gen_node(irb, body_node, &loop_scope->base);
- if (!instr_is_unreachable(body_result))
+ if (!instr_is_unreachable(body_result)) {
+ ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result));
ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));
+ }
ir_set_cursor_at_end_and_append_block(irb, continue_block);
IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);
@@ -7891,6 +7934,11 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction,
return ir_add_error_node(ira, source_instruction->source_node, msg);
}
+static void ir_assert(bool ok, IrInstruction *source_instruction) {
+ if (ok) return;
+ src_assert(ok, source_instruction->source_node);
+}
+
// This function takes a comptime ptr and makes the child const value conform to the type
// described by the pointer.
static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
@@ -7943,7 +7991,7 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
return &codegen->invalid_instruction->value;
}
}
- return &codegen->invalid_instruction->value;
+ zig_unreachable();
}
static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {
@@ -8088,6 +8136,8 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) {
case 64:
dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);
break;
+ case 80:
+ zig_panic("TODO");
case 128:
dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);
break;
@@ -9904,6 +9954,7 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *t
static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {
ConstGlobalRefs *global_refs = dest->global_refs;
+ assert(!same_global_refs || src->global_refs != nullptr);
*dest = *src;
if (!same_global_refs) {
dest->global_refs = global_refs;
@@ -9949,6 +10000,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
case 64:
const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);
break;
+ case 80:
+ zig_panic("TODO");
case 128:
const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);
break;
@@ -9978,6 +10031,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
case 64:
const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);
break;
+ case 80:
+ zig_panic("TODO");
case 128:
const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);
break;
@@ -10170,6 +10225,7 @@ static void ir_finish_bb(IrAnalyze *ira) {
ira->instruction_index += 1;
}
+ size_t my_old_bb_index = ira->old_bb_index;
ira->old_bb_index += 1;
bool need_repeat = true;
@@ -10180,7 +10236,7 @@ static void ir_finish_bb(IrAnalyze *ira) {
ira->old_bb_index += 1;
continue;
}
- if (old_bb->other->instruction_list.length != 0) {
+ if (old_bb->other->instruction_list.length != 0 || ira->old_bb_index == my_old_bb_index) {
ira->old_bb_index += 1;
continue;
}
@@ -10205,16 +10261,18 @@ static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
static bool ir_emit_backward_branch(IrAnalyze *ira, IrInstruction *source_instruction) {
size_t *bbc = ira->new_irb.exec->backward_branch_count;
- size_t quota = ira->new_irb.exec->backward_branch_quota;
+ size_t *quota = ira->new_irb.exec->backward_branch_quota;
// If we're already over quota, we've already given an error message for this.
- if (*bbc > quota) {
+ if (*bbc > *quota) {
+ assert(ira->codegen->errors.length > 0);
return false;
}
*bbc += 1;
- if (*bbc > quota) {
- ir_add_error(ira, source_instruction, buf_sprintf("evaluation exceeded %" ZIG_PRI_usize " backwards branches", quota));
+ if (*bbc > *quota) {
+ ir_add_error(ira, source_instruction,
+ buf_sprintf("evaluation exceeded %" ZIG_PRI_usize " backwards branches", *quota));
return false;
}
return true;
@@ -10249,6 +10307,12 @@ static IrInstruction *ir_const_bool(IrAnalyze *ira, IrInstruction *source_instru
return result;
}
+static IrInstruction *ir_const_undef(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
+ IrInstruction *result = ir_const(ira, source_instruction, ty);
+ result->value.special = ConstValSpecialUndef;
+ return result;
+}
+
static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) {
return ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_void);
}
@@ -10295,7 +10359,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
}
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
- ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
+ ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
IrExecutable *parent_exec, AstNode *expected_type_source_node)
{
@@ -10317,7 +10381,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
if (codegen->verbose_ir) {
fprintf(stderr, "\nSource: ");
- ast_render(codegen, stderr, node, 4);
+ ast_render(stderr, node, 4);
fprintf(stderr, "\n{ // (IR)\n");
ir_print(codegen, stderr, ir_executable, 2);
fprintf(stderr, "}\n");
@@ -10562,19 +10626,34 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
assert(instr_is_comptime(value));
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
- assert(val);
+ assert(val != nullptr);
- IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);
- const_instruction->base.value.special = ConstValSpecialStatic;
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
+ result->value.special = ConstValSpecialStatic;
if (get_codegen_ptr_type(wanted_type) != nullptr) {
- const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull;
+ result->value.data.x_ptr.special = ConstPtrSpecialNull;
} else if (is_opt_err_set(wanted_type)) {
- const_instruction->base.value.data.x_err_set = nullptr;
+ result->value.data.x_err_set = nullptr;
} else {
- const_instruction->base.value.data.x_optional = nullptr;
+ result->value.data.x_optional = nullptr;
}
- const_instruction->base.value.type = wanted_type;
- return &const_instruction->base;
+ return result;
+}
+
+static IrInstruction *ir_analyze_null_to_c_pointer(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *value, ZigType *wanted_type)
+{
+ assert(wanted_type->id == ZigTypeIdPointer);
+ assert(wanted_type->data.pointer.ptr_len == PtrLenC);
+ assert(instr_is_comptime(value));
+
+ ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
+ assert(val != nullptr);
+
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
+ result->value.data.x_ptr.special = ConstPtrSpecialNull;
+ result->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
+ return result;
}
static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,
@@ -11576,6 +11655,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
}
+ // cast from null literal to C pointer
+ if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC &&
+ actual_type->id == ZigTypeIdNull)
+ {
+ return ir_analyze_null_to_c_pointer(ira, source_instr, value, wanted_type);
+ }
+
// cast from [N]T to E![]const T
if (wanted_type->id == ZigTypeIdErrorUnion &&
is_slice(wanted_type->data.error_union.payload_type) &&
@@ -12193,14 +12279,12 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
IrBinOp op_id = bin_op_instruction->op_id;
bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
- if (is_equality_cmp &&
+ if (is_equality_cmp && op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull) {
+ return ir_const_bool(ira, &bin_op_instruction->base, (op_id == IrBinOpCmpEq));
+ } else if (is_equality_cmp &&
((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdOptional) ||
- (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdOptional) ||
- (op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull)))
+ (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdOptional)))
{
- if (op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull) {
- return ir_const_bool(ira, &bin_op_instruction->base, (op_id == IrBinOpCmpEq));
- }
IrInstruction *maybe_op;
if (op1->value.type->id == ZigTypeIdNull) {
maybe_op = op2;
@@ -12230,9 +12314,48 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
} else {
return is_non_null;
}
+ } else if (is_equality_cmp &&
+ ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdPointer &&
+ op2->value.type->data.pointer.ptr_len == PtrLenC) ||
+ (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdPointer &&
+ op1->value.type->data.pointer.ptr_len == PtrLenC)))
+ {
+ IrInstruction *c_ptr_op;
+ if (op1->value.type->id == ZigTypeIdNull) {
+ c_ptr_op = op2;
+ } else if (op2->value.type->id == ZigTypeIdNull) {
+ c_ptr_op = op1;
+ } else {
+ zig_unreachable();
+ }
+ if (instr_is_comptime(c_ptr_op)) {
+ ConstExprValue *c_ptr_val = ir_resolve_const(ira, c_ptr_op, UndefOk);
+ if (!c_ptr_val)
+ return ira->codegen->invalid_instruction;
+ if (c_ptr_val->special == ConstValSpecialUndef)
+ return ir_const_undef(ira, &bin_op_instruction->base, ira->codegen->builtin_types.entry_bool);
+ bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull ||
+ (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
+ c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0);
+ bool bool_result = (op_id == IrBinOpCmpEq) ? is_null : !is_null;
+ return ir_const_bool(ira, &bin_op_instruction->base, bool_result);
+ }
+ IrInstruction *is_non_null = ir_build_test_nonnull(&ira->new_irb, bin_op_instruction->base.scope,
+ source_node, c_ptr_op);
+ is_non_null->value.type = ira->codegen->builtin_types.entry_bool;
+
+ if (op_id == IrBinOpCmpEq) {
+ IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope,
+ bin_op_instruction->base.source_node, is_non_null);
+ result->value.type = ira->codegen->builtin_types.entry_bool;
+ return result;
+ } else {
+ return is_non_null;
+ }
} else if (op1->value.type->id == ZigTypeIdNull || op2->value.type->id == ZigTypeIdNull) {
- ir_add_error_node(ira, source_node, buf_sprintf("only optionals (not '%s') can compare to null",
- buf_ptr(&(op1->value.type->id == ZigTypeIdNull ? op2->value.type->name : op1->value.type->name))));
+ ZigType *non_null_type = (op1->value.type->id == ZigTypeIdNull) ? op2->value.type : op1->value.type;
+ ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null",
+ buf_ptr(&non_null_type->name)));
return ira->codegen->invalid_instruction;
}
@@ -13828,11 +13951,12 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
zig_unreachable();
}
-static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry, ZigType *fn_type,
- IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst)
+static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry,
+ ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
+ IrInstruction *async_allocator_inst)
{
Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);
- assert(async_allocator_inst->value.type->id == ZigTypeIdPointer);
+ ir_assert(async_allocator_inst->value.type->id == ZigTypeIdPointer, &call_instruction->base);
ZigType *container_type = async_allocator_inst->value.type->data.pointer.child_type;
IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, realloc_field_name, &call_instruction->base,
async_allocator_inst, container_type);
@@ -13840,7 +13964,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c
return ira->codegen->invalid_instruction;
}
ZigType *ptr_to_realloc_fn_type = field_ptr_inst->value.type;
- assert(ptr_to_realloc_fn_type->id == ZigTypeIdPointer);
+ ir_assert(ptr_to_realloc_fn_type->id == ZigTypeIdPointer, &call_instruction->base);
ZigType *realloc_fn_type = ptr_to_realloc_fn_type->data.pointer.child_type;
if (realloc_fn_type->id != ZigTypeIdFn) {
@@ -13875,7 +13999,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
IrInstruction *casted_arg;
if (param_decl_node->data.param_decl.var_token == nullptr) {
AstNode *param_type_node = param_decl_node->data.param_decl.type;
- ZigType *param_type = analyze_type_expr(ira->codegen, *exec_scope, param_type_node);
+ ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node);
if (type_is_invalid(param_type))
return false;
@@ -13915,7 +14039,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
} else {
if (param_decl_node->data.param_decl.var_token == nullptr) {
AstNode *param_type_node = param_decl_node->data.param_decl.type;
- ZigType *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node);
+ ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node);
if (type_is_invalid(param_type))
return false;
@@ -14296,7 +14420,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
}
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
- ZigType *specified_return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node);
+ ZigType *specified_return_type = ir_analyze_type_expr(ira, exec_scope, return_type_node);
if (type_is_invalid(specified_return_type))
return ira->codegen->invalid_instruction;
ZigType *return_type;
@@ -14532,7 +14656,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
if (fn_proto_node->data.fn_proto.return_var_token == nullptr) {
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
- ZigType *specified_return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node);
+ ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node);
if (type_is_invalid(specified_return_type))
return ira->codegen->invalid_instruction;
if (fn_proto_node->data.fn_proto.auto_err_set) {
@@ -14559,7 +14683,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
if (call_instruction->is_async) {
AstNode *async_allocator_type_node = fn_proto_node->data.fn_proto.async_allocator_type;
if (async_allocator_type_node != nullptr) {
- ZigType *async_allocator_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, async_allocator_type_node);
+ ZigType *async_allocator_type = ir_analyze_type_expr(ira, impl_fn->child_scope, async_allocator_type_node);
if (type_is_invalid(async_allocator_type))
return ira->codegen->invalid_instruction;
inst_fn_type_id.async_allocator_type = async_allocator_type;
@@ -15822,7 +15946,7 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,
}
}
- if (!is_libc && !ira->codegen->have_pic && !ira->codegen->reported_bad_link_libc_error) {
+ if (!is_libc && !target_is_wasm(ira->codegen->zig_target) && !ira->codegen->have_pic && !ira->codegen->reported_bad_link_libc_error) {
ErrorMsg *msg = ir_add_error_node(ira, source_node,
buf_sprintf("dependency on dynamic library '%s' requires enabling Position Independent Code",
buf_ptr(lib_name)));
@@ -16696,16 +16820,16 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
case ZigTypeIdUnreachable:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdEnumLiteral:
case ZigTypeIdBoundFn:
- case ZigTypeIdMetaType:
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
- ir_add_error_node(ira, size_of_instruction->base.source_node,
+ ir_add_error_node(ira, type_value->source_node,
buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->invalid_instruction;
+ case ZigTypeIdMetaType:
+ case ZigTypeIdEnumLiteral:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdComptimeInt:
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdInt:
@@ -16732,11 +16856,30 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
ZigType *type_entry = value->value.type;
- if (type_entry->id == ZigTypeIdOptional) {
+ if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.allow_zero) {
if (instr_is_comptime(value)) {
- ConstExprValue *maybe_val = ir_resolve_const(ira, value, UndefBad);
- if (!maybe_val)
+ ConstExprValue *c_ptr_val = ir_resolve_const(ira, value, UndefOk);
+ if (c_ptr_val == nullptr)
+ return ira->codegen->invalid_instruction;
+ if (c_ptr_val->special == ConstValSpecialUndef)
+ return ir_const_undef(ira, source_inst, ira->codegen->builtin_types.entry_bool);
+ bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull ||
+ (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
+ c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0);
+ return ir_const_bool(ira, source_inst, !is_null);
+ }
+
+ IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,
+ source_inst->scope, source_inst->source_node, value);
+ result->value.type = ira->codegen->builtin_types.entry_bool;
+ return result;
+ } else if (type_entry->id == ZigTypeIdOptional) {
+ if (instr_is_comptime(value)) {
+ ConstExprValue *maybe_val = ir_resolve_const(ira, value, UndefOk);
+ if (maybe_val == nullptr)
return ira->codegen->invalid_instruction;
+ if (maybe_val->special == ConstValSpecialUndef)
+ return ir_const_undef(ira, source_inst, ira->codegen->builtin_types.entry_bool);
return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val));
}
@@ -16770,6 +16913,32 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
+ if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.ptr_len == PtrLenC) {
+ if (instr_is_comptime(base_ptr)) {
+ ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+ if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
+ ConstExprValue *c_ptr_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
+ if (c_ptr_val == nullptr)
+ return ira->codegen->invalid_instruction;
+ bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull ||
+ (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
+ c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0);
+ if (is_null) {
+ ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
+ return ira->codegen->invalid_instruction;
+ }
+ return base_ptr;
+ }
+ }
+ if (!safety_check_on)
+ return base_ptr;
+ IrInstruction *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr);
+ ir_build_assert_non_null(ira, source_instr, c_ptr_val);
+ return base_ptr;
+ }
+
if (type_entry->id != ZigTypeIdOptional) {
ir_add_error_node(ira, base_ptr->source_node,
buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
@@ -16784,11 +16953,11 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
if (!val)
return ira->codegen->invalid_instruction;
- ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
- if (maybe_val == nullptr)
- return ira->codegen->invalid_instruction;
-
if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
+ ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
+ if (maybe_val == nullptr)
+ return ira->codegen->invalid_instruction;
+
if (optional_value_is_null(maybe_val)) {
ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
return ira->codegen->invalid_instruction;
@@ -17435,6 +17604,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
ConstExprValue const_val = {};
const_val.special = ConstValSpecialStatic;
const_val.type = container_type;
+ // const_val.global_refs = allocate<ConstGlobalRefs>(1);
const_val.data.x_struct.fields = create_const_vals(actual_field_count);
for (size_t i = 0; i < instr_field_count; i += 1) {
IrInstructionContainerInitFieldsField *field = &fields[i];
@@ -17498,7 +17668,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
if (const_val.special == ConstValSpecialStatic) {
IrInstruction *result = ir_const(ira, instruction, nullptr);
ConstExprValue *out_val = &result->value;
- copy_const_val(out_val, &const_val, true);
+ copy_const_val(out_val, &const_val, false);
out_val->type = container_type;
for (size_t i = 0; i < instr_field_count; i += 1) {
@@ -17570,6 +17740,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
ConstExprValue const_val = {};
const_val.special = ConstValSpecialStatic;
const_val.type = fixed_size_array_type;
+ // const_val.global_refs = allocate<ConstGlobalRefs>(1);
const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
@@ -17606,8 +17777,6 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
if (const_val.special == ConstValSpecialStatic) {
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
ConstExprValue *out_val = &result->value;
- // Make sure to pass same_global_refs=false here in order not to
- // zero the global_refs field for `result` (#1608)
copy_const_val(out_val, &const_val, false);
result->value.type = fixed_size_array_type;
for (size_t i = 0; i < elem_count; i += 1) {
@@ -18961,8 +19130,8 @@ static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ir
if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))
return ira->codegen->invalid_instruction;
- if (new_quota > ira->new_irb.exec->backward_branch_quota) {
- ira->new_irb.exec->backward_branch_quota = new_quota;
+ if (new_quota > *ira->new_irb.exec->backward_branch_quota) {
+ *ira->new_irb.exec->backward_branch_quota = new_quota;
}
return ir_const_void(ira, &instruction->base);
@@ -19059,24 +19228,50 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
fprintf(stderr, "@cImport source: %s\n", buf_ptr(&tmp_c_file_path));
}
- ZigList<ErrorMsg *> errors = {0};
-
Buf *tmp_dep_file = buf_sprintf("%s.d", buf_ptr(&tmp_c_file_path));
+
+ ZigList<const char *> clang_argv = {0};
+
+ add_cc_args(ira->codegen, clang_argv, buf_ptr(tmp_dep_file), true);
+
+ clang_argv.append(buf_ptr(&tmp_c_file_path));
+
+ if (ira->codegen->verbose_cc) {
+ fprintf(stderr, "clang");
+ for (size_t i = 0; i < clang_argv.length; i += 1) {
+ fprintf(stderr, " %s", clang_argv.at(i));
+ }
+ fprintf(stderr, "\n");
+ }
+
+ clang_argv.append(nullptr); // to make the [start...end] argument work
+
AstNode *root_node;
- if ((err = parse_h_file(&root_node, &errors, buf_ptr(&tmp_c_file_path), ira->codegen, tmp_dep_file))) {
+ Stage2ErrorMsg *errors_ptr;
+ size_t errors_len;
+
+ const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir);
+
+ if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len,
+ &clang_argv.at(0), &clang_argv.last(), Stage2TranslateModeImport, resources_path)))
+ {
if (err != ErrorCCompileErrors) {
ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
return ira->codegen->invalid_instruction;
}
- assert(errors.length > 0);
ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));
if (ira->codegen->libc_link_lib == nullptr) {
add_error_note(ira->codegen, parent_err_msg, node,
buf_sprintf("libc headers not available; compilation does not link against libc"));
}
- for (size_t i = 0; i < errors.length; i += 1) {
- ErrorMsg *err_msg = errors.at(i);
+ for (size_t i = 0; i < errors_len; i += 1) {
+ Stage2ErrorMsg *clang_err = &errors_ptr[i];
+ ErrorMsg *err_msg = err_msg_create_with_offset(
+ clang_err->filename_ptr ?
+ buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(),
+ clang_err->line, clang_err->column, clang_err->offset, clang_err->source,
+ buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len));
err_msg_add_note(parent_err_msg, err_msg);
}
@@ -19106,7 +19301,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
buf_sprintf("C import failed: unable to open output file: %s", strerror(errno)));
return ira->codegen->invalid_instruction;
}
- ast_render(ira->codegen, out_file, root_node, 4);
+ ast_render(out_file, root_node, 4);
if (fclose(out_file) != 0) {
ir_add_error_node(ira, node,
buf_sprintf("C import failed: unable to write to output file: %s", strerror(errno)));
@@ -21026,18 +21221,24 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
- IrInstruction *start_value = range->start->child;
+ IrInstruction *start_value_uncasted = range->start->child;
+ if (type_is_invalid(start_value_uncasted->value.type))
+ return ira->codegen->invalid_instruction;
+ IrInstruction *start_value = ir_implicit_cast(ira, start_value_uncasted, switch_type);
if (type_is_invalid(start_value->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *end_value = range->end->child;
+ IrInstruction *end_value_uncasted = range->end->child;
+ if (type_is_invalid(end_value_uncasted->value.type))
+ return ira->codegen->invalid_instruction;
+ IrInstruction *end_value = ir_implicit_cast(ira, end_value_uncasted, switch_type);
if (type_is_invalid(end_value->value.type))
return ira->codegen->invalid_instruction;
- assert(start_value->value.type->id == ZigTypeIdErrorSet);
+ ir_assert(start_value->value.type->id == ZigTypeIdErrorSet, &instruction->base);
uint32_t start_index = start_value->value.data.x_err_set->value;
- assert(end_value->value.type->id == ZigTypeIdErrorSet);
+ ir_assert(end_value->value.type->id == ZigTypeIdErrorSet, &instruction->base);
uint32_t end_index = end_value->value.data.x_err_set->value;
if (start_index != end_index) {
@@ -21260,7 +21461,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
}
IrInstruction *result = ir_const(ira, target, result_type);
- copy_const_val(&result->value, val, false);
+ copy_const_val(&result->value, val, true);
result->value.type = result_type;
return result;
}
@@ -21330,7 +21531,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
}
IrInstruction *result = ir_const(ira, source_instr, dest_type);
- copy_const_val(&result->value, val, false);
+ copy_const_val(&result->value, val, true);
result->value.type = dest_type;
// Keep the bigger alignment, it can only help-
@@ -21562,7 +21763,7 @@ static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNod
static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
Error err;
- assert(val->special == ConstValSpecialStatic);
+ src_assert(val->special == ConstValSpecialStatic, source_node);
switch (val->type->id) {
case ZigTypeIdInvalid:
case ZigTypeIdMetaType:
@@ -21612,7 +21813,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
zig_panic("TODO buf_read_value_bytes enum packed");
case ContainerLayoutExtern: {
ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
- assert(tag_int_type->id == ZigTypeIdInt);
+ src_assert(tag_int_type->id == ZigTypeIdInt, source_node);
bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
codegen->is_big_endian, tag_int_type->data.integral.is_signed);
return ErrorNone;
@@ -21667,7 +21868,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false);
while (src_i < src_field_count) {
TypeStructField *field = &val->type->data.structure.fields[src_i];
- assert(field->gen_index != SIZE_MAX);
+ src_assert(field->gen_index != SIZE_MAX, source_node);
if (field->gen_index != gen_i)
break;
ConstExprValue *field_val = &val->data.x_struct.fields[src_i];
@@ -21743,10 +21944,10 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_
Error err;
ZigType *src_type = value->value.type;
- assert(get_codegen_ptr_type(src_type) == nullptr);
- assert(type_can_bit_cast(src_type));
- assert(get_codegen_ptr_type(dest_type) == nullptr);
- assert(type_can_bit_cast(dest_type));
+ ir_assert(get_codegen_ptr_type(src_type) == nullptr, source_instr);
+ ir_assert(type_can_bit_cast(src_type), source_instr);
+ ir_assert(get_codegen_ptr_type(dest_type) == nullptr, source_instr);
+ ir_assert(type_can_bit_cast(dest_type), source_instr);
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
return ira->codegen->invalid_instruction;
@@ -21836,8 +22037,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
ZigType *ptr_type)
{
- assert(get_src_ptr_type(ptr_type) != nullptr);
- assert(type_has_bits(ptr_type));
+ ir_assert(get_src_ptr_type(ptr_type) != nullptr, source_instr);
+ ir_assert(type_has_bits(ptr_type), source_instr);
IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
if (type_is_invalid(casted_int->value.type))
@@ -21936,7 +22137,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
case TldIdFn: {
TldFn *tld_fn = (TldFn *)tld;
ZigFn *fn_entry = tld_fn->fn_entry;
- assert(fn_entry->type_entry);
+ ir_assert(fn_entry->type_entry, &instruction->base);
if (tld_fn->extern_lib_name != nullptr) {
add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, instruction->base.source_node);
@@ -22134,7 +22335,7 @@ static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruct
ZigType *result_type = fn_type_id->param_info[arg_index].type;
if (result_type == nullptr) {
// Args are only unresolved if our function is generic.
- assert(fn_type->data.fn.is_generic);
+ ir_assert(fn_type->data.fn.is_generic, &instruction->base);
ir_add_error(ira, arg_index_inst,
buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic",
@@ -22220,7 +22421,7 @@ static IrInstruction *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstru
return ira->codegen->invalid_instruction;
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
- assert(fn_entry != nullptr);
+ ir_assert(fn_entry != nullptr, &instruction->base);
IrInstruction *result = ir_build_coro_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
coro_id, coro_mem_ptr);
result->value.type = get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type);
@@ -22458,7 +22659,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr
}
if (ordering == AtomicOrderRelease || ordering == AtomicOrderAcqRel) {
- assert(instruction->ordering != nullptr);
+ ir_assert(instruction->ordering != nullptr, &instruction->base);
ir_add_error(ira, instruction->ordering,
buf_sprintf("@atomicLoad atomic ordering must not be Release or AcqRel"));
return ira->codegen->invalid_instruction;
@@ -22466,7 +22667,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr
if (instr_is_comptime(casted_ptr)) {
IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr);
- assert(result->value.type != nullptr);
+ ir_assert(result->value.type != nullptr, &instruction->base);
return result;
}
@@ -22496,7 +22697,7 @@ static IrInstruction *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, I
return ira->codegen->invalid_instruction;
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
- assert(fn_entry != nullptr);
+ ir_assert(fn_entry != nullptr, &instruction->base);
if (type_can_fail(promise_result_type)) {
fn_entry->calls_or_awaits_errorable_fn = true;
@@ -22512,9 +22713,9 @@ static IrInstruction *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ira
if (type_is_invalid(coro_promise_ptr->value.type))
return ira->codegen->invalid_instruction;
- assert(coro_promise_ptr->value.type->id == ZigTypeIdPointer);
+ ir_assert(coro_promise_ptr->value.type->id == ZigTypeIdPointer, &instruction->base);
ZigType *promise_frame_type = coro_promise_ptr->value.type->data.pointer.child_type;
- assert(promise_frame_type->id == ZigTypeIdStruct);
+ ir_assert(promise_frame_type->id == ZigTypeIdStruct, &instruction->base);
ZigType *promise_result_type = promise_frame_type->data.structure.fields[1].type_entry;
if (!type_can_fail(promise_result_type)) {
@@ -22606,7 +22807,7 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS
return result;
}
- assert(float_type->id == ZigTypeIdFloat);
+ ir_assert(float_type->id == ZigTypeIdFloat, &instruction->base);
if (float_type->data.floating.bit_count != 16 &&
float_type->data.floating.bit_count != 32 &&
float_type->data.floating.bit_count != 64) {
@@ -22817,6 +23018,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
case IrInstructionIdArrayToVector:
case IrInstructionIdVectorToArray:
case IrInstructionIdAssertZero:
+ case IrInstructionIdAssertNonNull:
case IrInstructionIdResizeSlice:
case IrInstructionIdLoadPtrGen:
case IrInstructionIdBitCastGen:
@@ -23096,7 +23298,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *old_instruction) {
IrInstruction *new_instruction = ir_analyze_instruction_nocast(ira, old_instruction);
- assert(new_instruction->value.type != nullptr);
+ ir_assert(new_instruction->value.type != nullptr, old_instruction);
old_instruction->child = new_instruction;
return new_instruction;
}
@@ -23221,6 +23423,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdCmpxchgGen:
case IrInstructionIdCmpxchgSrc:
case IrInstructionIdAssertZero:
+ case IrInstructionIdAssertNonNull:
case IrInstructionIdResizeSlice:
case IrInstructionIdGlobalAsm:
return true;
diff --git a/src/ir.hpp b/src/ir.hpp
index 0b85ad2c55..4fb7552212 100644
--- a/src/ir.hpp
+++ b/src/ir.hpp
@@ -14,7 +14,7 @@ bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable
bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
- ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
+ ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
IrExecutable *parent_exec, AstNode *expected_type_source_node);
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index dba0e4ee00..08f5cd01a4 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1003,6 +1003,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct
fprintf(irp->f, ")");
}
+static void ir_print_assert_non_null(IrPrint *irp, IrInstructionAssertNonNull *instruction) {
+ fprintf(irp->f, "AssertNonNull(");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) {
fprintf(irp->f, "@resizeSlice(");
ir_print_other_instruction(irp, instruction->operand);
@@ -1880,6 +1886,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdAssertZero:
ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
break;
+ case IrInstructionIdAssertNonNull:
+ ir_print_assert_non_null(irp, (IrInstructionAssertNonNull *)instruction);
+ break;
case IrInstructionIdResizeSlice:
ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction);
break;
diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp
index 3ea17f1bdc..fc51fa427e 100644
--- a/src/libc_installation.cpp
+++ b/src/libc_installation.cpp
@@ -14,6 +14,7 @@ static const char *zig_libc_keys[] = {
"include_dir",
"sys_include_dir",
"crt_dir",
+ "static_crt_dir",
"msvc_lib_dir",
"kernel32_lib_dir",
};
@@ -34,6 +35,7 @@ static void zig_libc_init_empty(ZigLibCInstallation *libc) {
buf_init_from_str(&libc->include_dir, "");
buf_init_from_str(&libc->sys_include_dir, "");
buf_init_from_str(&libc->crt_dir, "");
+ buf_init_from_str(&libc->static_crt_dir, "");
buf_init_from_str(&libc->msvc_lib_dir, "");
buf_init_from_str(&libc->kernel32_lib_dir, "");
}
@@ -45,7 +47,7 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
bool found_keys[array_length(zig_libc_keys)] = {};
Buf *contents = buf_alloc();
- if ((err = os_fetch_file_path(libc_file, contents, false))) {
+ if ((err = os_fetch_file_path(libc_file, contents))) {
if (err != ErrorFileNotFound && verbose) {
fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err));
}
@@ -74,8 +76,9 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir);
match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->sys_include_dir);
match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_dir);
- match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->msvc_lib_dir);
- match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->kernel32_lib_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->static_crt_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->msvc_lib_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->kernel32_lib_dir);
}
for (size_t i = 0; i < zig_libc_keys_len; i += 1) {
@@ -110,6 +113,15 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
}
}
+ if (buf_len(&libc->static_crt_dir) == 0) {
+ if (target->os == OsWindows && target_abi_is_gnu(target->abi)) {
+ if (verbose) {
+ fprintf(stderr, "static_crt_dir may not be empty for %s\n", target_os_name(target->os));
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ }
+
if (buf_len(&libc->msvc_lib_dir) == 0) {
if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) {
if (verbose) {
@@ -311,6 +323,10 @@ static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool
#endif
#if defined(ZIG_OS_WINDOWS)
+static Error zig_libc_find_native_static_crt_dir_posix(ZigLibCInstallation *self, bool verbose) {
+ return zig_libc_cc_print_file_name("crtbegin.o", &self->static_crt_dir, true, verbose);
+}
+
static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
Error err;
if ((err = os_get_win32_ucrt_include_path(sdk, &self->include_dir))) {
@@ -322,7 +338,7 @@ static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self,
return ErrorNone;
}
-static Error zig_libc_find_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
+static Error zig_libc_find_native_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
bool verbose)
{
Error err;
@@ -398,11 +414,16 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
"# On POSIX it's the directory that includes `sys/errno.h`.\n"
"sys_include_dir=%s\n"
"\n"
- "# The directory that contains `crt1.o`.\n"
+ "# The directory that contains `crt1.o` or `crt2.o`.\n"
"# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n"
"# Not needed when targeting MacOS.\n"
"crt_dir=%s\n"
"\n"
+ "# The directory that contains `crtbegin.o`.\n"
+ "# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.\n"
+ "# Not needed when targeting MacOS.\n"
+ "static_crt_dir=%s\n"
+ "\n"
"# The directory that contains `vcruntime.lib`.\n"
"# Only needed when targeting MSVC on Windows.\n"
"msvc_lib_dir=%s\n"
@@ -415,6 +436,7 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
buf_ptr(&self->include_dir),
buf_ptr(&self->sys_include_dir),
buf_ptr(&self->crt_dir),
+ buf_ptr(&self->static_crt_dir),
buf_ptr(&self->msvc_lib_dir),
buf_ptr(&self->kernel32_lib_dir)
);
@@ -431,6 +453,8 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
return err;
if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))
return err;
+ if ((err = zig_libc_find_native_static_crt_dir_posix(self, verbose)))
+ return err;
return ErrorNone;
} else {
ZigWindowsSDK *sdk;
@@ -444,7 +468,7 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
return err;
if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose)))
return err;
- if ((err = zig_libc_find_crt_dir_windows(self, sdk, &native_target, verbose)))
+ if ((err = zig_libc_find_native_crt_dir_windows(self, sdk, &native_target, verbose)))
return err;
return ErrorNone;
case ZigFindWindowsSdkErrorOutOfMemory:
diff --git a/src/libc_installation.hpp b/src/libc_installation.hpp
index 765ae4ec56..8ecad7ce61 100644
--- a/src/libc_installation.hpp
+++ b/src/libc_installation.hpp
@@ -19,6 +19,7 @@ struct ZigLibCInstallation {
Buf include_dir;
Buf sys_include_dir;
Buf crt_dir;
+ Buf static_crt_dir;
Buf msvc_lib_dir;
Buf kernel32_lib_dir;
};
@@ -29,8 +30,6 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file);
Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose);
-#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_WINDOWS)
Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose);
-#endif
#endif
diff --git a/src/link.cpp b/src/link.cpp
index d6093581f7..8900d0351b 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -25,6 +25,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou
CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path());
child_gen->disable_gen_h = true;
+ child_gen->disable_stack_probing = true;
child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
child_gen->verbose_ast = parent_gen->verbose_ast;
child_gen->verbose_link = parent_gen->verbose_link;
@@ -772,17 +773,15 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
}
}
-static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) {
+static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, OutType child_out_type) {
// The Mach-O LLD code is not well maintained, and trips an assertion
// when we link compiler_rt and builtin as libraries rather than objects.
// Here we workaround this by having compiler_rt and builtin be objects.
// TODO write our own linker. https://github.com/ziglang/zig/issues/1535
- OutType child_out_type = OutTypeLib;
if (parent_gen->zig_target->os == OsMacOSX) {
child_out_type = OutTypeObj;
}
-
CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type,
parent_gen->libc);
codegen_set_out_name(child_gen, buf_create_from_str(aname));
@@ -804,14 +803,14 @@ static Buf *build_a(CodeGen *parent_gen, const char *aname) {
Buf *full_path = buf_alloc();
os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);
- return build_a_raw(parent_gen, aname, full_path);
+ return build_a_raw(parent_gen, aname, full_path, OutTypeLib);
}
-static Buf *build_compiler_rt(CodeGen *parent_gen) {
+static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type) {
Buf *full_path = buf_alloc();
os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("compiler_rt.zig"), full_path);
- return build_a_raw(parent_gen, "compiler_rt", full_path);
+ return build_a_raw(parent_gen, "compiler_rt", full_path, child_out_type);
}
static const char *get_darwin_arch_string(const ZigTarget *t) {
@@ -1006,7 +1005,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append(buf_ptr(builtin_a_path));
}
- Buf *compiler_rt_o_path = build_compiler_rt(g);
+ Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
lj->args.append(buf_ptr(compiler_rt_o_path));
}
@@ -1091,16 +1090,35 @@ static void construct_linker_job_wasm(LinkJob *lj) {
CodeGen *g = lj->codegen;
lj->args.append("-error-limit=0");
- lj->args.append("--no-entry"); // So lld doesn't look for _start.
+
+ if (g->zig_target->os != OsWASI) {
+ lj->args.append("--no-entry"); // So lld doesn't look for _start.
+ }
lj->args.append("--allow-undefined");
- lj->args.append("--export-all");
lj->args.append("-o");
lj->args.append(buf_ptr(&g->output_file_path));
+ auto export_it = g->exported_symbol_names.entry_iterator();
+ decltype(g->exported_symbol_names)::Entry *curr_entry = nullptr;
+ while ((curr_entry = export_it.next()) != nullptr) {
+ Buf *arg = buf_sprintf("--export=%s", buf_ptr(curr_entry->key));
+ lj->args.append(buf_ptr(arg));
+ }
+
// .o files
for (size_t i = 0; i < g->link_objects.length; i += 1) {
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
}
+
+ if (g->out_type == OutTypeExe) {
+ if (g->libc_link_lib == nullptr) {
+ Buf *builtin_a_path = build_a(g, "builtin");
+ lj->args.append(buf_ptr(builtin_a_path));
+ }
+
+ Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
+ lj->args.append(buf_ptr(compiler_rt_o_path));
+ }
}
static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {
@@ -1124,53 +1142,121 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
}
static void add_uefi_link_args(LinkJob *lj) {
- lj->args.append("/BASE:0");
- lj->args.append("/ENTRY:EfiMain");
- lj->args.append("/OPT:REF");
- lj->args.append("/SAFESEH:NO");
- lj->args.append("/MERGE:.rdata=.data");
- lj->args.append("/ALIGN:32");
- lj->args.append("/NODEFAULTLIB");
- lj->args.append("/SECTION:.xdata,D");
+ lj->args.append("-BASE:0");
+ lj->args.append("-ENTRY:EfiMain");
+ lj->args.append("-OPT:REF");
+ lj->args.append("-SAFESEH:NO");
+ lj->args.append("-MERGE:.rdata=.data");
+ lj->args.append("-ALIGN:32");
+ lj->args.append("-NODEFAULTLIB");
+ lj->args.append("-SECTION:.xdata,D");
}
-static void add_nt_link_args(LinkJob *lj, bool is_library) {
+static void add_msvc_link_args(LinkJob *lj, bool is_library) {
CodeGen *g = lj->codegen;
- if (lj->link_in_crt) {
- // TODO: https://github.com/ziglang/zig/issues/2064
- bool is_dynamic = true; // g->is_dynamic;
- const char *lib_str = is_dynamic ? "" : "lib";
- const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
-
- if (!is_dynamic) {
- Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str);
- lj->args.append(buf_ptr(cmt_lib_name));
- } else {
- Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str);
- lj->args.append(buf_ptr(msvcrt_lib_name));
- }
+ // TODO: https://github.com/ziglang/zig/issues/2064
+ bool is_dynamic = true; // g->is_dynamic;
+ const char *lib_str = is_dynamic ? "" : "lib";
+ const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
+
+ if (!is_dynamic) {
+ Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str);
+ lj->args.append(buf_ptr(cmt_lib_name));
+ } else {
+ Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str);
+ lj->args.append(buf_ptr(msvcrt_lib_name));
+ }
+
+ Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str);
+ lj->args.append(buf_ptr(vcruntime_lib_name));
- Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str);
- lj->args.append(buf_ptr(vcruntime_lib_name));
+ Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str);
+ lj->args.append(buf_ptr(crt_lib_name));
- Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str);
- lj->args.append(buf_ptr(crt_lib_name));
+ //Visual C++ 2015 Conformance Changes
+ //https://msdn.microsoft.com/en-us/library/bb531344.aspx
+ lj->args.append("legacy_stdio_definitions.lib");
- //Visual C++ 2015 Conformance Changes
- //https://msdn.microsoft.com/en-us/library/bb531344.aspx
- lj->args.append("legacy_stdio_definitions.lib");
+ // msvcrt depends on kernel32 and ntdll
+ lj->args.append("kernel32.lib");
+ lj->args.append("ntdll.lib");
+}
+
+static const char *get_libc_file(ZigLibCInstallation *lib, const char *file) {
+ Buf *out_buf = buf_alloc();
+ os_path_join(&lib->crt_dir, buf_create_from_str(file), out_buf);
+ return buf_ptr(out_buf);
+}
+
+static const char *get_libc_static_file(ZigLibCInstallation *lib, const char *file) {
+ Buf *out_buf = buf_alloc();
+ os_path_join(&lib->static_crt_dir, buf_create_from_str(file), out_buf);
+ return buf_ptr(out_buf);
+}
+
+static void add_mingw_link_args(LinkJob *lj, bool is_library) {
+ CodeGen *g = lj->codegen;
- // msvcrt depends on kernel32 and ntdll
- lj->args.append("kernel32.lib");
- lj->args.append("ntdll.lib");
+ bool is_dll = g->out_type == OutTypeLib && g->is_dynamic;
+
+ if (g->zig_target->arch == ZigLLVM_x86) {
+ lj->args.append("-ALTERNATENAME:__image_base__=___ImageBase");
+ } else {
+ lj->args.append("-ALTERNATENAME:__image_base__=__ImageBase");
+ }
+
+ if (is_dll) {
+ lj->args.append(get_libc_file(g->libc, "dllcrt2.o"));
+ } else {
+ lj->args.append(get_libc_file(g->libc, "crt2.o"));
+ }
+
+ lj->args.append(get_libc_static_file(g->libc, "crtbegin.o"));
+
+ lj->args.append(get_libc_file(g->libc, "libmingw32.a"));
+
+ if (is_dll) {
+ lj->args.append(get_libc_static_file(g->libc, "libgcc_s.a"));
+ lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
+ } else {
+ lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
+ lj->args.append(get_libc_static_file(g->libc, "libgcc_eh.a"));
+ }
+
+ lj->args.append(get_libc_static_file(g->libc, "libssp.a"));
+ lj->args.append(get_libc_file(g->libc, "libmoldname.a"));
+ lj->args.append(get_libc_file(g->libc, "libmingwex.a"));
+ lj->args.append(get_libc_file(g->libc, "libmsvcrt.a"));
+
+ if (g->subsystem == TargetSubsystemWindows) {
+ lj->args.append(get_libc_file(g->libc, "libgdi32.a"));
+ lj->args.append(get_libc_file(g->libc, "libcomdlg32.a"));
+ }
+
+ lj->args.append(get_libc_file(g->libc, "libadvapi32.a"));
+ lj->args.append(get_libc_file(g->libc, "libadvapi32.a"));
+ lj->args.append(get_libc_file(g->libc, "libshell32.a"));
+ lj->args.append(get_libc_file(g->libc, "libuser32.a"));
+ lj->args.append(get_libc_file(g->libc, "libkernel32.a"));
+
+ lj->args.append(get_libc_static_file(g->libc, "crtend.o"));
+}
+
+static void add_win_link_args(LinkJob *lj, bool is_library) {
+ if (lj->link_in_crt) {
+ if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
+ add_mingw_link_args(lj, is_library);
+ } else {
+ add_msvc_link_args(lj, is_library);
+ }
} else {
- lj->args.append("/NODEFAULTLIB");
+ lj->args.append("-NODEFAULTLIB");
if (!is_library) {
- if (g->have_winmain) {
- lj->args.append("/ENTRY:WinMain");
+ if (lj->codegen->have_winmain) {
+ lj->args.append("-ENTRY:WinMain");
} else {
- lj->args.append("/ENTRY:WinMainCRTStartup");
+ lj->args.append("-ENTRY:WinMainCRTStartup");
}
}
}
@@ -1180,87 +1266,93 @@ static void construct_linker_job_coff(LinkJob *lj) {
Error err;
CodeGen *g = lj->codegen;
- lj->args.append("/ERRORLIMIT:0");
+ lj->args.append("-ERRORLIMIT:0");
- lj->args.append("/NOLOGO");
+ lj->args.append("-NOLOGO");
if (!g->strip_debug_symbols) {
- lj->args.append("/DEBUG");
+ lj->args.append("-DEBUG");
}
if (g->out_type == OutTypeExe) {
// TODO compile time stack upper bound detection
- lj->args.append("/STACK:16777216");
+ lj->args.append("-STACK:16777216");
}
coff_append_machine_arg(g, &lj->args);
bool is_library = g->out_type == OutTypeLib;
+ if (is_library && g->is_dynamic) {
+ lj->args.append("-DLL");
+ }
+
+ lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
+
+ if (g->libc_link_lib != nullptr) {
+ assert(g->libc != nullptr);
+
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
+
+ if (target_abi_is_gnu(g->zig_target->abi)) {
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->sys_include_dir))));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->include_dir))));
+ } else {
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
+ }
+ }
+
+ for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
+ const char *lib_dir = g->lib_dirs.at(i);
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
+ }
+
+ for (size_t i = 0; i < g->link_objects.length; i += 1) {
+ lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
+ }
+
switch (g->subsystem) {
case TargetSubsystemAuto:
if (g->zig_target->os == OsUefi) {
add_uefi_link_args(lj);
} else {
- add_nt_link_args(lj, is_library);
+ add_win_link_args(lj, is_library);
}
break;
case TargetSubsystemConsole:
- lj->args.append("/SUBSYSTEM:console");
- add_nt_link_args(lj, is_library);
+ lj->args.append("-SUBSYSTEM:console");
+ add_win_link_args(lj, is_library);
break;
case TargetSubsystemEfiApplication:
- lj->args.append("/SUBSYSTEM:efi_application");
+ lj->args.append("-SUBSYSTEM:efi_application");
add_uefi_link_args(lj);
break;
case TargetSubsystemEfiBootServiceDriver:
- lj->args.append("/SUBSYSTEM:efi_boot_service_driver");
+ lj->args.append("-SUBSYSTEM:efi_boot_service_driver");
add_uefi_link_args(lj);
break;
case TargetSubsystemEfiRom:
- lj->args.append("/SUBSYSTEM:efi_rom");
+ lj->args.append("-SUBSYSTEM:efi_rom");
add_uefi_link_args(lj);
break;
case TargetSubsystemEfiRuntimeDriver:
- lj->args.append("/SUBSYSTEM:efi_runtime_driver");
+ lj->args.append("-SUBSYSTEM:efi_runtime_driver");
add_uefi_link_args(lj);
break;
case TargetSubsystemNative:
- lj->args.append("/SUBSYSTEM:native");
- add_nt_link_args(lj, is_library);
+ lj->args.append("-SUBSYSTEM:native");
+ add_win_link_args(lj, is_library);
break;
case TargetSubsystemPosix:
- lj->args.append("/SUBSYSTEM:posix");
- add_nt_link_args(lj, is_library);
+ lj->args.append("-SUBSYSTEM:posix");
+ add_win_link_args(lj, is_library);
break;
case TargetSubsystemWindows:
- lj->args.append("/SUBSYSTEM:windows");
- add_nt_link_args(lj, is_library);
+ lj->args.append("-SUBSYSTEM:windows");
+ add_win_link_args(lj, is_library);
break;
}
- lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
-
- if (g->libc_link_lib != nullptr) {
- assert(g->libc != nullptr);
-
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
- }
-
- if (is_library && g->is_dynamic) {
- lj->args.append("-DLL");
- }
-
- for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
- const char *lib_dir = g->lib_dirs.at(i);
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
- }
-
- for (size_t i = 0; i < g->link_objects.length; i += 1) {
- lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
- }
-
if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) {
if (g->libc_link_lib == nullptr && !g->is_dummy_so) {
Buf *builtin_a_path = build_a(g, "builtin");
@@ -1268,7 +1360,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
}
// msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage
- Buf *compiler_rt_o_path = build_compiler_rt(g);
+ Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
lj->args.append(buf_ptr(compiler_rt_o_path));
}
@@ -1280,11 +1372,10 @@ static void construct_linker_job_coff(LinkJob *lj) {
continue;
}
if (link_lib->provided_explicitly) {
- if (lj->codegen->zig_target->abi == ZigLLVM_GNU) {
- Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
- lj->args.append(buf_ptr(arg));
- }
- else {
+ if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
+ Buf *lib_name = buf_sprintf("lib%s.a", buf_ptr(link_lib->name));
+ lj->args.append(buf_ptr(lib_name));
+ } else {
lj->args.append(buf_ptr(link_lib->name));
}
} else {
@@ -1416,18 +1507,6 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
}
}
-static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) {
- if (platform->major < major) {
- return true;
- } else if (platform->major > major) {
- return false;
- }
- if (platform->minor < minor) {
- return true;
- }
- return false;
-}
-
static void construct_linker_job_macho(LinkJob *lj) {
CodeGen *g = lj->codegen;
@@ -1524,7 +1603,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
// compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
if (g->out_type == OutTypeExe || is_dyn_lib) {
- Buf *compiler_rt_o_path = build_compiler_rt(g);
+ Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
lj->args.append(buf_ptr(compiler_rt_o_path));
}
@@ -1552,16 +1631,6 @@ static void construct_linker_job_macho(LinkJob *lj) {
lj->args.append("dynamic_lookup");
}
- if (platform.kind == MacOS) {
- if (darwin_version_lt(&platform, 10, 5)) {
- lj->args.append("-lgcc_s.10.4");
- } else if (darwin_version_lt(&platform, 10, 6)) {
- lj->args.append("-lgcc_s.10.5");
- }
- } else {
- zig_panic("TODO");
- }
-
for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {
lj->args.append("-framework");
lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));
@@ -1585,6 +1654,11 @@ static void construct_linker_job(LinkJob *lj) {
}
}
+void zig_link_add_compiler_rt(CodeGen *g) {
+ Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj);
+ g->link_objects.append(compiler_rt_o_path);
+}
+
void codegen_link(CodeGen *g) {
codegen_add_time_event(g, "Build Dependencies");
@@ -1611,14 +1685,14 @@ void codegen_link(CodeGen *g) {
if (g->out_type == OutTypeLib && !g->is_dynamic) {
ZigList<const char *> file_names = {};
for (size_t i = 0; i < g->link_objects.length; i += 1) {
- file_names.append((const char *)buf_ptr(g->link_objects.at(i)));
+ file_names.append(buf_ptr(g->link_objects.at(i)));
}
ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os);
codegen_add_time_event(g, "LLVM Link");
if (g->verbose_link) {
fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path));
- for (size_t i = 0; i < g->link_objects.length; i += 1) {
- fprintf(stderr, " %s", (const char *)buf_ptr(g->link_objects.at(i)));
+ for (size_t i = 0; i < file_names.length; i += 1) {
+ fprintf(stderr, " %s", file_names.at(i));
}
fprintf(stderr, "\n");
}
diff --git a/src/list.hpp b/src/list.hpp
index b69a369f5a..f838e44a5b 100644
--- a/src/list.hpp
+++ b/src/list.hpp
@@ -10,8 +10,6 @@
#include "util.hpp"
-#include <assert.h>
-
template<typename T>
struct ZigList {
void deinit() {
diff --git a/src/main.cpp b/src/main.cpp
index bd3d574956..5659624cb7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -14,6 +14,7 @@
#include "os.hpp"
#include "target.hpp"
#include "libc_installation.hpp"
+#include "userland.h"
#include <stdio.h>
@@ -40,6 +41,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" libc [paths_file] Display native libc paths file or validate one\n"
" run [source] [-- [args]] create executable and run immediately\n"
" translate-c [source] convert c code to zig code\n"
+ " translate-c-2 [source] experimental self-hosted translate-c\n"
" targets list available compilation targets\n"
" test [source] create and run a test build\n"
" version print version number and exit\n"
@@ -52,11 +54,12 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" --cache [auto|off|on] build in cache, print output path to stdout\n"
" --color [auto|off|on] enable or disable colored error messages\n"
" --disable-gen-h do not generate a C header file (.h)\n"
- " --disable-pic disable Position Independent Code\n"
- " --enable-pic enable Position Independent Code\n"
" --disable-valgrind omit valgrind client requests in debug builds\n"
" --enable-valgrind include valgrind client requests release builds\n"
+ " --disable-stack-probing workaround for macosx\n"
" --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
+ " -fPIC enable Position Independent Code\n"
+ " -fno-PIC disable Position Independent Code\n"
" -ftime-report print timing diagnostics\n"
" --libc [file] Provide a file which specifies libc paths\n"
" --name [name] override output name\n"
@@ -84,6 +87,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" --override-std-dir [arg] use an alternate Zig standard library\n"
"\n"
"Link Options:\n"
+ " --bundle-compiler-rt [path] for static libraries, include compiler-rt symbols\n"
" --dynamic-linker [path] set the path to ld.so\n"
" --each-lib-rpath add rpath for each used dynamic library\n"
" --library [lib] link against lib\n"
@@ -131,19 +135,6 @@ static int print_libc_usage(const char *arg0, FILE *file, int return_code) {
return return_code;
}
-static const char *ZIG_ZEN = "\n"
-" * Communicate intent precisely.\n"
-" * Edge cases matter.\n"
-" * Favor reading code over writing code.\n"
-" * Only one obvious way to do things.\n"
-" * Runtime crashes are better than bugs.\n"
-" * Compile errors are better than runtime crashes.\n"
-" * Incremental improvements.\n"
-" * Avoid local maximums.\n"
-" * Reduce the amount one must remember.\n"
-" * Minimize energy spent on coding style.\n"
-" * Together we serve end users.\n";
-
static bool arch_available_in_llvm(ZigLLVM_ArchType arch) {
LLVMTargetRef target_ref;
char *err_msg = nullptr;
@@ -211,6 +202,7 @@ enum Cmd {
CmdTargets,
CmdTest,
CmdTranslateC,
+ CmdTranslateCUserland,
CmdVersion,
CmdZen,
CmdLibC,
@@ -324,7 +316,7 @@ int main(int argc, char **argv) {
return print_error_usage(arg0);
}
Buf *cmd_template_path = buf_alloc();
- os_path_join(get_zig_special_dir(), buf_create_from_str(init_cmd), cmd_template_path);
+ os_path_join(get_zig_special_dir(get_zig_lib_dir()), buf_create_from_str(init_cmd), cmd_template_path);
Buf *build_zig_path = buf_alloc();
os_path_join(cmd_template_path, buf_create_from_str("build.zig"), build_zig_path);
Buf *src_dir_path = buf_alloc();
@@ -341,7 +333,7 @@ int main(int argc, char **argv) {
os_path_split(cwd, nullptr, cwd_basename);
Buf *build_zig_contents = buf_alloc();
- if ((err = os_fetch_file_path(build_zig_path, build_zig_contents, false))) {
+ if ((err = os_fetch_file_path(build_zig_path, build_zig_contents))) {
fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(build_zig_path), err_str(err));
return EXIT_FAILURE;
}
@@ -356,7 +348,7 @@ int main(int argc, char **argv) {
}
Buf *main_zig_contents = buf_alloc();
- if ((err = os_fetch_file_path(main_zig_path, main_zig_contents, false))) {
+ if ((err = os_fetch_file_path(main_zig_path, main_zig_contents))) {
fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(main_zig_path), err_str(err));
return EXIT_FAILURE;
}
@@ -450,9 +442,12 @@ int main(int argc, char **argv) {
int runtime_args_start = -1;
bool system_linker_hack = false;
TargetSubsystem subsystem = TargetSubsystemAuto;
- bool is_single_threaded = false;
+ bool want_single_threaded = false;
bool disable_gen_h = false;
+ bool bundle_compiler_rt = false;
+ bool disable_stack_probing = false;
Buf *override_std_dir = nullptr;
+ Buf *override_lib_dir = nullptr;
Buf *main_pkg_path = nullptr;
ValgrindSupport valgrind_support = ValgrindSupportAuto;
WantPIC want_pic = WantPICAuto;
@@ -486,13 +481,27 @@ int main(int argc, char **argv) {
} else if (i + 1 < argc && strcmp(argv[i], "--cache-dir") == 0) {
cache_dir = argv[i + 1];
i += 1;
+ } else if (i + 1 < argc && strcmp(argv[i], "--override-std-dir") == 0) {
+ override_std_dir = buf_create_from_str(argv[i + 1]);
+ i += 1;
+
+ args.append("--override-std-dir");
+ args.append(buf_ptr(override_std_dir));
+ } else if (i + 1 < argc && strcmp(argv[i], "--override-lib-dir") == 0) {
+ override_lib_dir = buf_create_from_str(argv[i + 1]);
+ i += 1;
+
+ args.append("--override-lib-dir");
+ args.append(buf_ptr(override_lib_dir));
} else {
args.append(argv[i]);
}
}
+ Buf *zig_lib_dir = (override_lib_dir == nullptr) ? get_zig_lib_dir() : override_lib_dir;
+
Buf *build_runner_path = buf_alloc();
- os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);
+ os_path_join(get_zig_special_dir(zig_lib_dir), buf_create_from_str("build_runner.zig"), build_runner_path);
ZigTarget target;
get_native_target(&target);
@@ -512,7 +521,7 @@ int main(int argc, char **argv) {
}
CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe,
- BuildModeDebug, get_zig_lib_dir(), override_std_dir, nullptr, &full_cache_dir);
+ BuildModeDebug, override_lib_dir, override_std_dir, nullptr, &full_cache_dir);
g->valgrind_support = valgrind_support;
g->enable_time_report = timing_info;
codegen_set_out_name(g, buf_create_from_str("build"));
@@ -532,23 +541,25 @@ int main(int argc, char **argv) {
"Usage: %s build [options]\n"
"\n"
"General Options:\n"
- " --help Print this help and exit\n"
- " --verbose Print commands before executing them\n"
- " --prefix [path] Override default install prefix\n"
- " --search-prefix [path] Add a path to look for binaries, libraries, headers\n"
+ " --help Print this help and exit\n"
+ " --verbose Print commands before executing them\n"
+ " --prefix [path] Override default install prefix\n"
+ " --search-prefix [path] Add a path to look for binaries, libraries, headers\n"
"\n"
"Project-specific options become available when the build file is found.\n"
"\n"
"Advanced Options:\n"
- " --build-file [file] Override path to build.zig\n"
- " --cache-dir [path] Override path to cache directory\n"
- " --verbose-tokenize Enable compiler debug output for tokenization\n"
- " --verbose-ast Enable compiler debug output for parsing into an AST\n"
- " --verbose-link Enable compiler debug output for linking\n"
- " --verbose-ir Enable compiler debug output for Zig IR\n"
- " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
- " --verbose-cimport Enable compiler debug output for C imports\n"
- " --verbose-cc Enable compiler debug output for C compilation\n"
+ " --build-file [file] Override path to build.zig\n"
+ " --cache-dir [path] Override path to cache directory\n"
+ " --override-std-dir [arg] Override path to Zig standard library\n"
+ " --override-lib-dir [arg] Override path to Zig lib library\n"
+ " --verbose-tokenize Enable compiler debug output for tokenization\n"
+ " --verbose-ast Enable compiler debug output for parsing into an AST\n"
+ " --verbose-link Enable compiler debug output for linking\n"
+ " --verbose-ir Enable compiler debug output for Zig IR\n"
+ " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
+ " --verbose-cimport Enable compiler debug output for C imports\n"
+ " --verbose-cc Enable compiler debug output for C compilation\n"
"\n"
, zig_exe_path);
return EXIT_SUCCESS;
@@ -581,36 +592,7 @@ int main(int argc, char **argv) {
}
return (term.how == TerminationIdClean) ? term.code : -1;
} else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
- init_all_targets();
- ZigTarget target;
- get_native_target(&target);
- Buf *fmt_runner_path = buf_alloc();
- os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path);
- Buf *cache_dir_buf = buf_create_from_str(cache_dir ? cache_dir : default_zig_cache_name);
- CodeGen *g = codegen_create(main_pkg_path, fmt_runner_path, &target, OutTypeExe,
- BuildModeDebug, get_zig_lib_dir(), nullptr, nullptr, cache_dir_buf);
- g->valgrind_support = valgrind_support;
- g->is_single_threaded = true;
- codegen_set_out_name(g, buf_create_from_str("fmt"));
- g->enable_cache = true;
-
- codegen_build_and_link(g);
-
- // TODO standardize os.cpp so that the args are supposed to have the exe
- ZigList<const char*> args_with_exe = {0};
- ZigList<const char*> args_without_exe = {0};
- const char *exec_path = buf_ptr(&g->output_file_path);
- args_with_exe.append(exec_path);
- for (int i = 2; i < argc; i += 1) {
- args_with_exe.append(argv[i]);
- args_without_exe.append(argv[i]);
- }
- args_with_exe.append(nullptr);
- os_execv(exec_path, args_with_exe.items);
-
- Termination term;
- os_spawn_process(exec_path, args_without_exe, &term);
- return term.code;
+ return stage2_fmt(argc, argv);
}
for (int i = 1; i < argc; i += 1) {
@@ -664,16 +646,20 @@ int main(int argc, char **argv) {
valgrind_support = ValgrindSupportEnabled;
} else if (strcmp(arg, "--disable-valgrind") == 0) {
valgrind_support = ValgrindSupportDisabled;
- } else if (strcmp(arg, "--enable-pic") == 0) {
+ } else if (strcmp(arg, "-fPIC") == 0) {
want_pic = WantPICEnabled;
- } else if (strcmp(arg, "--disable-pic") == 0) {
+ } else if (strcmp(arg, "-fno-PIC") == 0) {
want_pic = WantPICDisabled;
} else if (strcmp(arg, "--system-linker-hack") == 0) {
system_linker_hack = true;
} else if (strcmp(arg, "--single-threaded") == 0) {
- is_single_threaded = true;
+ want_single_threaded = true;
} else if (strcmp(arg, "--disable-gen-h") == 0) {
disable_gen_h = true;
+ } else if (strcmp(arg, "--bundle-compiler-rt") == 0) {
+ bundle_compiler_rt = true;
+ } else if (strcmp(arg, "--disable-stack-probing") == 0) {
+ disable_stack_probing = true;
} else if (strcmp(arg, "--test-cmd-bin") == 0) {
test_exec_args.append(nullptr);
} else if (arg[1] == 'L' && arg[2] != 0) {
@@ -757,6 +743,8 @@ int main(int argc, char **argv) {
llvm_argv.append(argv[i]);
} else if (strcmp(arg, "--override-std-dir") == 0) {
override_std_dir = buf_create_from_str(argv[i]);
+ } else if (strcmp(arg, "--override-lib-dir") == 0) {
+ override_lib_dir = buf_create_from_str(argv[i]);
} else if (strcmp(arg, "--main-pkg-path") == 0) {
main_pkg_path = buf_create_from_str(argv[i]);
} else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {
@@ -775,7 +763,11 @@ int main(int argc, char **argv) {
if (argv[i][0] == '-') {
c_file->args.append(argv[i]);
i += 1;
- continue;
+ if (i < argc) {
+ continue;
+ }
+
+ break;
} else {
c_file->source_path = argv[i];
c_source_files.append(c_file);
@@ -867,6 +859,8 @@ int main(int argc, char **argv) {
cmd = CmdLibC;
} else if (strcmp(arg, "translate-c") == 0) {
cmd = CmdTranslateC;
+ } else if (strcmp(arg, "translate-c-2") == 0) {
+ cmd = CmdTranslateCUserland;
} else if (strcmp(arg, "test") == 0) {
cmd = CmdTest;
out_type = OutTypeExe;
@@ -883,6 +877,7 @@ int main(int argc, char **argv) {
case CmdBuild:
case CmdRun:
case CmdTranslateC:
+ case CmdTranslateCUserland:
case CmdTest:
case CmdLibC:
if (!in_file) {
@@ -959,10 +954,10 @@ int main(int argc, char **argv) {
}
case CmdBuiltin: {
CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,
- out_type, build_mode, get_zig_lib_dir(), override_std_dir, nullptr, nullptr);
+ out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr);
g->valgrind_support = valgrind_support;
g->want_pic = want_pic;
- g->is_single_threaded = is_single_threaded;
+ g->want_single_threaded = want_single_threaded;
Buf *builtin_source = codegen_generate_builtin_source(g);
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
@@ -973,6 +968,7 @@ int main(int argc, char **argv) {
case CmdRun:
case CmdBuild:
case CmdTranslateC:
+ case CmdTranslateCUserland:
case CmdTest:
{
if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0 &&
@@ -985,14 +981,16 @@ int main(int argc, char **argv) {
" * --assembly argument\n"
" * --c-source argument\n");
return print_error_usage(arg0);
- } else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) {
+ } else if ((cmd == CmdTranslateC || cmd == CmdTranslateCUserland ||
+ cmd == CmdTest || cmd == CmdRun) && !in_file)
+ {
fprintf(stderr, "Expected source file argument.\n");
return print_error_usage(arg0);
}
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
- bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC);
+ bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC || cmd == CmdTranslateCUserland);
if (cmd == CmdRun) {
out_name = "run";
@@ -1026,7 +1024,8 @@ int main(int argc, char **argv) {
return print_error_usage(arg0);
}
- Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
+ Buf *zig_root_source_file = (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) ?
+ nullptr : in_file_buf;
if (cmd == CmdRun && buf_out_name == nullptr) {
buf_out_name = buf_create_from_str("run");
@@ -1050,7 +1049,7 @@ int main(int argc, char **argv) {
cache_dir_buf = buf_create_from_str(cache_dir);
}
CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,
- get_zig_lib_dir(), override_std_dir, libc, cache_dir_buf);
+ override_lib_dir, override_std_dir, libc, cache_dir_buf);
if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
g->valgrind_support = valgrind_support;
g->want_pic = want_pic;
@@ -1060,7 +1059,7 @@ int main(int argc, char **argv) {
codegen_set_out_name(g, buf_out_name);
codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
codegen_set_is_test(g, cmd == CmdTest);
- g->is_single_threaded = is_single_threaded;
+ g->want_single_threaded = want_single_threaded;
codegen_set_linker_script(g, linker_script);
if (each_lib_rpath)
codegen_set_each_lib_rpath(g, each_lib_rpath);
@@ -1079,6 +1078,8 @@ int main(int argc, char **argv) {
g->verbose_cc = verbose_cc;
g->output_dir = output_dir;
g->disable_gen_h = disable_gen_h;
+ g->bundle_compiler_rt = bundle_compiler_rt;
+ g->disable_stack_probing = disable_stack_probing;
codegen_set_errmsg_color(g, color);
g->system_linker_hack = system_linker_hack;
@@ -1144,14 +1145,15 @@ int main(int argc, char **argv) {
codegen_print_timing_report(g, stdout);
if (cmd == CmdRun) {
+ const char *exec_path = buf_ptr(&g->output_file_path);
ZigList<const char*> args = {0};
+
+ args.append(exec_path);
if (runtime_args_start != -1) {
for (int i = runtime_args_start; i < argc; ++i) {
args.append(argv[i]);
}
}
-
- const char *exec_path = buf_ptr(&g->output_file_path);
args.append(nullptr);
os_execv(exec_path, args.items);
@@ -1169,9 +1171,8 @@ int main(int argc, char **argv) {
} else {
zig_unreachable();
}
- } else if (cmd == CmdTranslateC) {
- AstNode *root_node = codegen_translate_c(g, in_file_buf);
- ast_render(g, stdout, root_node, 4);
+ } else if (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) {
+ codegen_translate_c(g, in_file_buf, stdout, cmd == CmdTranslateCUserland);
if (timing_info)
codegen_print_timing_report(g, stderr);
return EXIT_SUCCESS;
@@ -1228,9 +1229,13 @@ int main(int argc, char **argv) {
case CmdVersion:
printf("%s\n", ZIG_VERSION_STRING);
return EXIT_SUCCESS;
- case CmdZen:
- printf("%s\n", ZIG_ZEN);
+ case CmdZen: {
+ const char *ptr;
+ size_t len;
+ stage2_zen(&ptr, &len);
+ fwrite(ptr, len, 1, stdout);
return EXIT_SUCCESS;
+ }
case CmdTargets:
return print_target_list(stdout);
case CmdNone:
diff --git a/src/os.cpp b/src/os.cpp
index 470d222307..83c67d5818 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -751,39 +751,15 @@ Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {
#endif
}
-Error os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
+Error os_fetch_file(FILE *f, Buf *out_buf) {
static const ssize_t buf_size = 0x2000;
buf_resize(out_buf, buf_size);
ssize_t actual_buf_len = 0;
- bool first_read = true;
-
for (;;) {
size_t amt_read = fread(buf_ptr(out_buf) + actual_buf_len, 1, buf_size, f);
actual_buf_len += amt_read;
- if (skip_shebang && first_read && buf_starts_with_str(out_buf, "#!")) {
- size_t i = 0;
- while (true) {
- if (i > buf_len(out_buf)) {
- zig_panic("shebang line exceeded %zd characters", buf_size);
- }
-
- size_t current_pos = i;
- i += 1;
-
- if (out_buf->list.at(current_pos) == '\n') {
- break;
- }
- }
-
- ZigList<char> *list = &out_buf->list;
- memmove(list->items, list->items + i, list->length - i);
- list->length -= i;
-
- actual_buf_len -= i;
- }
-
if (amt_read != buf_size) {
if (feof(f)) {
buf_resize(out_buf, actual_buf_len);
@@ -794,7 +770,6 @@ Error os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
}
buf_resize(out_buf, actual_buf_len + buf_size);
- first_read = false;
}
zig_unreachable();
}
@@ -864,8 +839,8 @@ static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,
FILE *stdout_f = fdopen(stdout_pipe[0], "rb");
FILE *stderr_f = fdopen(stderr_pipe[0], "rb");
- Error err1 = os_fetch_file(stdout_f, out_stdout, false);
- Error err2 = os_fetch_file(stderr_f, out_stderr, false);
+ Error err1 = os_fetch_file(stdout_f, out_stdout);
+ Error err2 = os_fetch_file(stderr_f, out_stderr);
fclose(stdout_f);
fclose(stderr_f);
@@ -1097,7 +1072,7 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {
}
}
-Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
+Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {
FILE *f = fopen(buf_ptr(full_path), "rb");
if (!f) {
switch (errno) {
@@ -1116,7 +1091,7 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
return ErrorFileSystem;
}
}
- Error result = os_fetch_file(f, out_contents, skip_shebang);
+ Error result = os_fetch_file(f, out_contents);
fclose(f);
return result;
}
@@ -1772,8 +1747,14 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {
// TODO use /etc/passwd
return ErrorFileNotFound;
}
- buf_resize(out_path, 0);
- buf_appendf(out_path, "%s/.local/share/%s", home_dir, appname);
+ if (home_dir[0] == 0) {
+ return ErrorFileNotFound;
+ }
+ buf_init_from_str(out_path, home_dir);
+ if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') {
+ buf_append_char(out_path, '/');
+ }
+ buf_appendf(out_path, ".local/share/%s", appname);
return ErrorNone;
#endif
}
@@ -2081,11 +2062,13 @@ Error os_file_overwrite(OsFile file, Buf *contents) {
#endif
}
-void os_file_close(OsFile file) {
+void os_file_close(OsFile *file) {
#if defined(ZIG_OS_WINDOWS)
- CloseHandle(file);
+ CloseHandle(*file);
+ *file = NULL;
#else
- close(file);
+ close(*file);
+ *file = -1;
#endif
}
diff --git a/src/os.hpp b/src/os.hpp
index 5064a6444c..058bb2020c 100644
--- a/src/os.hpp
+++ b/src/os.hpp
@@ -121,13 +121,13 @@ Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
-void os_file_close(OsFile file);
+void os_file_close(OsFile *file);
Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
-Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);
-Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);
+Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
+Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);
Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
diff --git a/src/parser.cpp b/src/parser.cpp
index 9172e21b92..583accfd72 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -577,7 +577,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) {
// TopLevelDecl
// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
-// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl
+// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
// / KEYWORD_use Expr SEMICOLON
static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
Token *first = eat_token_if(pc, TokenIdKeywordExport);
@@ -591,17 +591,22 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
lib_name = eat_token_if(pc, TokenIdStringLiteral);
if (first->id != TokenIdKeywordInline) {
+ Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
AstNode *var_decl = ast_parse_var_decl(pc);
if (var_decl != nullptr) {
assert(var_decl->type == NodeTypeVariableDeclaration);
var_decl->line = first->start_line;
var_decl->column = first->start_column;
+ var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
var_decl->data.variable_declaration.visib_mod = visib_mod;
var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern;
var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport;
var_decl->data.variable_declaration.lib_name = token_buf(lib_name);
return var_decl;
}
+
+ if (thread_local_kw != nullptr)
+ put_back_token(pc);
}
AstNode *fn_proto = ast_parse_fn_proto(pc);
@@ -632,13 +637,18 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
ast_invalid_token_error(pc, peek_token(pc));
}
+ Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
AstNode *var_decl = ast_parse_var_decl(pc);
if (var_decl != nullptr) {
assert(var_decl->type == NodeTypeVariableDeclaration);
var_decl->data.variable_declaration.visib_mod = visib_mod;
+ var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
return var_decl;
}
+ if (thread_local_kw != nullptr)
+ put_back_token(pc);
+
AstNode *fn_proto = ast_parse_fn_proto(pc);
if (fn_proto != nullptr) {
AstNode *body = ast_parse_block(pc);
@@ -741,17 +751,12 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
static AstNode *ast_parse_var_decl(ParseContext *pc) {
- Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst);
if (mut_kw == nullptr)
mut_kw = eat_token_if(pc, TokenIdKeywordVar);
- if (mut_kw == nullptr) {
- if (thread_local_kw == nullptr) {
- return nullptr;
- } else {
- ast_invalid_token_error(pc, peek_token(pc));
- }
- }
+ if (mut_kw == nullptr)
+ return nullptr;
+
Token *identifier = expect_token(pc, TokenIdSymbol);
AstNode *type_expr = nullptr;
if (eat_token_if(pc, TokenIdColon) != nullptr)
@@ -766,7 +771,6 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
expect_token(pc, TokenIdSemicolon);
AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw);
- res->data.variable_declaration.threadlocal_tok = thread_local_kw;
res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst;
res->data.variable_declaration.symbol = token_buf(identifier);
res->data.variable_declaration.type = type_expr;
@@ -952,17 +956,10 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) {
// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
static AstNode *ast_parse_loop_statement(ParseContext *pc) {
- Token *label = ast_parse_block_label(pc);
- Token *first = label;
-
Token *inline_token = eat_token_if(pc, TokenIdKeywordInline);
- if (first == nullptr)
- first = inline_token;
-
AstNode *for_statement = ast_parse_for_statement(pc);
if (for_statement != nullptr) {
assert(for_statement->type == NodeTypeForExpr);
- for_statement->data.for_expr.name = token_buf(label);
for_statement->data.for_expr.is_inline = inline_token != nullptr;
return for_statement;
}
@@ -970,12 +967,11 @@ static AstNode *ast_parse_loop_statement(ParseContext *pc) {
AstNode *while_statement = ast_parse_while_statement(pc);
if (while_statement != nullptr) {
assert(while_statement->type == NodeTypeWhileExpr);
- while_statement->data.while_expr.name = token_buf(label);
while_statement->data.while_expr.is_inline = inline_token != nullptr;
return while_statement;
}
- if (first != nullptr)
+ if (inline_token != nullptr)
ast_invalid_token_error(pc, peek_token(pc));
return nullptr;
}
@@ -1117,7 +1113,7 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc) {
// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?
static AstNode *ast_parse_compare_expr(ParseContext *pc) {
- return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_compare_op, ast_parse_bitwise_expr);
+ return ast_parse_bin_op_expr(pc, BinOpChainOnce, ast_parse_compare_op, ast_parse_bitwise_expr);
}
// BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*
@@ -1162,10 +1158,6 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) {
// / Block
// / CurlySuffixExpr
static AstNode *ast_parse_primary_expr(ParseContext *pc) {
- AstNode *enum_lit = ast_parse_enum_lit(pc);
- if (enum_lit != nullptr)
- return enum_lit;
-
AstNode *asm_expr = ast_parse_asm_expr(pc);
if (asm_expr != nullptr)
return asm_expr;
@@ -1246,11 +1238,8 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) {
}
AstNode *block = ast_parse_block(pc);
- if (block != nullptr) {
- assert(block->type == NodeTypeBlock);
- block->data.block.name = token_buf(label);
+ if (block != nullptr)
return block;
- }
AstNode *curly_suffix = ast_parse_curly_suffix_expr(pc);
if (curly_suffix != nullptr)
@@ -1503,6 +1492,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
// <- BUILTINIDENTIFIER FnCallArguments
// / CHAR_LITERAL
// / ContainerDecl
+// / DOT IDENTIFIER
// / ErrorSetDecl
// / FLOAT
// / FnProto
@@ -1563,6 +1553,10 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
if (container_decl != nullptr)
return container_decl;
+ AstNode *enum_lit = ast_parse_enum_lit(pc);
+ if (enum_lit != nullptr)
+ return enum_lit;
+
AstNode *error_set_decl = ast_parse_error_set_decl(pc);
if (error_set_decl != nullptr)
return error_set_decl;
@@ -1672,32 +1666,26 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
// ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto
static AstNode *ast_parse_container_decl(ParseContext *pc) {
- Token *extern_token = eat_token_if(pc, TokenIdKeywordExtern);
- if (extern_token != nullptr) {
- AstNode *res = ast_parse_container_decl_auto(pc);
- if (res == nullptr) {
- put_back_token(pc);
- return nullptr;
- }
+ Token *layout_token = eat_token_if(pc, TokenIdKeywordExtern);
+ if (layout_token == nullptr)
+ layout_token = eat_token_if(pc, TokenIdKeywordPacked);
- assert(res->type == NodeTypeContainerDecl);
- res->line = extern_token->start_line;
- res->column = extern_token->start_column;
- res->data.container_decl.layout = ContainerLayoutExtern;
- return res;
+ AstNode *res = ast_parse_container_decl_auto(pc);
+ if (res == nullptr) {
+ if (layout_token != nullptr)
+ put_back_token(pc);
+ return nullptr;
}
- Token *packed_token = eat_token_if(pc, TokenIdKeywordPacked);
- if (packed_token != nullptr) {
- AstNode *res = ast_expect(pc, ast_parse_container_decl_auto);
- assert(res->type == NodeTypeContainerDecl);
- res->line = packed_token->start_line;
- res->column = packed_token->start_column;
- res->data.container_decl.layout = ContainerLayoutPacked;
- return res;
+ assert(res->type == NodeTypeContainerDecl);
+ if (layout_token != nullptr) {
+ res->line = layout_token->start_line;
+ res->column = layout_token->start_column;
+ res->data.container_decl.layout = layout_token->id == TokenIdKeywordExtern
+ ? ContainerLayoutExtern
+ : ContainerLayoutPacked;
}
-
- return ast_parse_container_decl_auto(pc);
+ return res;
}
// ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE
@@ -1971,7 +1959,14 @@ static AstNode *ast_parse_field_init(ParseContext *pc) {
return nullptr;
Token *name = expect_token(pc, TokenIdSymbol);
- expect_token(pc, TokenIdEq);
+ if (eat_token_if(pc, TokenIdEq) == nullptr) {
+ // Because ".Name" can also be intepreted as an enum literal, we should put back
+ // those two tokens again so that the parser can try to parse them as the enum
+ // literal later.
+ put_back_token(pc);
+ put_back_token(pc);
+ return nullptr;
+ }
AstNode *expr = ast_expect(pc, ast_parse_expr);
AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first);
@@ -2750,12 +2745,19 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) {
}
// ContainerDeclType
-// <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)?
+// <- KEYWORD_struct
+// / KEYWORD_enum (LPAREN Expr RPAREN)?
// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
Token *first = eat_token_if(pc, TokenIdKeywordStruct);
- if (first == nullptr)
- first = eat_token_if(pc, TokenIdKeywordEnum);
+ if (first != nullptr) {
+ AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
+ res->data.container_decl.init_arg_expr = nullptr;
+ res->data.container_decl.kind = ContainerKindStruct;
+ return res;
+ }
+
+ first = eat_token_if(pc, TokenIdKeywordEnum);
if (first != nullptr) {
AstNode *init_arg_expr = nullptr;
if (eat_token_if(pc, TokenIdLParen) != nullptr) {
@@ -2764,9 +2766,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
}
AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
res->data.container_decl.init_arg_expr = init_arg_expr;
- res->data.container_decl.kind = first->id == TokenIdKeywordStruct
- ? ContainerKindStruct
- : ContainerKindEnum;
+ res->data.container_decl.kind = ContainerKindEnum;
return res;
}
diff --git a/src/target.cpp b/src/target.cpp
index dda8188765..1954fd7e2e 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -894,10 +894,25 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case CIntTypeCount:
zig_unreachable();
}
+ case OsIOS:
+ switch (id) {
+ case CIntTypeShort:
+ case CIntTypeUShort:
+ return 16;
+ case CIntTypeInt:
+ case CIntTypeUInt:
+ return 32;
+ case CIntTypeLong:
+ case CIntTypeULong:
+ case CIntTypeLongLong:
+ case CIntTypeULongLong:
+ return 64;
+ case CIntTypeCount:
+ zig_unreachable();
+ }
case OsAnanas:
case OsCloudABI:
case OsDragonFly:
- case OsIOS:
case OsKFreeBSD:
case OsLv2:
case OsSolaris:
@@ -950,6 +965,8 @@ const char *target_exe_file_ext(const ZigTarget *target) {
return ".exe";
} else if (target->os == OsUefi) {
return ".efi";
+ } else if (target_is_wasm(target)) {
+ return ".wasm";
} else {
return "";
}
@@ -1350,6 +1367,14 @@ bool target_is_musl(const ZigTarget *target) {
return target->os == OsLinux && target_abi_is_musl(target->abi);
}
+bool target_is_wasm(const ZigTarget *target) {
+ return target->arch == ZigLLVM_wasm32 || target->arch == ZigLLVM_wasm64;
+}
+
+bool target_is_single_threaded(const ZigTarget *target) {
+ return target_is_wasm(target);
+}
+
ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
switch (os) {
case OsFreestanding:
diff --git a/src/target.hpp b/src/target.hpp
index 4a0264c2b1..fd5c7471c3 100644
--- a/src/target.hpp
+++ b/src/target.hpp
@@ -170,6 +170,8 @@ bool target_abi_is_gnu(ZigLLVM_EnvironmentType abi);
bool target_abi_is_musl(ZigLLVM_EnvironmentType abi);
bool target_is_glibc(const ZigTarget *target);
bool target_is_musl(const ZigTarget *target);
+bool target_is_wasm(const ZigTarget *target);
+bool target_is_single_threaded(const ZigTarget *target);
uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
index 8abd66c0ff..c3c715cb47 100644
--- a/src/translate_c.cpp
+++ b/src/translate_c.cpp
@@ -76,10 +76,9 @@ struct TransScopeWhile {
};
struct Context {
- ZigList<ErrorMsg *> *errors;
+ AstNode *root;
VisibMod visib_mod;
bool want_export;
- AstNode *root;
HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
@@ -112,19 +111,39 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren
static TransScopeBlock *trans_scope_block_find(TransScope *scope);
-static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl);
-static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl);
-static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl);
+static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl);
+static AstNode *resolve_enum_decl(Context *c, const ZigClangEnumDecl *enum_decl);
+static AstNode *resolve_typedef_decl(Context *c, const ZigClangTypedefNameDecl *typedef_decl);
-static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
+static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *stmt,
ResultUsed result_used, TransLRValue lrval,
AstNode **out_node, TransScope **out_child_scope,
TransScope **out_node_scope);
-static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node);
-static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
-static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc);
-static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
-static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc);
+static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt *stmt, AstNode **out_node);
+static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr, TransLRValue lrval);
+static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc);
+static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceLocation source_loc);
+static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope,
+ const ZigClangExpr *expr, TransLRValue lrval);
+static AstNode *trans_ap_value(Context *c, const ZigClangAPValue *ap_value, ZigClangQualType qt,
+ ZigClangSourceLocation source_loc);
+static bool c_is_unsigned_integer(Context *c, ZigClangQualType qt);
+
+static const ZigClangAPSInt *bitcast(const llvm::APSInt *src) {
+ return reinterpret_cast<const ZigClangAPSInt *>(src);
+}
+
+static const ZigClangAPValue *bitcast(const clang::APValue *src) {
+ return reinterpret_cast<const ZigClangAPValue *>(src);
+}
+
+static const ZigClangStmt *bitcast(const clang::Stmt *src) {
+ return reinterpret_cast<const ZigClangStmt *>(src);
+}
+
+static const ZigClangExpr *bitcast(const clang::Expr *src) {
+ return reinterpret_cast<const ZigClangExpr *>(src);
+}
static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
ZigClangSourceLocation dest;
@@ -136,14 +155,14 @@ static ZigClangQualType bitcast(clang::QualType src) {
memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));
return dest;
}
-static clang::QualType bitcast(ZigClangQualType src) {
- clang::QualType dest;
- memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));
- return dest;
-}
+//static clang::QualType bitcast(ZigClangQualType src) {
+// clang::QualType dest;
+// memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));
+// return dest;
+//}
ATTRIBUTE_PRINTF(3, 4)
-static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) {
+static void emit_warning(Context *c, ZigClangSourceLocation sl, const char *format, ...) {
if (!c->warnings_on) {
return;
}
@@ -153,7 +172,6 @@ static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, cons
Buf *msg = buf_vprintf(format, ap);
va_end(ap);
- ZigClangSourceLocation sl = bitcast(clang_sl);
const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,
ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));
Buf *path;
@@ -489,107 +507,99 @@ static Buf *string_ref_to_buf(llvm::StringRef string_ref) {
return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
}
-static const char *decl_name(const clang::Decl *decl) {
- const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl);
- return (const char *)named_decl->getName().bytes_begin();
-}
-
-static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
+static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_int) {
AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
node->data.int_literal.bigint = allocate<BigInt>(1);
- bool is_negative = aps_int.isSigned() && aps_int.isNegative();
+ bool is_negative = ZigClangAPSInt_isSigned(aps_int) && ZigClangAPSInt_isNegative(aps_int);
if (!is_negative) {
- bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);
+ bigint_init_data(node->data.int_literal.bigint,
+ ZigClangAPSInt_getRawData(aps_int),
+ ZigClangAPSInt_getNumWords(aps_int),
+ false);
return node;
}
- llvm::APSInt negated = -aps_int;
- bigint_init_data(node->data.int_literal.bigint, negated.getRawData(), negated.getNumWords(), true);
+ const ZigClangAPSInt *negated = ZigClangAPSInt_negate(aps_int);
+ bigint_init_data(node->data.int_literal.bigint, ZigClangAPSInt_getRawData(negated),
+ ZigClangAPSInt_getNumWords(negated), true);
+ ZigClangAPSInt_free(negated);
return node;
+}
+static AstNode *trans_create_node_apfloat(Context *c, const llvm::APFloat &ap_float) {
+ uint8_t buf[128];
+ size_t written = ap_float.convertToHexString((char *)buf, 0, false,
+ llvm::APFloat::rmNearestTiesToEven);
+ AstNode *node = trans_create_node(c, NodeTypeFloatLiteral);
+ node->data.float_literal.bigfloat = allocate<BigFloat>(1);
+ if (bigfloat_init_buf(node->data.float_literal.bigfloat, buf, written)) {
+ node->data.float_literal.overflow = true;
+ }
+ return node;
}
-static const clang::Type *qual_type_canon(clang::QualType qt) {
- return qt.getCanonicalType().getTypePtr();
+static const ZigClangType *qual_type_canon(ZigClangQualType qt) {
+ ZigClangQualType canon = ZigClangQualType_getCanonicalType(qt);
+ return ZigClangQualType_getTypePtr(canon);
}
-static clang::QualType get_expr_qual_type(Context *c, const clang::Expr *expr) {
+static ZigClangQualType get_expr_qual_type(Context *c, const ZigClangExpr *expr) {
// String literals in C are `char *` but they should really be `const char *`.
- if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
- const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
- if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) {
- const clang::Expr *sub_expr = cast_expr->getSubExpr();
- if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) {
- clang::QualType array_qt = sub_expr->getType();
- const clang::ArrayType *array_type = static_cast<const clang::ArrayType *>(array_qt.getTypePtr());
- clang::QualType pointee_qt = array_type->getElementType();
- pointee_qt.addConst();
- return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt)));
+ if (ZigClangExpr_getStmtClass(expr) == ZigClangStmt_ImplicitCastExprClass) {
+ const clang::ImplicitCastExpr *cast_expr = reinterpret_cast<const clang::ImplicitCastExpr *>(expr);
+ if ((ZigClangCK)cast_expr->getCastKind() == ZigClangCK_ArrayToPointerDecay) {
+ const ZigClangExpr *sub_expr = bitcast(cast_expr->getSubExpr());
+ if (ZigClangExpr_getStmtClass(sub_expr) == ZigClangStmt_StringLiteralClass) {
+ ZigClangQualType array_qt = ZigClangExpr_getType(sub_expr);
+ const clang::ArrayType *array_type = reinterpret_cast<const clang::ArrayType *>(
+ ZigClangQualType_getTypePtr(array_qt));
+ ZigClangQualType pointee_qt = bitcast(array_type->getElementType());
+ ZigClangQualType_addConst(&pointee_qt);
+ return ZigClangASTContext_getPointerType(c->ctx, pointee_qt);
}
}
}
- return expr->getType();
+ return ZigClangExpr_getType(expr);
}
-static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) {
- if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
- const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
- return get_expr_qual_type(c, cast_expr->getSubExpr());
+static ZigClangQualType get_expr_qual_type_before_implicit_cast(Context *c, const ZigClangExpr *expr) {
+ if (ZigClangExpr_getStmtClass(expr) == ZigClangStmt_ImplicitCastExprClass) {
+ const clang::ImplicitCastExpr *cast_expr = reinterpret_cast<const clang::ImplicitCastExpr *>(expr);
+ return get_expr_qual_type(c, bitcast(cast_expr->getSubExpr()));
}
- return expr->getType();
+ return ZigClangExpr_getType(expr);
}
-static AstNode *get_expr_type(Context *c, const clang::Expr *expr) {
- return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getBeginLoc());
-}
-
-static bool qual_types_equal(clang::QualType t1, clang::QualType t2) {
- if (t1.isConstQualified() != t2.isConstQualified()) {
- return false;
- }
- if (t1.isVolatileQualified() != t2.isVolatileQualified()) {
- return false;
- }
- if (t1.isRestrictQualified() != t2.isRestrictQualified()) {
- return false;
- }
- return t1.getTypePtr() == t2.getTypePtr();
+static AstNode *get_expr_type(Context *c, const ZigClangExpr *expr) {
+ return trans_qual_type(c, get_expr_qual_type(c, expr), ZigClangExpr_getBeginLoc(expr));
}
static bool is_c_void_type(AstNode *node) {
return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
}
-static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) {
- clang::QualType t1 = get_expr_qual_type(c, expr1);
- clang::QualType t2 = get_expr_qual_type(c, expr2);
-
- return qual_types_equal(t1, t2);
+static bool qual_type_is_ptr(ZigClangQualType qt) {
+ const ZigClangType *ty = qual_type_canon(qt);
+ return ZigClangType_getTypeClass(ty) == ZigClangType_Pointer;
}
-static bool qual_type_is_ptr(clang::QualType qt) {
- const clang::Type *ty = qual_type_canon(qt);
- return ty->getTypeClass() == clang::Type::Pointer;
-}
-
-static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) {
- const clang::Type *ty = qual_type_canon(qt);
+static const clang::FunctionProtoType *qual_type_get_fn_proto(ZigClangQualType qt, bool *is_ptr) {
+ const ZigClangType *ty = qual_type_canon(qt);
*is_ptr = false;
- if (ty->getTypeClass() == clang::Type::Pointer) {
+ if (ZigClangType_getTypeClass(ty) == ZigClangType_Pointer) {
*is_ptr = true;
- const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
- clang::QualType child_qt = pointer_ty->getPointeeType();
- ty = child_qt.getTypePtr();
+ ZigClangQualType child_qt = ZigClangType_getPointeeType(ty);
+ ty = ZigClangQualType_getTypePtr(child_qt);
}
- if (ty->getTypeClass() == clang::Type::FunctionProto) {
- return static_cast<const clang::FunctionProtoType*>(ty);
+ if (ZigClangType_getTypeClass(ty) == ZigClangType_FunctionProto) {
+ return reinterpret_cast<const clang::FunctionProtoType*>(ty);
}
return nullptr;
}
-static bool qual_type_is_fn_ptr(clang::QualType qt) {
+static bool qual_type_is_fn_ptr(ZigClangQualType qt) {
bool is_ptr;
if (qual_type_get_fn_proto(qt, &is_ptr)) {
return is_ptr;
@@ -598,31 +608,31 @@ static bool qual_type_is_fn_ptr(clang::QualType qt) {
return false;
}
-static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) {
- const clang::Type *ty = qt.getTypePtr();
- switch (ty->getTypeClass()) {
- case clang::Type::Builtin:
+static uint32_t qual_type_int_bit_width(Context *c, const ZigClangQualType qt, ZigClangSourceLocation source_loc) {
+ const ZigClangType *ty = ZigClangQualType_getTypePtr(qt);
+ switch (ZigClangType_getTypeClass(ty)) {
+ case ZigClangType_Builtin:
{
- const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
- switch (builtin_ty->getKind()) {
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::SChar:
+ const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty);
+ switch (ZigClangBuiltinType_getKind(builtin_ty)) {
+ case ZigClangBuiltinTypeChar_U:
+ case ZigClangBuiltinTypeUChar:
+ case ZigClangBuiltinTypeChar_S:
+ case ZigClangBuiltinTypeSChar:
return 8;
- case clang::BuiltinType::UInt128:
- case clang::BuiltinType::Int128:
+ case ZigClangBuiltinTypeUInt128:
+ case ZigClangBuiltinTypeInt128:
return 128;
default:
return 0;
}
zig_unreachable();
}
- case clang::Type::Typedef:
+ case ZigClangType_Typedef:
{
- const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
- const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
- const char *type_name = decl_name(typedef_decl);
+ const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
+ const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
+ const char *type_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl);
if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
return 8;
} else if (strcmp(type_name, "uint16_t") == 0 || strcmp(type_name, "int16_t") == 0) {
@@ -642,8 +652,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, c
}
-static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,
- const clang::SourceLocation &source_loc)
+static AstNode *qual_type_to_log2_int_ref(Context *c, const ZigClangQualType qt,
+ ZigClangSourceLocation source_loc)
{
uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
if (int_bit_width != 0) {
@@ -675,37 +685,76 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,
return log2int_fn_call;
}
-static bool qual_type_child_is_fn_proto(const clang::QualType &qt) {
- if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) {
- const clang::ParenType *paren_type = static_cast<const clang::ParenType *>(qt.getTypePtr());
+static bool qual_type_child_is_fn_proto(ZigClangQualType qt) {
+ const ZigClangType *ty = ZigClangQualType_getTypePtr(qt);
+ if (ZigClangType_getTypeClass(ty) == ZigClangType_Paren) {
+ const clang::ParenType *paren_type = reinterpret_cast<const clang::ParenType *>(ty);
if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) {
return true;
}
- } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) {
- const clang::AttributedType *attr_type = static_cast<const clang::AttributedType *>(qt.getTypePtr());
- return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
+ } else if (ZigClangType_getTypeClass(ty) == ZigClangType_Attributed) {
+ const clang::AttributedType *attr_type = reinterpret_cast<const clang::AttributedType *>(ty);
+ return qual_type_child_is_fn_proto(bitcast(attr_type->getEquivalentType()));
}
return false;
}
-static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type,
- clang::QualType src_type, AstNode *expr)
+static AstNode* trans_c_ptr_cast(Context *c, ZigClangSourceLocation source_location, ZigClangQualType dest_type,
+ ZigClangQualType src_type, AstNode *expr)
+{
+ const ZigClangType *ty = ZigClangQualType_getTypePtr(dest_type);
+ const ZigClangQualType child_type = ZigClangType_getPointeeType(ty);
+
+ AstNode *dest_type_node = trans_type(c, ty, source_location);
+ AstNode *child_type_node = trans_qual_type(c, child_type, source_location);
+
+ // Implicit downcasting from higher to lower alignment values is forbidden,
+ // use @alignCast to side-step this problem
+ AstNode *ptrcast_node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
+ ptrcast_node->data.fn_call_expr.params.append(dest_type_node);
+
+ if (ZigClangType_isVoidType(qual_type_canon(child_type))) {
+ // void has 1-byte alignment
+ ptrcast_node->data.fn_call_expr.params.append(expr);
+ } else {
+ AstNode *alignof_node = trans_create_node_builtin_fn_call_str(c, "alignOf");
+ alignof_node->data.fn_call_expr.params.append(child_type_node);
+ AstNode *aligncast_node = trans_create_node_builtin_fn_call_str(c, "alignCast");
+ aligncast_node->data.fn_call_expr.params.append(alignof_node);
+ aligncast_node->data.fn_call_expr.params.append(expr);
+
+ ptrcast_node->data.fn_call_expr.params.append(aligncast_node);
+ }
+
+ return ptrcast_node;
+}
+
+static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location, ZigClangQualType dest_type,
+ ZigClangQualType src_type, AstNode *expr)
{
// The only way void pointer casts are valid C code, is if
// the value of the expression is ignored. We therefore just
// return the expr, and let the system that ignores values
// translate this correctly.
- if (qual_type_canon(dest_type)->isVoidType()) {
+ if (ZigClangType_isVoidType(qual_type_canon(dest_type))) {
return expr;
}
- if (qual_types_equal(dest_type, src_type)) {
+ if (ZigClangQualType_eq(dest_type, src_type)) {
return expr;
}
if (qual_type_is_ptr(dest_type) && qual_type_is_ptr(src_type)) {
- AstNode *ptr_cast_node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
- ptr_cast_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location));
- ptr_cast_node->data.fn_call_expr.params.append(expr);
- return ptr_cast_node;
+ return trans_c_ptr_cast(c, source_location, dest_type, src_type, expr);
+ }
+ if (c_is_unsigned_integer(c, dest_type) && qual_type_is_ptr(src_type)) {
+ AstNode *addr_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
+ addr_node->data.fn_call_expr.params.append(expr);
+ return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), addr_node);
+ }
+ if (c_is_unsigned_integer(c, src_type) && qual_type_is_ptr(dest_type)) {
+ AstNode *ptr_node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
+ ptr_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location));
+ ptr_node->data.fn_call_expr.params.append(expr);
+ return ptr_node;
}
// TODO: maybe widen to increase size
// TODO: maybe bitcast to change sign
@@ -713,72 +762,72 @@ static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_loc
return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);
}
-static bool c_is_signed_integer(Context *c, clang::QualType qt) {
- const clang::Type *c_type = qual_type_canon(qt);
- if (c_type->getTypeClass() != clang::Type::Builtin)
+static bool c_is_signed_integer(Context *c, ZigClangQualType qt) {
+ const ZigClangType *c_type = qual_type_canon(qt);
+ if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
return false;
- const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);
- switch (builtin_ty->getKind()) {
- case clang::BuiltinType::SChar:
- case clang::BuiltinType::Short:
- case clang::BuiltinType::Int:
- case clang::BuiltinType::Long:
- case clang::BuiltinType::LongLong:
- case clang::BuiltinType::Int128:
- case clang::BuiltinType::WChar_S:
+ const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
+ switch (ZigClangBuiltinType_getKind(builtin_ty)) {
+ case ZigClangBuiltinTypeSChar:
+ case ZigClangBuiltinTypeShort:
+ case ZigClangBuiltinTypeInt:
+ case ZigClangBuiltinTypeLong:
+ case ZigClangBuiltinTypeLongLong:
+ case ZigClangBuiltinTypeInt128:
+ case ZigClangBuiltinTypeWChar_S:
return true;
default:
return false;
}
}
-static bool c_is_unsigned_integer(Context *c, clang::QualType qt) {
- const clang::Type *c_type = qual_type_canon(qt);
- if (c_type->getTypeClass() != clang::Type::Builtin)
+static bool c_is_unsigned_integer(Context *c, ZigClangQualType qt) {
+ const ZigClangType *c_type = qual_type_canon(qt);
+ if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
return false;
- const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);
- switch (builtin_ty->getKind()) {
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::UShort:
- case clang::BuiltinType::UInt:
- case clang::BuiltinType::ULong:
- case clang::BuiltinType::ULongLong:
- case clang::BuiltinType::UInt128:
- case clang::BuiltinType::WChar_U:
+ const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
+ switch (ZigClangBuiltinType_getKind(builtin_ty)) {
+ case ZigClangBuiltinTypeChar_U:
+ case ZigClangBuiltinTypeUChar:
+ case ZigClangBuiltinTypeChar_S:
+ case ZigClangBuiltinTypeUShort:
+ case ZigClangBuiltinTypeUInt:
+ case ZigClangBuiltinTypeULong:
+ case ZigClangBuiltinTypeULongLong:
+ case ZigClangBuiltinTypeUInt128:
+ case ZigClangBuiltinTypeWChar_U:
return true;
default:
return false;
}
}
-static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) {
- const clang::Type *c_type = qual_type_canon(qt);
- if (c_type->getTypeClass() != clang::Type::Builtin)
+static bool c_is_builtin_type(Context *c, ZigClangQualType qt, ZigClangBuiltinTypeKind kind) {
+ const ZigClangType *c_type = qual_type_canon(qt);
+ if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
return false;
- const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);
- return builtin_ty->getKind() == kind;
+ const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
+ return ZigClangBuiltinType_getKind(builtin_ty) == kind;
}
-static bool c_is_float(Context *c, clang::QualType qt) {
- const clang::Type *c_type = qt.getTypePtr();
- if (c_type->getTypeClass() != clang::Type::Builtin)
+static bool c_is_float(Context *c, ZigClangQualType qt) {
+ const ZigClangType *c_type = ZigClangQualType_getTypePtr(qt);
+ if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
return false;
- const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);
- switch (builtin_ty->getKind()) {
- case clang::BuiltinType::Half:
- case clang::BuiltinType::Float:
- case clang::BuiltinType::Double:
- case clang::BuiltinType::Float128:
- case clang::BuiltinType::LongDouble:
+ const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
+ switch (ZigClangBuiltinType_getKind(builtin_ty)) {
+ case ZigClangBuiltinTypeHalf:
+ case ZigClangBuiltinTypeFloat:
+ case ZigClangBuiltinTypeDouble:
+ case ZigClangBuiltinTypeFloat128:
+ case ZigClangBuiltinTypeLongDouble:
return true;
default:
return false;
}
}
-static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {
+static bool qual_type_has_wrapping_overflow(Context *c, ZigClangQualType qt) {
if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
// float and signed integer overflow is undefined behavior.
return false;
@@ -788,181 +837,182 @@ static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {
}
}
-static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
- switch (ty->getTypeClass()) {
- case clang::Type::Builtin: {
- const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
- return builtin_ty->getKind() == clang::BuiltinType::Void;
+static bool type_is_opaque(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
+ switch (ZigClangType_getTypeClass(ty)) {
+ case ZigClangType_Builtin: {
+ const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty);
+ return ZigClangBuiltinType_getKind(builtin_ty) == ZigClangBuiltinTypeVoid;
}
- case clang::Type::Record: {
- const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);
+ case ZigClangType_Record: {
+ const clang::RecordType *record_ty = reinterpret_cast<const clang::RecordType*>(ty);
return record_ty->getDecl()->getDefinition() == nullptr;
}
- case clang::Type::Elaborated: {
- const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
- return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);
+ case ZigClangType_Elaborated: {
+ const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty);
+ ZigClangQualType qt = bitcast(elaborated_ty->getNamedType());
+ return type_is_opaque(c, ZigClangQualType_getTypePtr(qt), source_loc);
}
- case clang::Type::Typedef: {
- const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
- const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
- return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);
+ case ZigClangType_Typedef: {
+ const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
+ const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
+ ZigClangQualType underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
+ return type_is_opaque(c, ZigClangQualType_getTypePtr(underlying_type), source_loc);
}
default:
return false;
}
}
-static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
- switch (ty->getTypeClass()) {
- case clang::Type::Builtin:
+static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
+ switch (ZigClangType_getTypeClass(ty)) {
+ case ZigClangType_Builtin:
{
- const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
- switch (builtin_ty->getKind()) {
- case clang::BuiltinType::Void:
+ const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType *>(ty);
+ switch (ZigClangBuiltinType_getKind(builtin_ty)) {
+ case ZigClangBuiltinTypeVoid:
return trans_create_node_symbol_str(c, "c_void");
- case clang::BuiltinType::Bool:
+ case ZigClangBuiltinTypeBool:
return trans_create_node_symbol_str(c, "bool");
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::Char8:
+ case ZigClangBuiltinTypeChar_U:
+ case ZigClangBuiltinTypeUChar:
+ case ZigClangBuiltinTypeChar_S:
+ case ZigClangBuiltinTypeChar8:
return trans_create_node_symbol_str(c, "u8");
- case clang::BuiltinType::SChar:
+ case ZigClangBuiltinTypeSChar:
return trans_create_node_symbol_str(c, "i8");
- case clang::BuiltinType::UShort:
+ case ZigClangBuiltinTypeUShort:
return trans_create_node_symbol_str(c, "c_ushort");
- case clang::BuiltinType::UInt:
+ case ZigClangBuiltinTypeUInt:
return trans_create_node_symbol_str(c, "c_uint");
- case clang::BuiltinType::ULong:
+ case ZigClangBuiltinTypeULong:
return trans_create_node_symbol_str(c, "c_ulong");
- case clang::BuiltinType::ULongLong:
+ case ZigClangBuiltinTypeULongLong:
return trans_create_node_symbol_str(c, "c_ulonglong");
- case clang::BuiltinType::Short:
+ case ZigClangBuiltinTypeShort:
return trans_create_node_symbol_str(c, "c_short");
- case clang::BuiltinType::Int:
+ case ZigClangBuiltinTypeInt:
return trans_create_node_symbol_str(c, "c_int");
- case clang::BuiltinType::Long:
+ case ZigClangBuiltinTypeLong:
return trans_create_node_symbol_str(c, "c_long");
- case clang::BuiltinType::LongLong:
+ case ZigClangBuiltinTypeLongLong:
return trans_create_node_symbol_str(c, "c_longlong");
- case clang::BuiltinType::UInt128:
+ case ZigClangBuiltinTypeUInt128:
return trans_create_node_symbol_str(c, "u128");
- case clang::BuiltinType::Int128:
+ case ZigClangBuiltinTypeInt128:
return trans_create_node_symbol_str(c, "i128");
- case clang::BuiltinType::Float:
+ case ZigClangBuiltinTypeFloat:
return trans_create_node_symbol_str(c, "f32");
- case clang::BuiltinType::Double:
+ case ZigClangBuiltinTypeDouble:
return trans_create_node_symbol_str(c, "f64");
- case clang::BuiltinType::Float128:
+ case ZigClangBuiltinTypeFloat128:
return trans_create_node_symbol_str(c, "f128");
- case clang::BuiltinType::Float16:
+ case ZigClangBuiltinTypeFloat16:
return trans_create_node_symbol_str(c, "f16");
- case clang::BuiltinType::LongDouble:
+ case ZigClangBuiltinTypeLongDouble:
return trans_create_node_symbol_str(c, "c_longdouble");
- case clang::BuiltinType::WChar_U:
- case clang::BuiltinType::Char16:
- case clang::BuiltinType::Char32:
- case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Half:
- case clang::BuiltinType::NullPtr:
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- case clang::BuiltinType::ObjCSel:
- case clang::BuiltinType::OMPArraySection:
- case clang::BuiltinType::Dependent:
- case clang::BuiltinType::Overload:
- case clang::BuiltinType::BoundMember:
- case clang::BuiltinType::PseudoObject:
- case clang::BuiltinType::UnknownAny:
- case clang::BuiltinType::BuiltinFn:
- case clang::BuiltinType::ARCUnbridgedCast:
- case clang::BuiltinType::ShortAccum:
- case clang::BuiltinType::Accum:
- case clang::BuiltinType::LongAccum:
- case clang::BuiltinType::UShortAccum:
- case clang::BuiltinType::UAccum:
- case clang::BuiltinType::ULongAccum:
-
- case clang::BuiltinType::OCLImage1dRO:
- case clang::BuiltinType::OCLImage1dArrayRO:
- case clang::BuiltinType::OCLImage1dBufferRO:
- case clang::BuiltinType::OCLImage2dRO:
- case clang::BuiltinType::OCLImage2dArrayRO:
- case clang::BuiltinType::OCLImage2dDepthRO:
- case clang::BuiltinType::OCLImage2dArrayDepthRO:
- case clang::BuiltinType::OCLImage2dMSAARO:
- case clang::BuiltinType::OCLImage2dArrayMSAARO:
- case clang::BuiltinType::OCLImage2dMSAADepthRO:
- case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
- case clang::BuiltinType::OCLImage3dRO:
- case clang::BuiltinType::OCLImage1dWO:
- case clang::BuiltinType::OCLImage1dArrayWO:
- case clang::BuiltinType::OCLImage1dBufferWO:
- case clang::BuiltinType::OCLImage2dWO:
- case clang::BuiltinType::OCLImage2dArrayWO:
- case clang::BuiltinType::OCLImage2dDepthWO:
- case clang::BuiltinType::OCLImage2dArrayDepthWO:
- case clang::BuiltinType::OCLImage2dMSAAWO:
- case clang::BuiltinType::OCLImage2dArrayMSAAWO:
- case clang::BuiltinType::OCLImage2dMSAADepthWO:
- case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
- case clang::BuiltinType::OCLImage3dWO:
- case clang::BuiltinType::OCLImage1dRW:
- case clang::BuiltinType::OCLImage1dArrayRW:
- case clang::BuiltinType::OCLImage1dBufferRW:
- case clang::BuiltinType::OCLImage2dRW:
- case clang::BuiltinType::OCLImage2dArrayRW:
- case clang::BuiltinType::OCLImage2dDepthRW:
- case clang::BuiltinType::OCLImage2dArrayDepthRW:
- case clang::BuiltinType::OCLImage2dMSAARW:
- case clang::BuiltinType::OCLImage2dArrayMSAARW:
- case clang::BuiltinType::OCLImage2dMSAADepthRW:
- case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
- case clang::BuiltinType::OCLImage3dRW:
- case clang::BuiltinType::OCLSampler:
- case clang::BuiltinType::OCLEvent:
- case clang::BuiltinType::OCLClkEvent:
- case clang::BuiltinType::OCLQueue:
- case clang::BuiltinType::OCLReserveID:
- case clang::BuiltinType::ShortFract:
- case clang::BuiltinType::Fract:
- case clang::BuiltinType::LongFract:
- case clang::BuiltinType::UShortFract:
- case clang::BuiltinType::UFract:
- case clang::BuiltinType::ULongFract:
- case clang::BuiltinType::SatShortAccum:
- case clang::BuiltinType::SatAccum:
- case clang::BuiltinType::SatLongAccum:
- case clang::BuiltinType::SatUShortAccum:
- case clang::BuiltinType::SatUAccum:
- case clang::BuiltinType::SatULongAccum:
- case clang::BuiltinType::SatShortFract:
- case clang::BuiltinType::SatFract:
- case clang::BuiltinType::SatLongFract:
- case clang::BuiltinType::SatUShortFract:
- case clang::BuiltinType::SatUFract:
- case clang::BuiltinType::SatULongFract:
- case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
+ case ZigClangBuiltinTypeWChar_U:
+ case ZigClangBuiltinTypeChar16:
+ case ZigClangBuiltinTypeChar32:
+ case ZigClangBuiltinTypeWChar_S:
+ case ZigClangBuiltinTypeHalf:
+ case ZigClangBuiltinTypeNullPtr:
+ case ZigClangBuiltinTypeObjCId:
+ case ZigClangBuiltinTypeObjCClass:
+ case ZigClangBuiltinTypeObjCSel:
+ case ZigClangBuiltinTypeOMPArraySection:
+ case ZigClangBuiltinTypeDependent:
+ case ZigClangBuiltinTypeOverload:
+ case ZigClangBuiltinTypeBoundMember:
+ case ZigClangBuiltinTypePseudoObject:
+ case ZigClangBuiltinTypeUnknownAny:
+ case ZigClangBuiltinTypeBuiltinFn:
+ case ZigClangBuiltinTypeARCUnbridgedCast:
+ case ZigClangBuiltinTypeShortAccum:
+ case ZigClangBuiltinTypeAccum:
+ case ZigClangBuiltinTypeLongAccum:
+ case ZigClangBuiltinTypeUShortAccum:
+ case ZigClangBuiltinTypeUAccum:
+ case ZigClangBuiltinTypeULongAccum:
+
+ case ZigClangBuiltinTypeOCLImage1dRO:
+ case ZigClangBuiltinTypeOCLImage1dArrayRO:
+ case ZigClangBuiltinTypeOCLImage1dBufferRO:
+ case ZigClangBuiltinTypeOCLImage2dRO:
+ case ZigClangBuiltinTypeOCLImage2dArrayRO:
+ case ZigClangBuiltinTypeOCLImage2dDepthRO:
+ case ZigClangBuiltinTypeOCLImage2dArrayDepthRO:
+ case ZigClangBuiltinTypeOCLImage2dMSAARO:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAARO:
+ case ZigClangBuiltinTypeOCLImage2dMSAADepthRO:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO:
+ case ZigClangBuiltinTypeOCLImage3dRO:
+ case ZigClangBuiltinTypeOCLImage1dWO:
+ case ZigClangBuiltinTypeOCLImage1dArrayWO:
+ case ZigClangBuiltinTypeOCLImage1dBufferWO:
+ case ZigClangBuiltinTypeOCLImage2dWO:
+ case ZigClangBuiltinTypeOCLImage2dArrayWO:
+ case ZigClangBuiltinTypeOCLImage2dDepthWO:
+ case ZigClangBuiltinTypeOCLImage2dArrayDepthWO:
+ case ZigClangBuiltinTypeOCLImage2dMSAAWO:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAAWO:
+ case ZigClangBuiltinTypeOCLImage2dMSAADepthWO:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO:
+ case ZigClangBuiltinTypeOCLImage3dWO:
+ case ZigClangBuiltinTypeOCLImage1dRW:
+ case ZigClangBuiltinTypeOCLImage1dArrayRW:
+ case ZigClangBuiltinTypeOCLImage1dBufferRW:
+ case ZigClangBuiltinTypeOCLImage2dRW:
+ case ZigClangBuiltinTypeOCLImage2dArrayRW:
+ case ZigClangBuiltinTypeOCLImage2dDepthRW:
+ case ZigClangBuiltinTypeOCLImage2dArrayDepthRW:
+ case ZigClangBuiltinTypeOCLImage2dMSAARW:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAARW:
+ case ZigClangBuiltinTypeOCLImage2dMSAADepthRW:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW:
+ case ZigClangBuiltinTypeOCLImage3dRW:
+ case ZigClangBuiltinTypeOCLSampler:
+ case ZigClangBuiltinTypeOCLEvent:
+ case ZigClangBuiltinTypeOCLClkEvent:
+ case ZigClangBuiltinTypeOCLQueue:
+ case ZigClangBuiltinTypeOCLReserveID:
+ case ZigClangBuiltinTypeShortFract:
+ case ZigClangBuiltinTypeFract:
+ case ZigClangBuiltinTypeLongFract:
+ case ZigClangBuiltinTypeUShortFract:
+ case ZigClangBuiltinTypeUFract:
+ case ZigClangBuiltinTypeULongFract:
+ case ZigClangBuiltinTypeSatShortAccum:
+ case ZigClangBuiltinTypeSatAccum:
+ case ZigClangBuiltinTypeSatLongAccum:
+ case ZigClangBuiltinTypeSatUShortAccum:
+ case ZigClangBuiltinTypeSatUAccum:
+ case ZigClangBuiltinTypeSatULongAccum:
+ case ZigClangBuiltinTypeSatShortFract:
+ case ZigClangBuiltinTypeSatFract:
+ case ZigClangBuiltinTypeSatLongFract:
+ case ZigClangBuiltinTypeSatUShortFract:
+ case ZigClangBuiltinTypeSatUFract:
+ case ZigClangBuiltinTypeSatULongFract:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin:
emit_warning(c, source_loc, "unsupported builtin type");
return nullptr;
}
break;
}
- case clang::Type::Pointer:
+ case ZigClangType_Pointer:
{
- const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
- clang::QualType child_qt = pointer_ty->getPointeeType();
+ ZigClangQualType child_qt = ZigClangType_getPointeeType(ty);
AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
if (child_node == nullptr) {
emit_warning(c, source_loc, "pointer to unsupported type");
@@ -973,29 +1023,33 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
}
- if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
- AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
- child_qt.isVolatileQualified(), child_node, PtrLenSingle);
+ if (type_is_opaque(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
+ AstNode *pointer_node = trans_create_node_ptr_type(c,
+ ZigClangQualType_isConstQualified(child_qt),
+ ZigClangQualType_isVolatileQualified(child_qt),
+ child_node, PtrLenSingle);
return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
} else {
- return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
- child_qt.isVolatileQualified(), child_node, PtrLenC);
+ return trans_create_node_ptr_type(c,
+ ZigClangQualType_isConstQualified(child_qt),
+ ZigClangQualType_isVolatileQualified(child_qt),
+ child_node, PtrLenC);
}
}
- case clang::Type::Typedef:
+ case ZigClangType_Typedef:
{
- const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
- const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
+ const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
return resolve_typedef_decl(c, typedef_decl);
}
- case clang::Type::Elaborated:
+ case ZigClangType_Elaborated:
{
- const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
+ const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty);
switch (elaborated_ty->getKeyword()) {
case clang::ETK_Struct:
case clang::ETK_Enum:
case clang::ETK_Union:
- return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
+ return trans_qual_type(c, bitcast(elaborated_ty->getNamedType()), source_loc);
case clang::ETK_Interface:
case clang::ETK_Class:
case clang::ETK_Typename:
@@ -1004,81 +1058,81 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
return nullptr;
}
}
- case clang::Type::FunctionProto:
- case clang::Type::FunctionNoProto:
+ case ZigClangType_FunctionProto:
+ case ZigClangType_FunctionNoProto:
{
- const clang::FunctionType *fn_ty = static_cast<const clang::FunctionType*>(ty);
+ const ZigClangFunctionType *fn_ty = reinterpret_cast<const ZigClangFunctionType*>(ty);
AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
- switch (fn_ty->getCallConv()) {
- case clang::CC_C: // __attribute__((cdecl))
+ switch (ZigClangFunctionType_getCallConv(fn_ty)) {
+ case ZigClangCallingConv_C: // __attribute__((cdecl))
proto_node->data.fn_proto.cc = CallingConventionC;
proto_node->data.fn_proto.is_extern = true;
break;
- case clang::CC_X86StdCall: // __attribute__((stdcall))
+ case ZigClangCallingConv_X86StdCall: // __attribute__((stdcall))
proto_node->data.fn_proto.cc = CallingConventionStdcall;
break;
- case clang::CC_X86FastCall: // __attribute__((fastcall))
+ case ZigClangCallingConv_X86FastCall: // __attribute__((fastcall))
emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
return nullptr;
- case clang::CC_X86ThisCall: // __attribute__((thiscall))
+ case ZigClangCallingConv_X86ThisCall: // __attribute__((thiscall))
emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
return nullptr;
- case clang::CC_X86VectorCall: // __attribute__((vectorcall))
+ case ZigClangCallingConv_X86VectorCall: // __attribute__((vectorcall))
emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
return nullptr;
- case clang::CC_X86Pascal: // __attribute__((pascal))
+ case ZigClangCallingConv_X86Pascal: // __attribute__((pascal))
emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
return nullptr;
- case clang::CC_Win64: // __attribute__((ms_abi))
+ case ZigClangCallingConv_Win64: // __attribute__((ms_abi))
emit_warning(c, source_loc, "unsupported calling convention: win64");
return nullptr;
- case clang::CC_X86_64SysV: // __attribute__((sysv_abi))
+ case ZigClangCallingConv_X86_64SysV: // __attribute__((sysv_abi))
emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
return nullptr;
- case clang::CC_X86RegCall:
+ case ZigClangCallingConv_X86RegCall:
emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
return nullptr;
- case clang::CC_AAPCS: // __attribute__((pcs("aapcs")))
+ case ZigClangCallingConv_AAPCS: // __attribute__((pcs("aapcs")))
emit_warning(c, source_loc, "unsupported calling convention: aapcs");
return nullptr;
- case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
+ case ZigClangCallingConv_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
return nullptr;
- case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
+ case ZigClangCallingConv_IntelOclBicc: // __attribute__((intel_ocl_bicc))
emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
return nullptr;
- case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target
+ case ZigClangCallingConv_SpirFunction: // default for OpenCL functions on SPIR target
emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
return nullptr;
- case clang::CC_OpenCLKernel:
+ case ZigClangCallingConv_OpenCLKernel:
emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
return nullptr;
- case clang::CC_Swift:
+ case ZigClangCallingConv_Swift:
emit_warning(c, source_loc, "unsupported calling convention: Swift");
return nullptr;
- case clang::CC_PreserveMost:
+ case ZigClangCallingConv_PreserveMost:
emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
return nullptr;
- case clang::CC_PreserveAll:
+ case ZigClangCallingConv_PreserveAll:
emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
return nullptr;
- case clang::CC_AArch64VectorCall:
+ case ZigClangCallingConv_AArch64VectorCall:
emit_warning(c, source_loc, "unsupported calling convention: AArch64VectorCall");
return nullptr;
}
- if (fn_ty->getNoReturnAttr()) {
+ if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) {
proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
} else {
- proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_ty->getReturnType(),
- source_loc);
+ proto_node->data.fn_proto.return_type = trans_qual_type(c,
+ ZigClangFunctionType_getReturnType(fn_ty), source_loc);
if (proto_node->data.fn_proto.return_type == nullptr) {
emit_warning(c, source_loc, "unsupported function proto return type");
return nullptr;
}
// convert c_void to actual void (only for return type)
- // we do want to look at the AstNode instead of clang::QualType, because
+ // we do want to look at the AstNode instead of ZigClangQualType, because
// if they do something like:
// typedef Foo void;
// void foo(void) -> Foo;
@@ -1094,17 +1148,17 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
}
- if (ty->getTypeClass() == clang::Type::FunctionNoProto) {
+ if (ZigClangType_getTypeClass(ty) == ZigClangType_FunctionNoProto) {
return proto_node;
}
- const clang::FunctionProtoType *fn_proto_ty = static_cast<const clang::FunctionProtoType*>(ty);
+ const ZigClangFunctionProtoType *fn_proto_ty = reinterpret_cast<const ZigClangFunctionProtoType*>(ty);
- proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
- size_t param_count = fn_proto_ty->getNumParams();
+ proto_node->data.fn_proto.is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty);
+ size_t param_count = ZigClangFunctionProtoType_getNumParams(fn_proto_ty);
for (size_t i = 0; i < param_count; i += 1) {
- clang::QualType qt = fn_proto_ty->getParamType(i);
+ ZigClangQualType qt = ZigClangFunctionProtoType_getParamType(fn_proto_ty, i);
AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
if (param_type_node == nullptr) {
@@ -1118,7 +1172,7 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
if (param_name != nullptr) {
param_node->data.param_decl.name = buf_create_from_str(param_name);
}
- param_node->data.param_decl.is_noalias = qt.isRestrictQualified();
+ param_node->data.param_decl.is_noalias = ZigClangQualType_isRestrictQualified(qt);
param_node->data.param_decl.type = param_type_node;
proto_node->data.fn_proto.params.append(param_node);
}
@@ -1127,20 +1181,20 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
return proto_node;
}
- case clang::Type::Record:
+ case ZigClangType_Record:
{
- const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);
- return resolve_record_decl(c, record_ty->getDecl());
+ const ZigClangRecordType *record_ty = reinterpret_cast<const ZigClangRecordType*>(ty);
+ return resolve_record_decl(c, ZigClangRecordType_getDecl(record_ty));
}
- case clang::Type::Enum:
+ case ZigClangType_Enum:
{
- const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);
- return resolve_enum_decl(c, enum_ty->getDecl());
+ const ZigClangEnumType *enum_ty = reinterpret_cast<const ZigClangEnumType*>(ty);
+ return resolve_enum_decl(c, ZigClangEnumType_getDecl(enum_ty));
}
- case clang::Type::ConstantArray:
+ case ZigClangType_ConstantArray:
{
- const clang::ConstantArrayType *const_arr_ty = static_cast<const clang::ConstantArrayType *>(ty);
- AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
+ const clang::ConstantArrayType *const_arr_ty = reinterpret_cast<const clang::ConstantArrayType *>(ty);
+ AstNode *child_type_node = trans_qual_type(c, bitcast(const_arr_ty->getElementType()), source_loc);
if (child_type_node == nullptr) {
emit_warning(c, source_loc, "unresolved array element type");
return nullptr;
@@ -1149,83 +1203,87 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
AstNode *size_node = trans_create_node_unsigned(c, size);
return trans_create_node_array_type(c, size_node, child_type_node);
}
- case clang::Type::Paren:
+ case ZigClangType_Paren:
{
- const clang::ParenType *paren_ty = static_cast<const clang::ParenType *>(ty);
- return trans_qual_type(c, paren_ty->getInnerType(), source_loc);
+ const clang::ParenType *paren_ty = reinterpret_cast<const clang::ParenType *>(ty);
+ return trans_qual_type(c, bitcast(paren_ty->getInnerType()), source_loc);
}
- case clang::Type::Decayed:
+ case ZigClangType_Decayed:
{
- const clang::DecayedType *decayed_ty = static_cast<const clang::DecayedType *>(ty);
- return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);
+ const clang::DecayedType *decayed_ty = reinterpret_cast<const clang::DecayedType *>(ty);
+ return trans_qual_type(c, bitcast(decayed_ty->getDecayedType()), source_loc);
}
- case clang::Type::Attributed:
+ case ZigClangType_Attributed:
{
- const clang::AttributedType *attributed_ty = static_cast<const clang::AttributedType *>(ty);
- return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
+ const clang::AttributedType *attributed_ty = reinterpret_cast<const clang::AttributedType *>(ty);
+ return trans_qual_type(c, bitcast(attributed_ty->getEquivalentType()), source_loc);
}
- case clang::Type::IncompleteArray:
+ case ZigClangType_IncompleteArray:
{
- const clang::IncompleteArrayType *incomplete_array_ty = static_cast<const clang::IncompleteArrayType *>(ty);
- clang::QualType child_qt = incomplete_array_ty->getElementType();
+ const clang::IncompleteArrayType *incomplete_array_ty = reinterpret_cast<const clang::IncompleteArrayType *>(ty);
+ ZigClangQualType child_qt = bitcast(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_ptr_type(c, child_qt.isConstQualified(),
- child_qt.isVolatileQualified(), child_type_node, PtrLenC);
+ AstNode *pointer_node = trans_create_node_ptr_type(c,
+ ZigClangQualType_isConstQualified(child_qt),
+ ZigClangQualType_isVolatileQualified(child_qt),
+ child_type_node, PtrLenC);
return pointer_node;
}
- case clang::Type::BlockPointer:
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- case clang::Type::MemberPointer:
- case clang::Type::VariableArray:
- case clang::Type::DependentSizedArray:
- case clang::Type::DependentSizedExtVector:
- case clang::Type::Vector:
- case clang::Type::ExtVector:
- case clang::Type::UnresolvedUsing:
- case clang::Type::Adjusted:
- case clang::Type::TypeOfExpr:
- case clang::Type::TypeOf:
- case clang::Type::Decltype:
- case clang::Type::UnaryTransform:
- case clang::Type::TemplateTypeParm:
- case clang::Type::SubstTemplateTypeParm:
- case clang::Type::SubstTemplateTypeParmPack:
- case clang::Type::TemplateSpecialization:
- case clang::Type::Auto:
- case clang::Type::InjectedClassName:
- case clang::Type::DependentName:
- case clang::Type::DependentTemplateSpecialization:
- case clang::Type::PackExpansion:
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- case clang::Type::Complex:
- case clang::Type::ObjCObjectPointer:
- case clang::Type::Atomic:
- case clang::Type::Pipe:
- case clang::Type::ObjCTypeParam:
- case clang::Type::DeducedTemplateSpecialization:
- case clang::Type::DependentAddressSpace:
- case clang::Type::DependentVector:
- emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
+ case ZigClangType_BlockPointer:
+ case ZigClangType_LValueReference:
+ case ZigClangType_RValueReference:
+ case ZigClangType_MemberPointer:
+ case ZigClangType_VariableArray:
+ case ZigClangType_DependentSizedArray:
+ case ZigClangType_DependentSizedExtVector:
+ case ZigClangType_Vector:
+ case ZigClangType_ExtVector:
+ case ZigClangType_UnresolvedUsing:
+ case ZigClangType_Adjusted:
+ case ZigClangType_TypeOfExpr:
+ case ZigClangType_TypeOf:
+ case ZigClangType_Decltype:
+ case ZigClangType_UnaryTransform:
+ case ZigClangType_TemplateTypeParm:
+ case ZigClangType_SubstTemplateTypeParm:
+ case ZigClangType_SubstTemplateTypeParmPack:
+ case ZigClangType_TemplateSpecialization:
+ case ZigClangType_Auto:
+ case ZigClangType_InjectedClassName:
+ case ZigClangType_DependentName:
+ case ZigClangType_DependentTemplateSpecialization:
+ case ZigClangType_PackExpansion:
+ case ZigClangType_ObjCObject:
+ case ZigClangType_ObjCInterface:
+ case ZigClangType_Complex:
+ case ZigClangType_ObjCObjectPointer:
+ case ZigClangType_Atomic:
+ case ZigClangType_Pipe:
+ case ZigClangType_ObjCTypeParam:
+ case ZigClangType_DeducedTemplateSpecialization:
+ case ZigClangType_DependentAddressSpace:
+ case ZigClangType_DependentVector:
+ emit_warning(c, source_loc, "unsupported type: '%s'", ZigClangType_getTypeClassName(ty));
return nullptr;
}
zig_unreachable();
}
-static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) {
- return trans_type(c, qt.getTypePtr(), source_loc);
+static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceLocation source_loc) {
+ return trans_type(c, ZigClangQualType_getTypePtr(qt), source_loc);
}
-static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
+static int trans_compound_stmt_inline(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt,
AstNode *block_node, TransScope **out_node_scope)
{
assert(block_node->type == NodeTypeBlock);
- for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
+ for (ZigClangCompoundStmt_const_body_iterator it = ZigClangCompoundStmt_body_begin(stmt),
+ end_it = ZigClangCompoundStmt_body_end(stmt); it != end_it; ++it)
+ {
AstNode *child_node;
scope = trans_stmt(c, scope, *it, &child_node);
if (scope == nullptr)
@@ -1239,7 +1297,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang
return ErrorNone;
}
-static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
+static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt,
TransScope **out_node_scope)
{
TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);
@@ -1251,7 +1309,7 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::
static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope,
const clang::StmtExpr *stmt, TransScope **out_node_scope)
{
- AstNode *block = trans_compound_stmt(c, scope, stmt->getSubStmt(), out_node_scope);
+ AstNode *block = trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt->getSubStmt(), out_node_scope);
if (block == nullptr)
return block;
assert(block->type == NodeTypeBlock);
@@ -1274,7 +1332,7 @@ static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *
}
static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {
- const clang::Expr *value_expr = stmt->getRetValue();
+ const ZigClangExpr *value_expr = bitcast(stmt->getRetValue());
if (value_expr == nullptr) {
return trans_create_node(c, NodeTypeReturnExpr);
} else {
@@ -1289,22 +1347,62 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::Re
static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const clang::IntegerLiteral *stmt) {
clang::Expr::EvalResult result;
if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
- emit_warning(c, stmt->getBeginLoc(), "invalid integer literal");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "invalid integer literal");
+ return nullptr;
+ }
+ AstNode *node = trans_create_node_apint(c, bitcast(&result.Val.getInt()));
+ return maybe_suppress_result(c, result_used, node);
+}
+
+static AstNode *trans_floating_literal(Context *c, ResultUsed result_used, const clang::FloatingLiteral *stmt) {
+ llvm::APFloat result{0.0f};
+ if (!stmt->EvaluateAsFloat(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "invalid floating literal");
return nullptr;
}
- AstNode *node = trans_create_node_apint(c, result.Val.getInt());
+ AstNode *node = trans_create_node_apfloat(c, result);
return maybe_suppress_result(c, result_used, node);
}
+static AstNode *trans_character_literal(Context *c, ResultUsed result_used, const clang::CharacterLiteral *stmt) {
+ switch (stmt->getKind()) {
+ case clang::CharacterLiteral::CharacterKind::Ascii:
+ {
+ unsigned val = stmt->getValue();
+ // C has a somewhat obscure feature called multi-character character
+ // constant
+ if (val > 255)
+ return trans_create_node_unsigned(c, val);
+ }
+ // fallthrough
+ case clang::CharacterLiteral::CharacterKind::UTF8:
+ {
+ AstNode *node = trans_create_node(c, NodeTypeCharLiteral);
+ node->data.char_literal.value = stmt->getValue();
+ return maybe_suppress_result(c, result_used, node);
+ }
+ case clang::CharacterLiteral::CharacterKind::UTF16:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF16 character literals");
+ return nullptr;
+ case clang::CharacterLiteral::CharacterKind::UTF32:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF32 character literals");
+ return nullptr;
+ case clang::CharacterLiteral::CharacterKind::Wide:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support wide character literals");
+ return nullptr;
+ }
+ zig_unreachable();
+}
+
static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) {
clang::Expr::EvalResult result;
if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen,
*reinterpret_cast<clang::ASTContext *>(c->ctx)))
{
- emit_warning(c, expr->getBeginLoc(), "invalid constant expression");
+ emit_warning(c, bitcast(expr->getBeginLoc()), "invalid constant expression");
return nullptr;
}
- AstNode *node = trans_ap_value(c, &result.Val, expr->getType(), expr->getBeginLoc());
+ AstNode *node = trans_ap_value(c, bitcast(&result.Val), bitcast(expr->getType()), bitcast(expr->getBeginLoc()));
return maybe_suppress_result(c, result_used, node);
}
@@ -1313,9 +1411,9 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
{
AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
- clang::Expr *cond_expr = stmt->getCond();
- clang::Expr *true_expr = stmt->getTrueExpr();
- clang::Expr *false_expr = stmt->getFalseExpr();
+ const ZigClangExpr *cond_expr = bitcast(stmt->getCond());
+ const ZigClangExpr *true_expr = bitcast(stmt->getTrueExpr());
+ const ZigClangExpr *false_expr = bitcast(stmt->getFalseExpr());
node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);
if (node->data.if_bool_expr.condition == nullptr)
@@ -1332,7 +1430,9 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
return maybe_suppress_result(c, result_used, node);
}
-static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
+static AstNode *trans_create_bin_op(Context *c, TransScope *scope, const ZigClangExpr *lhs,
+ BinOpType bin_op, const ZigClangExpr *rhs)
+{
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
node->data.bin_op_expr.bin_op = bin_op;
@@ -1347,7 +1447,9 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *
return node;
}
-static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
+static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, const ZigClangExpr *lhs,
+ BinOpType bin_op, const ZigClangExpr *rhs)
+{
assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
node->data.bin_op_expr.bin_op = bin_op;
@@ -1363,7 +1465,9 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::E
return node;
}
-static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, clang::Expr *lhs, clang::Expr *rhs) {
+static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope,
+ const ZigClangExpr *lhs, const ZigClangExpr *rhs)
+{
if (result_used == ResultUsedNo) {
// common case
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
@@ -1414,10 +1518,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
}
}
-static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type,
- clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr)
+static AstNode *trans_create_shift_op(Context *c, TransScope *scope, ZigClangQualType result_type,
+ const ZigClangExpr *lhs_expr, BinOpType bin_op, const ZigClangExpr *rhs_expr)
{
- const clang::SourceLocation &rhs_location = rhs_expr->getBeginLoc();
+ ZigClangSourceLocation rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);
AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
// lhs >> u5(rh)
@@ -1434,130 +1538,130 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::Qual
static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) {
switch (stmt->getOpcode()) {
case clang::BO_PtrMemD:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemD");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C binary operators: BO_PtrMemD");
return nullptr;
case clang::BO_PtrMemI:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemI");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C binary operators: BO_PtrMemI");
return nullptr;
case clang::BO_Cmp:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_Cmp");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C binary operators: BO_Cmp");
return nullptr;
case clang::BO_Mul: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(),
- qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
- stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()),
+ qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())) ? BinOpTypeMultWrap : BinOpTypeMult,
+ bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_Div:
- if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
+ if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType()))) {
// unsigned/float division uses the operator
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeDiv, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
} else {
// signed integer division uses @divTrunc
AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc");
- AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue);
+ AstNode *lhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getLHS()), TransLValue);
if (lhs == nullptr) return nullptr;
fn_call->data.fn_call_expr.params.append(lhs);
- AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue);
+ AstNode *rhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getRHS()), TransLValue);
if (rhs == nullptr) return nullptr;
fn_call->data.fn_call_expr.params.append(rhs);
return maybe_suppress_result(c, result_used, fn_call);
}
case clang::BO_Rem:
- if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
+ if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType()))) {
// unsigned/float division uses the operator
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeMod, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
} else {
// signed integer division uses @rem
AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem");
- AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue);
+ AstNode *lhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getLHS()), TransLValue);
if (lhs == nullptr) return nullptr;
fn_call->data.fn_call_expr.params.append(lhs);
- AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue);
+ AstNode *rhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getRHS()), TransLValue);
if (rhs == nullptr) return nullptr;
fn_call->data.fn_call_expr.params.append(rhs);
return maybe_suppress_result(c, result_used, fn_call);
}
case clang::BO_Add: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(),
- qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
- stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()),
+ qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())) ? BinOpTypeAddWrap : BinOpTypeAdd,
+ bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_Sub: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(),
- qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
- stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()),
+ qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())) ? BinOpTypeSubWrap : BinOpTypeSub,
+ bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_Shl: {
- AstNode *node = trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
+ AstNode *node = trans_create_shift_op(c, scope, bitcast(stmt->getType()), bitcast(stmt->getLHS()), BinOpTypeBitShiftLeft, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_Shr: {
- AstNode *node = trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
+ AstNode *node = trans_create_shift_op(c, scope, bitcast(stmt->getType()), bitcast(stmt->getLHS()), BinOpTypeBitShiftRight, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_LT: {
- AstNode *node =trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
+ AstNode *node =trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpLessThan, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_GT: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpGreaterThan, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_LE: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpLessOrEq, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_GE: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpGreaterOrEq, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_EQ: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpEq, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_NE: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpNotEq, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_And: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBinAnd, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_Xor: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBinXor, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_Or: {
- AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
+ AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBinOr, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_LAnd: {
- AstNode *node = trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
+ AstNode *node = trans_create_bool_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBoolAnd, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_LOr: {
- AstNode *node = trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
+ AstNode *node = trans_create_bool_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBoolOr, bitcast(stmt->getRHS()));
return maybe_suppress_result(c, result_used, node);
}
case clang::BO_Assign:
- return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
+ return trans_create_assign(c, result_used, scope, bitcast(stmt->getLHS()), bitcast(stmt->getRHS()));
case clang::BO_Comma:
{
TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
Buf *label_name = buf_create_from_str("x");
scope_block->node->data.block.name = label_name;
- AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, stmt->getLHS(), TransRValue);
+ AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, bitcast(stmt->getLHS()), TransRValue);
if (lhs == nullptr)
return nullptr;
scope_block->node->data.block.statements.append(lhs);
- AstNode *rhs = trans_expr(c, ResultUsedYes, &scope_block->base, stmt->getRHS(), TransRValue);
+ AstNode *rhs = trans_expr(c, ResultUsedYes, &scope_block->base, bitcast(stmt->getRHS()), TransRValue);
if (rhs == nullptr)
return nullptr;
@@ -1584,17 +1688,17 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope,
const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
{
- const clang::SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc();
- AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
+ ZigClangSourceLocation rhs_location = bitcast(stmt->getRHS()->getBeginLoc());
+ AstNode *rhs_type = qual_type_to_log2_int_ref(c, bitcast(stmt->getComputationLHSType()), rhs_location);
bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();
if (!use_intermediate_casts && result_used == ResultUsedNo) {
// simple common case, where the C and Zig are identical:
// lhs >>= rhs
- AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue);
+ AstNode *lhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getLHS()), TransLValue);
if (lhs == nullptr) return nullptr;
- AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransRValue);
+ AstNode *rhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getRHS()), TransRValue);
if (rhs == nullptr) return nullptr;
AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
@@ -1614,7 +1718,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
child_scope->node->data.block.name = label_name;
// const _ref = &lhs;
- AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue);
+ AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, bitcast(stmt->getLHS()), TransLValue);
if (lhs == nullptr) return nullptr;
AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);
// TODO: avoid name collisions with generated variable names
@@ -1624,20 +1728,20 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
// *_ref = result_type(operation_type(*_ref) >> u5(rhs));
- AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getRHS(), TransRValue);
+ AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, bitcast(stmt->getRHS()), TransRValue);
if (rhs == nullptr) return nullptr;
AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
// operation_type(*_ref)
AstNode *operation_type_cast = trans_c_cast(c, rhs_location,
- stmt->getComputationLHSType(),
- stmt->getLHS()->getType(),
+ bitcast(stmt->getComputationLHSType()),
+ bitcast(stmt->getLHS()->getType()),
trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)));
// result_type(... >> u5(rhs))
AstNode *result_type_cast = trans_c_cast(c, rhs_location,
- stmt->getComputationResultType(),
- stmt->getComputationLHSType(),
+ bitcast(stmt->getComputationResultType()),
+ bitcast(stmt->getComputationLHSType()),
trans_create_node_bin_op(c,
operation_type_cast,
bin_op,
@@ -1669,9 +1773,9 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
if (result_used == ResultUsedNo) {
// simple common case, where the C and Zig are identical:
// lhs += rhs
- AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue);
+ AstNode *lhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getLHS()), TransLValue);
if (lhs == nullptr) return nullptr;
- AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransRValue);
+ AstNode *rhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getRHS()), TransRValue);
if (rhs == nullptr) return nullptr;
return trans_create_node_bin_op(c, lhs, assign_op, rhs);
} else {
@@ -1688,7 +1792,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
child_scope->node->data.block.name = label_name;
// const _ref = &lhs;
- AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue);
+ AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, bitcast(stmt->getLHS()), TransLValue);
if (lhs == nullptr) return nullptr;
AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);
// TODO: avoid name collisions with generated variable names
@@ -1698,7 +1802,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
// *_ref = *_ref + rhs;
- AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getRHS(), TransRValue);
+ AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, bitcast(stmt->getRHS()), TransRValue);
if (rhs == nullptr) return nullptr;
AstNode *assign_statement = trans_create_node_bin_op(c,
@@ -1728,26 +1832,26 @@ static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_use
{
switch (stmt->getOpcode()) {
case clang::BO_MulAssign:
- if (qual_type_has_wrapping_overflow(c, stmt->getType()))
+ if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
else
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
case clang::BO_DivAssign:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_DivAssign");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C compound assign operators: BO_DivAssign");
return nullptr;
case clang::BO_RemAssign:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_RemAssign");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C compound assign operators: BO_RemAssign");
return nullptr;
case clang::BO_Cmp:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_Cmp");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C compound assign operators: BO_Cmp");
return nullptr;
case clang::BO_AddAssign:
- if (qual_type_has_wrapping_overflow(c, stmt->getType()))
+ if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
else
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
case clang::BO_SubAssign:
- if (qual_type_has_wrapping_overflow(c, stmt->getType()))
+ if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
else
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
@@ -1790,202 +1894,265 @@ static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_use
}
static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ImplicitCastExpr *stmt) {
- switch (stmt->getCastKind()) {
- case clang::CK_LValueToRValue:
- return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
- case clang::CK_IntegralCast:
+ switch ((ZigClangCK)stmt->getCastKind()) {
+ case ZigClangCK_LValueToRValue:
+ return trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
+ case ZigClangCK_IntegralCast:
{
- AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
+ AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
if (target_node == nullptr)
return nullptr;
- AstNode *node = trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),
- stmt->getSubExpr()->getType(), target_node);
+ AstNode *node = trans_c_cast(c, bitcast(stmt->getExprLoc()), bitcast(stmt->getType()),
+ bitcast(stmt->getSubExpr()->getType()), target_node);
return maybe_suppress_result(c, result_used, node);
}
- case clang::CK_FunctionToPointerDecay:
- case clang::CK_ArrayToPointerDecay:
+ case ZigClangCK_FunctionToPointerDecay:
+ case ZigClangCK_ArrayToPointerDecay:
{
- AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
+ AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
if (target_node == nullptr)
return nullptr;
return maybe_suppress_result(c, result_used, target_node);
}
- case clang::CK_BitCast:
+ case ZigClangCK_BitCast:
{
- AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
+ AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
if (target_node == nullptr)
return nullptr;
- if (expr_types_equal(c, stmt, stmt->getSubExpr())) {
- return target_node;
- }
+ const ZigClangQualType dest_type = get_expr_qual_type(c, bitcast(stmt));
+ const ZigClangQualType src_type = get_expr_qual_type(c, bitcast(stmt->getSubExpr()));
- AstNode *dest_type_node = get_expr_type(c, stmt);
-
- AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
- node->data.fn_call_expr.params.append(dest_type_node);
- node->data.fn_call_expr.params.append(target_node);
- return maybe_suppress_result(c, result_used, node);
+ return trans_c_cast(c, bitcast(stmt->getBeginLoc()), dest_type, src_type, target_node);
}
- case clang::CK_NullToPointer:
- return trans_create_node_unsigned(c, 0);
- case clang::CK_NoOp:
- return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
- case clang::CK_Dependent:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dependent");
- return nullptr;
- case clang::CK_LValueBitCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_LValueBitCast");
- return nullptr;
- case clang::CK_BaseToDerived:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerived");
- return nullptr;
- case clang::CK_DerivedToBase:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBase");
- return nullptr;
- case clang::CK_UncheckedDerivedToBase:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UncheckedDerivedToBase");
+ case ZigClangCK_NullToPointer:
+ return trans_create_node(c, NodeTypeNullLiteral);
+ case ZigClangCK_NoOp:
+ return trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
+ case ZigClangCK_Dependent:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_Dependent");
return nullptr;
- case clang::CK_Dynamic:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dynamic");
+ case ZigClangCK_LValueBitCast:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_LValueBitCast");
return nullptr;
- case clang::CK_ToUnion:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToUnion");
+ case ZigClangCK_BaseToDerived:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_BaseToDerived");
return nullptr;
- case clang::CK_NullToMemberPointer:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NullToMemberPointer");
+ case ZigClangCK_DerivedToBase:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_DerivedToBase");
return nullptr;
- case clang::CK_BaseToDerivedMemberPointer:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
+ case ZigClangCK_UncheckedDerivedToBase:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_UncheckedDerivedToBase");
return nullptr;
- case clang::CK_DerivedToBaseMemberPointer:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
+ case ZigClangCK_Dynamic:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_Dynamic");
return nullptr;
- case clang::CK_MemberPointerToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_MemberPointerToBoolean");
+ case ZigClangCK_ToUnion:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_ToUnion");
return nullptr;
- case clang::CK_ReinterpretMemberPointer:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ReinterpretMemberPointer");
+ case ZigClangCK_NullToMemberPointer:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_NullToMemberPointer");
return nullptr;
- case clang::CK_UserDefinedConversion:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UserDefinedConversion");
+ case ZigClangCK_BaseToDerivedMemberPointer:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
return nullptr;
- case clang::CK_ConstructorConversion:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ConstructorConversion");
+ case ZigClangCK_DerivedToBaseMemberPointer:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
return nullptr;
- case clang::CK_IntegralToPointer:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToPointer");
+ case ZigClangCK_MemberPointerToBoolean:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_MemberPointerToBoolean");
return nullptr;
- case clang::CK_PointerToIntegral:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_PointerToIntegral");
+ case ZigClangCK_ReinterpretMemberPointer:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_ReinterpretMemberPointer");
return nullptr;
- case clang::CK_PointerToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_PointerToBoolean");
+ case ZigClangCK_UserDefinedConversion:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_UserDefinedConversion");
return nullptr;
- case clang::CK_ToVoid:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ToVoid");
+ case ZigClangCK_ConstructorConversion:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion");
return nullptr;
- case clang::CK_VectorSplat:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_VectorSplat");
- return nullptr;
- case clang::CK_IntegralToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToBoolean");
- return nullptr;
- case clang::CK_IntegralToFloating:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToFloating");
+ case ZigClangCK_PointerToBoolean:
+ {
+ const clang::Expr *expr = stmt->getSubExpr();
+ AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue);
+ if (val == nullptr)
+ return nullptr;
+
+ AstNode *val_ptr = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
+ val_ptr->data.fn_call_expr.params.append(val);
+
+ AstNode *zero = trans_create_node_unsigned(c, 0);
+
+ // Translate as @ptrToInt((&val) != 0)
+ return trans_create_node_bin_op(c, val_ptr, BinOpTypeCmpNotEq, zero);
+ }
+ case ZigClangCK_ToVoid:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ToVoid");
return nullptr;
- case clang::CK_FixedPointCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FixedPointCast");
+ case ZigClangCK_VectorSplat:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat");
return nullptr;
- case clang::CK_FixedPointToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FixedPointToBoolean");
+ case ZigClangCK_IntegralToBoolean:
+ {
+ const clang::Expr *expr = stmt->getSubExpr();
+
+ bool expr_val;
+ if (expr->EvaluateAsBooleanCondition(expr_val, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
+ return trans_create_node_bool(c, expr_val);
+ }
+
+ AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue);
+ if (val == nullptr)
+ return nullptr;
+
+ AstNode *zero = trans_create_node_unsigned(c, 0);
+
+ // Translate as val != 0
+ return trans_create_node_bin_op(c, val, BinOpTypeCmpNotEq, zero);
+ }
+ case ZigClangCK_PointerToIntegral:
+ {
+ AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
+ if (target_node == nullptr)
+ return nullptr;
+
+ AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
+ if (dest_type_node == nullptr)
+ return nullptr;
+
+ AstNode *val_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
+ val_node->data.fn_call_expr.params.append(target_node);
+ // @ptrToInt always returns a usize
+ AstNode *node = trans_create_node_builtin_fn_call_str(c, "intCast");
+ node->data.fn_call_expr.params.append(dest_type_node);
+ node->data.fn_call_expr.params.append(val_node);
+
+ return maybe_suppress_result(c, result_used, node);
+ }
+ case ZigClangCK_IntegralToPointer:
+ {
+ AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
+ if (target_node == nullptr)
+ return nullptr;
+
+ AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
+ if (dest_type_node == nullptr)
+ return nullptr;
+
+ AstNode *node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
+ node->data.fn_call_expr.params.append(dest_type_node);
+ node->data.fn_call_expr.params.append(target_node);
+
+ return maybe_suppress_result(c, result_used, node);
+ }
+ case ZigClangCK_IntegralToFloating:
+ case ZigClangCK_FloatingToIntegral:
+ {
+ AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
+ if (target_node == nullptr)
+ return nullptr;
+
+ AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
+ if (dest_type_node == nullptr)
+ return nullptr;
+
+ char const *fn = (ZigClangCK)stmt->getCastKind() == ZigClangCK_IntegralToFloating ?
+ "intToFloat" : "floatToInt";
+ AstNode *node = trans_create_node_builtin_fn_call_str(c, fn);
+ node->data.fn_call_expr.params.append(dest_type_node);
+ node->data.fn_call_expr.params.append(target_node);
+
+ return maybe_suppress_result(c, result_used, node);
+ }
+ case ZigClangCK_FixedPointCast:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointCast");
return nullptr;
- case clang::CK_FloatingToIntegral:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingToIntegral");
+ case ZigClangCK_FixedPointToBoolean:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean");
return nullptr;
- case clang::CK_FloatingToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingToBoolean");
+ case ZigClangCK_FloatingToBoolean:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean");
return nullptr;
- case clang::CK_BooleanToSignedIntegral:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BooleanToSignedIntegral");
+ case ZigClangCK_BooleanToSignedIntegral:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BooleanToSignedIntegral");
return nullptr;
- case clang::CK_FloatingCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingCast");
+ case ZigClangCK_FloatingCast:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingCast");
return nullptr;
- case clang::CK_CPointerToObjCPointerCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_CPointerToObjCPointerCast");
+ case ZigClangCK_CPointerToObjCPointerCast:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_CPointerToObjCPointerCast");
return nullptr;
- case clang::CK_BlockPointerToObjCPointerCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BlockPointerToObjCPointerCast");
+ case ZigClangCK_BlockPointerToObjCPointerCast:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BlockPointerToObjCPointerCast");
return nullptr;
- case clang::CK_AnyPointerToBlockPointerCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AnyPointerToBlockPointerCast");
+ case ZigClangCK_AnyPointerToBlockPointerCast:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AnyPointerToBlockPointerCast");
return nullptr;
- case clang::CK_ObjCObjectLValueCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ObjCObjectLValueCast");
+ case ZigClangCK_ObjCObjectLValueCast:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ObjCObjectLValueCast");
return nullptr;
- case clang::CK_FloatingRealToComplex:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingRealToComplex");
+ case ZigClangCK_FloatingRealToComplex:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingRealToComplex");
return nullptr;
- case clang::CK_FloatingComplexToReal:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToReal");
+ case ZigClangCK_FloatingComplexToReal:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToReal");
return nullptr;
- case clang::CK_FloatingComplexToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToBoolean");
+ case ZigClangCK_FloatingComplexToBoolean:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToBoolean");
return nullptr;
- case clang::CK_FloatingComplexCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexCast");
+ case ZigClangCK_FloatingComplexCast:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexCast");
return nullptr;
- case clang::CK_FloatingComplexToIntegralComplex:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToIntegralComplex");
+ case ZigClangCK_FloatingComplexToIntegralComplex:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToIntegralComplex");
return nullptr;
- case clang::CK_IntegralRealToComplex:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralRealToComplex");
+ case ZigClangCK_IntegralRealToComplex:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralRealToComplex");
return nullptr;
- case clang::CK_IntegralComplexToReal:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToReal");
+ case ZigClangCK_IntegralComplexToReal:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToReal");
return nullptr;
- case clang::CK_IntegralComplexToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToBoolean");
+ case ZigClangCK_IntegralComplexToBoolean:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToBoolean");
return nullptr;
- case clang::CK_IntegralComplexCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexCast");
+ case ZigClangCK_IntegralComplexCast:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexCast");
return nullptr;
- case clang::CK_IntegralComplexToFloatingComplex:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToFloatingComplex");
+ case ZigClangCK_IntegralComplexToFloatingComplex:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToFloatingComplex");
return nullptr;
- case clang::CK_ARCProduceObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCProduceObject");
+ case ZigClangCK_ARCProduceObject:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCProduceObject");
return nullptr;
- case clang::CK_ARCConsumeObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCConsumeObject");
+ case ZigClangCK_ARCConsumeObject:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCConsumeObject");
return nullptr;
- case clang::CK_ARCReclaimReturnedObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCReclaimReturnedObject");
+ case ZigClangCK_ARCReclaimReturnedObject:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCReclaimReturnedObject");
return nullptr;
- case clang::CK_ARCExtendBlockObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCExtendBlockObject");
+ case ZigClangCK_ARCExtendBlockObject:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCExtendBlockObject");
return nullptr;
- case clang::CK_AtomicToNonAtomic:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AtomicToNonAtomic");
+ case ZigClangCK_AtomicToNonAtomic:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AtomicToNonAtomic");
return nullptr;
- case clang::CK_NonAtomicToAtomic:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_NonAtomicToAtomic");
+ case ZigClangCK_NonAtomicToAtomic:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_NonAtomicToAtomic");
return nullptr;
- case clang::CK_CopyAndAutoreleaseBlockObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_CopyAndAutoreleaseBlockObject");
+ case ZigClangCK_CopyAndAutoreleaseBlockObject:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_CopyAndAutoreleaseBlockObject");
return nullptr;
- case clang::CK_BuiltinFnToFnPtr:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BuiltinFnToFnPtr");
+ case ZigClangCK_BuiltinFnToFnPtr:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BuiltinFnToFnPtr");
return nullptr;
- case clang::CK_ZeroToOCLOpaqueType:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ZeroToOCLOpaqueType");
+ case ZigClangCK_ZeroToOCLOpaqueType:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ZeroToOCLOpaqueType");
return nullptr;
- case clang::CK_AddressSpaceConversion:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AddressSpaceConversion");
+ case ZigClangCK_AddressSpaceConversion:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AddressSpaceConversion");
return nullptr;
- case clang::CK_IntToOCLSampler:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntToOCLSampler");
+ case ZigClangCK_IntToOCLSampler:
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntToOCLSampler");
return nullptr;
}
zig_unreachable();
@@ -1993,7 +2160,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra
static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) {
const clang::ValueDecl *value_decl = stmt->getDecl();
- Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));
+ Buf *c_symbol_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)value_decl));
Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);
if (lrval == TransLValue) {
c->ptr_params.put(zig_symbol_name, true);
@@ -2004,7 +2171,7 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::
static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope,
const clang::UnaryOperator *stmt, BinOpType assign_op)
{
- clang::Expr *op_expr = stmt->getSubExpr();
+ const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
if (result_used == ResultUsedNo) {
// common case
@@ -2060,7 +2227,7 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope,
const clang::UnaryOperator *stmt, BinOpType assign_op)
{
- clang::Expr *op_expr = stmt->getSubExpr();
+ const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
if (result_used == ResultUsedNo) {
// common case
@@ -2110,50 +2277,50 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) {
switch (stmt->getOpcode()) {
case clang::UO_PostInc:
- if (qual_type_has_wrapping_overflow(c, stmt->getType()))
+ if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
else
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
case clang::UO_PostDec:
- if (qual_type_has_wrapping_overflow(c, stmt->getType()))
+ if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
else
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
case clang::UO_PreInc:
- if (qual_type_has_wrapping_overflow(c, stmt->getType()))
+ if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
else
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
case clang::UO_PreDec:
- if (qual_type_has_wrapping_overflow(c, stmt->getType()))
+ if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
else
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
case clang::UO_AddrOf:
{
- AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
+ AstNode *value_node = trans_expr(c, result_used, scope, bitcast(stmt->getSubExpr()), TransLValue);
if (value_node == nullptr)
return value_node;
return trans_create_node_addr_of(c, value_node);
}
case clang::UO_Deref:
{
- AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);
+ AstNode *value_node = trans_expr(c, result_used, scope, bitcast(stmt->getSubExpr()), TransRValue);
if (value_node == nullptr)
return nullptr;
- bool is_fn_ptr = qual_type_is_fn_ptr(stmt->getSubExpr()->getType());
+ bool is_fn_ptr = qual_type_is_fn_ptr(bitcast(stmt->getSubExpr()->getType()));
if (is_fn_ptr)
return value_node;
AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);
return trans_create_node_ptr_deref(c, unwrapped);
}
case clang::UO_Plus:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Plus");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Plus");
return nullptr;
case clang::UO_Minus:
{
- clang::Expr *op_expr = stmt->getSubExpr();
- if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
+ const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
+ if (!qual_type_has_wrapping_overflow(c, ZigClangExpr_getType(op_expr))) {
AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
@@ -2162,7 +2329,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
return nullptr;
return node;
- } else if (c_is_unsigned_integer(c, op_expr->getType())) {
+ } else if (c_is_unsigned_integer(c, ZigClangExpr_getType(op_expr))) {
// we gotta emit 0 -% x
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0);
@@ -2174,13 +2341,13 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
node->data.bin_op_expr.bin_op = BinOpTypeSubWrap;
return node;
} else {
- emit_warning(c, stmt->getBeginLoc(), "C negation with non float non integer");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "C negation with non float non integer");
return nullptr;
}
}
case clang::UO_Not:
{
- clang::Expr *op_expr = stmt->getSubExpr();
+ const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
if (sub_node == nullptr)
return nullptr;
@@ -2189,7 +2356,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
}
case clang::UO_LNot:
{
- clang::Expr *op_expr = stmt->getSubExpr();
+ const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
if (sub_node == nullptr)
return nullptr;
@@ -2197,15 +2364,15 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
}
case clang::UO_Real:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Real");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Real");
return nullptr;
case clang::UO_Imag:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Imag");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Imag");
return nullptr;
case clang::UO_Extension:
- return trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
+ return trans_expr(c, result_used, scope, bitcast(stmt->getSubExpr()), TransLValue);
case clang::UO_Coawait:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Coawait");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Coawait");
return nullptr;
}
zig_unreachable();
@@ -2225,249 +2392,250 @@ static int trans_local_declaration(Context *c, TransScope *scope, const clang::D
switch (decl->getKind()) {
case clang::Decl::Var: {
clang::VarDecl *var_decl = (clang::VarDecl *)decl;
- clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType();
+ ZigClangQualType qual_type = bitcast(var_decl->getTypeSourceInfo()->getType());
AstNode *init_node = nullptr;
if (var_decl->hasInit()) {
- init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue);
+ init_node = trans_expr(c, ResultUsedYes, scope, bitcast(var_decl->getInit()), TransRValue);
if (init_node == nullptr)
return ErrorUnexpected;
} else {
init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
}
- AstNode *type_node = trans_qual_type(c, qual_type, stmt->getBeginLoc());
+ AstNode *type_node = trans_qual_type(c, qual_type, bitcast(stmt->getBeginLoc()));
if (type_node == nullptr)
return ErrorUnexpected;
- Buf *c_symbol_name = buf_create_from_str(decl_name(var_decl));
+ Buf *c_symbol_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)var_decl));
TransScopeVar *var_scope = trans_scope_var_create(c, scope, c_symbol_name);
scope = &var_scope->base;
- AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(),
+ AstNode *node = trans_create_node_var_decl_local(c,
+ ZigClangQualType_isConstQualified(qual_type),
var_scope->zig_name, type_node, init_node);
scope_block->node->data.block.statements.append(node);
continue;
}
case clang::Decl::AccessSpec:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind AccessSpec");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle decl kind AccessSpec");
return ErrorUnexpected;
case clang::Decl::Block:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Block");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Block");
return ErrorUnexpected;
case clang::Decl::Captured:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Captured");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Captured");
return ErrorUnexpected;
case clang::Decl::ClassScopeFunctionSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassScopeFunctionSpecialization");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassScopeFunctionSpecialization");
return ErrorUnexpected;
case clang::Decl::Empty:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Empty");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Empty");
return ErrorUnexpected;
case clang::Decl::Export:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Export");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Export");
return ErrorUnexpected;
case clang::Decl::ExternCContext:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExternCContext");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ExternCContext");
return ErrorUnexpected;
case clang::Decl::FileScopeAsm:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C FileScopeAsm");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FileScopeAsm");
return ErrorUnexpected;
case clang::Decl::Friend:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Friend");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Friend");
return ErrorUnexpected;
case clang::Decl::FriendTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C FriendTemplate");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FriendTemplate");
return ErrorUnexpected;
case clang::Decl::Import:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Import");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Import");
return ErrorUnexpected;
case clang::Decl::LinkageSpec:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C LinkageSpec");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C LinkageSpec");
return ErrorUnexpected;
case clang::Decl::Label:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Label");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Label");
return ErrorUnexpected;
case clang::Decl::Namespace:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Namespace");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Namespace");
return ErrorUnexpected;
case clang::Decl::NamespaceAlias:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C NamespaceAlias");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C NamespaceAlias");
return ErrorUnexpected;
case clang::Decl::ObjCCompatibleAlias:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCCompatibleAlias");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCCompatibleAlias");
return ErrorUnexpected;
case clang::Decl::ObjCCategory:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCCategory");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCCategory");
return ErrorUnexpected;
case clang::Decl::ObjCCategoryImpl:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCCategoryImpl");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCCategoryImpl");
return ErrorUnexpected;
case clang::Decl::ObjCImplementation:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCImplementation");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCImplementation");
return ErrorUnexpected;
case clang::Decl::ObjCInterface:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCInterface");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCInterface");
return ErrorUnexpected;
case clang::Decl::ObjCProtocol:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProtocol");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCProtocol");
return ErrorUnexpected;
case clang::Decl::ObjCMethod:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCMethod");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCMethod");
return ErrorUnexpected;
case clang::Decl::ObjCProperty:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProperty");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCProperty");
return ErrorUnexpected;
case clang::Decl::BuiltinTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C BuiltinTemplate");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C BuiltinTemplate");
return ErrorUnexpected;
case clang::Decl::ClassTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassTemplate");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassTemplate");
return ErrorUnexpected;
case clang::Decl::FunctionTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C FunctionTemplate");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FunctionTemplate");
return ErrorUnexpected;
case clang::Decl::TypeAliasTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeAliasTemplate");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TypeAliasTemplate");
return ErrorUnexpected;
case clang::Decl::VarTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C VarTemplate");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VarTemplate");
return ErrorUnexpected;
case clang::Decl::TemplateTemplateParm:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C TemplateTemplateParm");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TemplateTemplateParm");
return ErrorUnexpected;
case clang::Decl::Enum:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Enum");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Enum");
return ErrorUnexpected;
case clang::Decl::Record:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Record");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Record");
return ErrorUnexpected;
case clang::Decl::CXXRecord:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXRecord");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXRecord");
return ErrorUnexpected;
case clang::Decl::ClassTemplateSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassTemplateSpecialization");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassTemplateSpecialization");
return ErrorUnexpected;
case clang::Decl::ClassTemplatePartialSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassTemplatePartialSpecialization");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassTemplatePartialSpecialization");
return ErrorUnexpected;
case clang::Decl::TemplateTypeParm:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C TemplateTypeParm");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TemplateTypeParm");
return ErrorUnexpected;
case clang::Decl::ObjCTypeParam:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCTypeParam");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCTypeParam");
return ErrorUnexpected;
case clang::Decl::TypeAlias:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeAlias");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TypeAlias");
return ErrorUnexpected;
case clang::Decl::Typedef:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Typedef");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Typedef");
return ErrorUnexpected;
case clang::Decl::UnresolvedUsingTypename:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedUsingTypename");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UnresolvedUsingTypename");
return ErrorUnexpected;
case clang::Decl::Using:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Using");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Using");
return ErrorUnexpected;
case clang::Decl::UsingDirective:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UsingDirective");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UsingDirective");
return ErrorUnexpected;
case clang::Decl::UsingPack:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UsingPack");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UsingPack");
return ErrorUnexpected;
case clang::Decl::UsingShadow:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UsingShadow");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UsingShadow");
return ErrorUnexpected;
case clang::Decl::ConstructorUsingShadow:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ConstructorUsingShadow");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ConstructorUsingShadow");
return ErrorUnexpected;
case clang::Decl::Binding:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Binding");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Binding");
return ErrorUnexpected;
case clang::Decl::Field:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Field");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Field");
return ErrorUnexpected;
case clang::Decl::ObjCAtDefsField:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtDefsField");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAtDefsField");
return ErrorUnexpected;
case clang::Decl::ObjCIvar:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIvar");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCIvar");
return ErrorUnexpected;
case clang::Decl::Function:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Function");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Function");
return ErrorUnexpected;
case clang::Decl::CXXDeductionGuide:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDeductionGuide");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDeductionGuide");
return ErrorUnexpected;
case clang::Decl::CXXMethod:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXMethod");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXMethod");
return ErrorUnexpected;
case clang::Decl::CXXConstructor:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstructor");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXConstructor");
return ErrorUnexpected;
case clang::Decl::CXXConversion:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConversion");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXConversion");
return ErrorUnexpected;
case clang::Decl::CXXDestructor:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDestructor");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDestructor");
return ErrorUnexpected;
case clang::Decl::MSProperty:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSProperty");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C MSProperty");
return ErrorUnexpected;
case clang::Decl::NonTypeTemplateParm:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C NonTypeTemplateParm");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C NonTypeTemplateParm");
return ErrorUnexpected;
case clang::Decl::Decomposition:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C Decomposition");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Decomposition");
return ErrorUnexpected;
case clang::Decl::ImplicitParam:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImplicitParam");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ImplicitParam");
return ErrorUnexpected;
case clang::Decl::OMPCapturedExpr:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCapturedExpr");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPCapturedExpr");
return ErrorUnexpected;
case clang::Decl::ParmVar:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ParmVar");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ParmVar");
return ErrorUnexpected;
case clang::Decl::VarTemplateSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C VarTemplateSpecialization");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VarTemplateSpecialization");
return ErrorUnexpected;
case clang::Decl::VarTemplatePartialSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C VarTemplatePartialSpecialization");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VarTemplatePartialSpecialization");
return ErrorUnexpected;
case clang::Decl::EnumConstant:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C EnumConstant");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C EnumConstant");
return ErrorUnexpected;
case clang::Decl::IndirectField:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C IndirectField");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C IndirectField");
return ErrorUnexpected;
case clang::Decl::OMPDeclareReduction:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDeclareReduction");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPDeclareReduction");
return ErrorUnexpected;
case clang::Decl::UnresolvedUsingValue:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedUsingValue");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UnresolvedUsingValue");
return ErrorUnexpected;
case clang::Decl::OMPRequires:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPRequires");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPRequires");
return ErrorUnexpected;
case clang::Decl::OMPThreadPrivate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPThreadPrivate");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPThreadPrivate");
return ErrorUnexpected;
case clang::Decl::ObjCPropertyImpl:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCPropertyImpl");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCPropertyImpl");
return ErrorUnexpected;
case clang::Decl::PragmaComment:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C PragmaComment");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C PragmaComment");
return ErrorUnexpected;
case clang::Decl::PragmaDetectMismatch:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C PragmaDetectMismatch");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C PragmaDetectMismatch");
return ErrorUnexpected;
case clang::Decl::StaticAssert:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C StaticAssert");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C StaticAssert");
return ErrorUnexpected;
case clang::Decl::TranslationUnit:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C TranslationUnit");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TranslationUnit");
return ErrorUnexpected;
}
zig_unreachable();
@@ -2493,7 +2661,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)
return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
}
-static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval) {
+static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr, TransLRValue lrval) {
AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
if (res == nullptr)
return nullptr;
@@ -2530,146 +2698,145 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
}
- const clang::Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();
- auto classs = ty->getTypeClass();
+ const ZigClangType *ty = ZigClangQualType_getTypePtr(get_expr_qual_type_before_implicit_cast(c, expr));
+ auto classs = ZigClangType_getTypeClass(ty);
switch (classs) {
- case clang::Type::Builtin:
+ case ZigClangType_Builtin:
{
- const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
- switch (builtin_ty->getKind()) {
- case clang::BuiltinType::Bool:
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::SChar:
- case clang::BuiltinType::UShort:
- case clang::BuiltinType::UInt:
- case clang::BuiltinType::ULong:
- case clang::BuiltinType::ULongLong:
- case clang::BuiltinType::Short:
- case clang::BuiltinType::Int:
- case clang::BuiltinType::Long:
- case clang::BuiltinType::LongLong:
- case clang::BuiltinType::UInt128:
- case clang::BuiltinType::Int128:
- case clang::BuiltinType::Float:
- case clang::BuiltinType::Double:
- case clang::BuiltinType::Float128:
- case clang::BuiltinType::LongDouble:
- case clang::BuiltinType::WChar_U:
- case clang::BuiltinType::Char8:
- case clang::BuiltinType::Char16:
- case clang::BuiltinType::Char32:
- case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Float16:
+ const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty);
+ switch (ZigClangBuiltinType_getKind(builtin_ty)) {
+ case ZigClangBuiltinTypeBool:
+ case ZigClangBuiltinTypeChar_U:
+ case ZigClangBuiltinTypeUChar:
+ case ZigClangBuiltinTypeChar_S:
+ case ZigClangBuiltinTypeSChar:
+ case ZigClangBuiltinTypeUShort:
+ case ZigClangBuiltinTypeUInt:
+ case ZigClangBuiltinTypeULong:
+ case ZigClangBuiltinTypeULongLong:
+ case ZigClangBuiltinTypeShort:
+ case ZigClangBuiltinTypeInt:
+ case ZigClangBuiltinTypeLong:
+ case ZigClangBuiltinTypeLongLong:
+ case ZigClangBuiltinTypeUInt128:
+ case ZigClangBuiltinTypeInt128:
+ case ZigClangBuiltinTypeFloat:
+ case ZigClangBuiltinTypeDouble:
+ case ZigClangBuiltinTypeFloat128:
+ case ZigClangBuiltinTypeLongDouble:
+ case ZigClangBuiltinTypeWChar_U:
+ case ZigClangBuiltinTypeChar8:
+ case ZigClangBuiltinTypeChar16:
+ case ZigClangBuiltinTypeChar32:
+ case ZigClangBuiltinTypeWChar_S:
+ case ZigClangBuiltinTypeFloat16:
return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
- case clang::BuiltinType::NullPtr:
+ case ZigClangBuiltinTypeNullPtr:
return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
- trans_create_node_unsigned(c, 0));
-
- case clang::BuiltinType::Void:
- case clang::BuiltinType::Half:
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- case clang::BuiltinType::ObjCSel:
- case clang::BuiltinType::OMPArraySection:
- case clang::BuiltinType::Dependent:
- case clang::BuiltinType::Overload:
- case clang::BuiltinType::BoundMember:
- case clang::BuiltinType::PseudoObject:
- case clang::BuiltinType::UnknownAny:
- case clang::BuiltinType::BuiltinFn:
- case clang::BuiltinType::ARCUnbridgedCast:
- case clang::BuiltinType::OCLImage1dRO:
- case clang::BuiltinType::OCLImage1dArrayRO:
- case clang::BuiltinType::OCLImage1dBufferRO:
- case clang::BuiltinType::OCLImage2dRO:
- case clang::BuiltinType::OCLImage2dArrayRO:
- case clang::BuiltinType::OCLImage2dDepthRO:
- case clang::BuiltinType::OCLImage2dArrayDepthRO:
- case clang::BuiltinType::OCLImage2dMSAARO:
- case clang::BuiltinType::OCLImage2dArrayMSAARO:
- case clang::BuiltinType::OCLImage2dMSAADepthRO:
- case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
- case clang::BuiltinType::OCLImage3dRO:
- case clang::BuiltinType::OCLImage1dWO:
- case clang::BuiltinType::OCLImage1dArrayWO:
- case clang::BuiltinType::OCLImage1dBufferWO:
- case clang::BuiltinType::OCLImage2dWO:
- case clang::BuiltinType::OCLImage2dArrayWO:
- case clang::BuiltinType::OCLImage2dDepthWO:
- case clang::BuiltinType::OCLImage2dArrayDepthWO:
- case clang::BuiltinType::OCLImage2dMSAAWO:
- case clang::BuiltinType::OCLImage2dArrayMSAAWO:
- case clang::BuiltinType::OCLImage2dMSAADepthWO:
- case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
- case clang::BuiltinType::OCLImage3dWO:
- case clang::BuiltinType::OCLImage1dRW:
- case clang::BuiltinType::OCLImage1dArrayRW:
- case clang::BuiltinType::OCLImage1dBufferRW:
- case clang::BuiltinType::OCLImage2dRW:
- case clang::BuiltinType::OCLImage2dArrayRW:
- case clang::BuiltinType::OCLImage2dDepthRW:
- case clang::BuiltinType::OCLImage2dArrayDepthRW:
- case clang::BuiltinType::OCLImage2dMSAARW:
- case clang::BuiltinType::OCLImage2dArrayMSAARW:
- case clang::BuiltinType::OCLImage2dMSAADepthRW:
- case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
- case clang::BuiltinType::OCLImage3dRW:
- case clang::BuiltinType::OCLSampler:
- case clang::BuiltinType::OCLEvent:
- case clang::BuiltinType::OCLClkEvent:
- case clang::BuiltinType::OCLQueue:
- case clang::BuiltinType::OCLReserveID:
- case clang::BuiltinType::ShortAccum:
- case clang::BuiltinType::Accum:
- case clang::BuiltinType::LongAccum:
- case clang::BuiltinType::UShortAccum:
- case clang::BuiltinType::UAccum:
- case clang::BuiltinType::ULongAccum:
- case clang::BuiltinType::ShortFract:
- case clang::BuiltinType::Fract:
- case clang::BuiltinType::LongFract:
- case clang::BuiltinType::UShortFract:
- case clang::BuiltinType::UFract:
- case clang::BuiltinType::ULongFract:
- case clang::BuiltinType::SatShortAccum:
- case clang::BuiltinType::SatAccum:
- case clang::BuiltinType::SatLongAccum:
- case clang::BuiltinType::SatUShortAccum:
- case clang::BuiltinType::SatUAccum:
- case clang::BuiltinType::SatULongAccum:
- case clang::BuiltinType::SatShortFract:
- case clang::BuiltinType::SatFract:
- case clang::BuiltinType::SatLongFract:
- case clang::BuiltinType::SatUShortFract:
- case clang::BuiltinType::SatUFract:
- case clang::BuiltinType::SatULongFract:
- case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
+ trans_create_node(c, NodeTypeNullLiteral));
+
+ case ZigClangBuiltinTypeVoid:
+ case ZigClangBuiltinTypeHalf:
+ case ZigClangBuiltinTypeObjCId:
+ case ZigClangBuiltinTypeObjCClass:
+ case ZigClangBuiltinTypeObjCSel:
+ case ZigClangBuiltinTypeOMPArraySection:
+ case ZigClangBuiltinTypeDependent:
+ case ZigClangBuiltinTypeOverload:
+ case ZigClangBuiltinTypeBoundMember:
+ case ZigClangBuiltinTypePseudoObject:
+ case ZigClangBuiltinTypeUnknownAny:
+ case ZigClangBuiltinTypeBuiltinFn:
+ case ZigClangBuiltinTypeARCUnbridgedCast:
+ case ZigClangBuiltinTypeOCLImage1dRO:
+ case ZigClangBuiltinTypeOCLImage1dArrayRO:
+ case ZigClangBuiltinTypeOCLImage1dBufferRO:
+ case ZigClangBuiltinTypeOCLImage2dRO:
+ case ZigClangBuiltinTypeOCLImage2dArrayRO:
+ case ZigClangBuiltinTypeOCLImage2dDepthRO:
+ case ZigClangBuiltinTypeOCLImage2dArrayDepthRO:
+ case ZigClangBuiltinTypeOCLImage2dMSAARO:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAARO:
+ case ZigClangBuiltinTypeOCLImage2dMSAADepthRO:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO:
+ case ZigClangBuiltinTypeOCLImage3dRO:
+ case ZigClangBuiltinTypeOCLImage1dWO:
+ case ZigClangBuiltinTypeOCLImage1dArrayWO:
+ case ZigClangBuiltinTypeOCLImage1dBufferWO:
+ case ZigClangBuiltinTypeOCLImage2dWO:
+ case ZigClangBuiltinTypeOCLImage2dArrayWO:
+ case ZigClangBuiltinTypeOCLImage2dDepthWO:
+ case ZigClangBuiltinTypeOCLImage2dArrayDepthWO:
+ case ZigClangBuiltinTypeOCLImage2dMSAAWO:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAAWO:
+ case ZigClangBuiltinTypeOCLImage2dMSAADepthWO:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO:
+ case ZigClangBuiltinTypeOCLImage3dWO:
+ case ZigClangBuiltinTypeOCLImage1dRW:
+ case ZigClangBuiltinTypeOCLImage1dArrayRW:
+ case ZigClangBuiltinTypeOCLImage1dBufferRW:
+ case ZigClangBuiltinTypeOCLImage2dRW:
+ case ZigClangBuiltinTypeOCLImage2dArrayRW:
+ case ZigClangBuiltinTypeOCLImage2dDepthRW:
+ case ZigClangBuiltinTypeOCLImage2dArrayDepthRW:
+ case ZigClangBuiltinTypeOCLImage2dMSAARW:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAARW:
+ case ZigClangBuiltinTypeOCLImage2dMSAADepthRW:
+ case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW:
+ case ZigClangBuiltinTypeOCLImage3dRW:
+ case ZigClangBuiltinTypeOCLSampler:
+ case ZigClangBuiltinTypeOCLEvent:
+ case ZigClangBuiltinTypeOCLClkEvent:
+ case ZigClangBuiltinTypeOCLQueue:
+ case ZigClangBuiltinTypeOCLReserveID:
+ case ZigClangBuiltinTypeShortAccum:
+ case ZigClangBuiltinTypeAccum:
+ case ZigClangBuiltinTypeLongAccum:
+ case ZigClangBuiltinTypeUShortAccum:
+ case ZigClangBuiltinTypeUAccum:
+ case ZigClangBuiltinTypeULongAccum:
+ case ZigClangBuiltinTypeShortFract:
+ case ZigClangBuiltinTypeFract:
+ case ZigClangBuiltinTypeLongFract:
+ case ZigClangBuiltinTypeUShortFract:
+ case ZigClangBuiltinTypeUFract:
+ case ZigClangBuiltinTypeULongFract:
+ case ZigClangBuiltinTypeSatShortAccum:
+ case ZigClangBuiltinTypeSatAccum:
+ case ZigClangBuiltinTypeSatLongAccum:
+ case ZigClangBuiltinTypeSatUShortAccum:
+ case ZigClangBuiltinTypeSatUAccum:
+ case ZigClangBuiltinTypeSatULongAccum:
+ case ZigClangBuiltinTypeSatShortFract:
+ case ZigClangBuiltinTypeSatFract:
+ case ZigClangBuiltinTypeSatLongFract:
+ case ZigClangBuiltinTypeSatUShortFract:
+ case ZigClangBuiltinTypeSatUFract:
+ case ZigClangBuiltinTypeSatULongFract:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin:
+ case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin:
return res;
}
break;
}
- case clang::Type::Pointer:
- return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
- trans_create_node_unsigned(c, 0));
+ case ZigClangType_Pointer:
+ return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
- case clang::Type::Typedef:
+ case ZigClangType_Typedef:
{
- const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
- const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
- auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
+ const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
+ const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
+ auto existing_entry = c->decl_table.maybe_get((void*)ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl));
if (existing_entry) {
return existing_entry->value;
}
@@ -2677,19 +2844,20 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
return res;
}
- case clang::Type::Enum:
+ case ZigClangType_Enum:
{
- const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);
- AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());
+ const ZigClangEnumType *enum_ty = reinterpret_cast<const ZigClangEnumType *>(ty);
+ AstNode *enum_type = resolve_enum_decl(c, ZigClangEnumType_getDecl(enum_ty));
return to_enum_zero_cmp(c, res, enum_type);
}
- case clang::Type::Elaborated:
+ case ZigClangType_Elaborated:
{
- const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
+ const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty);
switch (elaborated_ty->getKeyword()) {
case clang::ETK_Enum: {
- AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginLoc());
+ AstNode *enum_type = trans_qual_type(c, bitcast(elaborated_ty->getNamedType()),
+ ZigClangExpr_getBeginLoc(expr));
return to_enum_zero_cmp(c, res, enum_type);
}
case clang::ETK_Struct:
@@ -2702,48 +2870,48 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
}
}
- case clang::Type::FunctionProto:
- case clang::Type::Record:
- case clang::Type::ConstantArray:
- case clang::Type::Paren:
- case clang::Type::Decayed:
- case clang::Type::Attributed:
- case clang::Type::IncompleteArray:
- case clang::Type::BlockPointer:
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- case clang::Type::MemberPointer:
- case clang::Type::VariableArray:
- case clang::Type::DependentSizedArray:
- case clang::Type::DependentSizedExtVector:
- case clang::Type::Vector:
- case clang::Type::ExtVector:
- case clang::Type::FunctionNoProto:
- case clang::Type::UnresolvedUsing:
- case clang::Type::Adjusted:
- case clang::Type::TypeOfExpr:
- case clang::Type::TypeOf:
- case clang::Type::Decltype:
- case clang::Type::UnaryTransform:
- case clang::Type::TemplateTypeParm:
- case clang::Type::SubstTemplateTypeParm:
- case clang::Type::SubstTemplateTypeParmPack:
- case clang::Type::TemplateSpecialization:
- case clang::Type::Auto:
- case clang::Type::InjectedClassName:
- case clang::Type::DependentName:
- case clang::Type::DependentTemplateSpecialization:
- case clang::Type::PackExpansion:
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- case clang::Type::Complex:
- case clang::Type::ObjCObjectPointer:
- case clang::Type::Atomic:
- case clang::Type::Pipe:
- case clang::Type::ObjCTypeParam:
- case clang::Type::DeducedTemplateSpecialization:
- case clang::Type::DependentAddressSpace:
- case clang::Type::DependentVector:
+ case ZigClangType_FunctionProto:
+ case ZigClangType_Record:
+ case ZigClangType_ConstantArray:
+ case ZigClangType_Paren:
+ case ZigClangType_Decayed:
+ case ZigClangType_Attributed:
+ case ZigClangType_IncompleteArray:
+ case ZigClangType_BlockPointer:
+ case ZigClangType_LValueReference:
+ case ZigClangType_RValueReference:
+ case ZigClangType_MemberPointer:
+ case ZigClangType_VariableArray:
+ case ZigClangType_DependentSizedArray:
+ case ZigClangType_DependentSizedExtVector:
+ case ZigClangType_Vector:
+ case ZigClangType_ExtVector:
+ case ZigClangType_FunctionNoProto:
+ case ZigClangType_UnresolvedUsing:
+ case ZigClangType_Adjusted:
+ case ZigClangType_TypeOfExpr:
+ case ZigClangType_TypeOf:
+ case ZigClangType_Decltype:
+ case ZigClangType_UnaryTransform:
+ case ZigClangType_TemplateTypeParm:
+ case ZigClangType_SubstTemplateTypeParm:
+ case ZigClangType_SubstTemplateTypeParmPack:
+ case ZigClangType_TemplateSpecialization:
+ case ZigClangType_Auto:
+ case ZigClangType_InjectedClassName:
+ case ZigClangType_DependentName:
+ case ZigClangType_DependentTemplateSpecialization:
+ case ZigClangType_PackExpansion:
+ case ZigClangType_ObjCObject:
+ case ZigClangType_ObjCInterface:
+ case ZigClangType_Complex:
+ case ZigClangType_ObjCObjectPointer:
+ case ZigClangType_Atomic:
+ case ZigClangType_Pipe:
+ case ZigClangType_ObjCTypeParam:
+ case ZigClangType_DeducedTemplateSpecialization:
+ case ZigClangType_DependentAddressSpace:
+ case ZigClangType_DependentVector:
return res;
}
zig_unreachable();
@@ -2752,11 +2920,12 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) {
TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
- while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
+ while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope,
+ bitcast(stmt->getCond()), TransRValue);
if (while_scope->node->data.while_expr.condition == nullptr)
return nullptr;
- TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(),
+ TransScope *body_scope = trans_stmt(c, &while_scope->base, bitcast(stmt->getBody()),
&while_scope->node->data.while_expr.body);
if (body_scope == nullptr)
return nullptr;
@@ -2769,17 +2938,18 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::I
// if (c) t else e
AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
- TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block);
+ TransScope *then_scope = trans_stmt(c, scope, bitcast(stmt->getThen()), &if_node->data.if_bool_expr.then_block);
if (then_scope == nullptr)
return nullptr;
if (stmt->getElse() != nullptr) {
- TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node);
+ TransScope *else_scope = trans_stmt(c, scope, bitcast(stmt->getElse()), &if_node->data.if_bool_expr.else_node);
if (else_scope == nullptr)
return nullptr;
}
- if_node->data.if_bool_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
+ if_node->data.if_bool_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, bitcast(stmt->getCond()),
+ TransRValue);
if (if_node->data.if_bool_expr.condition == nullptr)
return nullptr;
@@ -2789,18 +2959,18 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::I
static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) {
AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
- AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue);
+ AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getCallee()), TransRValue);
if (callee_raw_node == nullptr)
return nullptr;
bool is_ptr = false;
- const clang::FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);
+ const clang::FunctionProtoType *fn_ty = qual_type_get_fn_proto(bitcast(stmt->getCallee()->getType()), &is_ptr);
AstNode *callee_node = nullptr;
if (is_ptr && fn_ty) {
- if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
+ if ((ZigClangStmtClass)stmt->getCallee()->getStmtClass() == ZigClangStmt_ImplicitCastExprClass) {
const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee());
- if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) {
- if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) {
+ if ((ZigClangCK)implicit_cast->getCastKind() == ZigClangCK_FunctionToPointerDecay) {
+ if ((ZigClangStmtClass)implicit_cast->getSubExpr()->getStmtClass() == ZigClangStmt_DeclRefExprClass) {
const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr());
const clang::Decl *decl = decl_ref->getFoundDecl();
if (decl->getKind() == clang::Decl::Function) {
@@ -2819,7 +2989,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
node->data.fn_call_expr.fn_ref_expr = callee_node;
unsigned num_args = stmt->getNumArgs();
- const clang::Expr * const* args = stmt->getArgs();
+ const ZigClangExpr * const* args = reinterpret_cast<const ZigClangExpr * const*>(stmt->getArgs());
for (unsigned i = 0; i < num_args; i += 1) {
AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);
if (arg_node == nullptr)
@@ -2828,7 +2998,9 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
node->data.fn_call_expr.params.append(arg_node);
}
- if (result_used == ResultUsedNo && fn_ty && !qual_type_canon(fn_ty->getReturnType())->isVoidType()) {
+ if (result_used == ResultUsedNo && fn_ty &&
+ !ZigClangType_isVoidType(qual_type_canon(bitcast(fn_ty->getReturnType()))))
+ {
node = trans_create_node_bin_op(c, trans_create_node_symbol_str(c, "_"), BinOpTypeAssign, node);
}
@@ -2838,7 +3010,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope *scope,
const clang::MemberExpr *stmt)
{
- AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
+ AstNode *container_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getBase()), TransRValue);
if (container_node == nullptr)
return nullptr;
@@ -2846,18 +3018,18 @@ static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope
container_node = trans_create_node_unwrap_null(c, container_node);
}
- const char *name = decl_name(stmt->getMemberDecl());
+ const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)stmt->getMemberDecl());
AstNode *node = trans_create_node_field_access_str(c, container_node, name);
return maybe_suppress_result(c, result_used, node);
}
static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ArraySubscriptExpr *stmt) {
- AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
+ AstNode *container_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getBase()), TransRValue);
if (container_node == nullptr)
return nullptr;
- AstNode *idx_node = trans_expr(c, ResultUsedYes, scope, stmt->getIdx(), TransRValue);
+ AstNode *idx_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getIdx()), TransRValue);
if (idx_node == nullptr)
return nullptr;
@@ -2871,11 +3043,12 @@ static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, T
static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,
const clang::CStyleCastExpr *stmt, TransLRValue lrvalue)
{
- AstNode *sub_expr_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), lrvalue);
+ AstNode *sub_expr_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), lrvalue);
if (sub_expr_node == nullptr)
return nullptr;
- AstNode *cast = trans_c_cast(c, stmt->getBeginLoc(), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node);
+ AstNode *cast = trans_c_cast(c, bitcast(stmt->getBeginLoc()), bitcast(stmt->getType()),
+ bitcast(stmt->getSubExpr()->getType()), sub_expr_node);
if (cast == nullptr)
return nullptr;
@@ -2885,7 +3058,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran
static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, ResultUsed result_used,
TransScope *scope, const clang::UnaryExprOrTypeTraitExpr *stmt)
{
- AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getBeginLoc());
+ AstNode *type_node = trans_qual_type(c, bitcast(stmt->getTypeOfArgument()), bitcast(stmt->getBeginLoc()));
if (type_node == nullptr)
return nullptr;
@@ -2901,7 +3074,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:
AstNode *body_node;
TransScope *child_scope;
- if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) {
+ if ((ZigClangStmtClass)stmt->getBody()->getStmtClass() == ZigClangStmt_CompoundStmtClass) {
// there's already a block in C, so we'll append our condition to it.
// c: do {
// c: a;
@@ -2914,7 +3087,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:
// zig: }
// We call the low level function so that we can set child_scope to the scope of the generated block.
- if (trans_stmt_extra(c, &while_scope->base, stmt->getBody(), ResultUsedNo, TransRValue, &body_node,
+ if (trans_stmt_extra(c, &while_scope->base, bitcast(stmt->getBody()), ResultUsedNo, TransRValue, &body_node,
nullptr, &child_scope))
{
return nullptr;
@@ -2932,7 +3105,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:
TransScopeBlock *child_block_scope = trans_scope_block_create(c, &while_scope->base);
body_node = child_block_scope->node;
AstNode *child_statement;
- child_scope = trans_stmt(c, &child_block_scope->base, stmt->getBody(), &child_statement);
+ child_scope = trans_stmt(c, &child_block_scope->base, bitcast(stmt->getBody()), &child_statement);
if (child_scope == nullptr) return nullptr;
if (child_statement != nullptr) {
body_node->data.block.statements.append(child_statement);
@@ -2940,7 +3113,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:
}
// if (!cond) break;
- AstNode *condition_node = trans_expr(c, ResultUsedYes, child_scope, stmt->getCond(), TransRValue);
+ AstNode *condition_node = trans_expr(c, ResultUsedYes, child_scope, bitcast(stmt->getCond()), TransRValue);
if (condition_node == nullptr) return nullptr;
AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr);
terminator_node->data.if_bool_expr.condition = trans_create_node_prefix_op(c, PrefixOpBoolNot, condition_node);
@@ -2958,7 +3131,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang
AstNode *loop_block_node;
TransScopeWhile *while_scope;
TransScope *cond_scope;
- const clang::Stmt *init_stmt = stmt->getInit();
+ const ZigClangStmt *init_stmt = bitcast(stmt->getInit());
if (init_stmt == nullptr) {
while_scope = trans_scope_while_create(c, parent_scope);
loop_block_node = while_scope->node;
@@ -2979,35 +3152,27 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang
child_scope->node->data.block.statements.append(while_scope->node);
}
- const clang::Stmt *cond_stmt = stmt->getCond();
- if (cond_stmt == nullptr) {
+ const ZigClangExpr *cond_expr = bitcast(stmt->getCond());
+ if (cond_expr == nullptr) {
while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
} else {
- if (clang::Expr::classof(cond_stmt)) {
- const clang::Expr *cond_expr = static_cast<const clang::Expr*>(cond_stmt);
- while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
+ while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope,
+ cond_expr, TransRValue);
- if (while_scope->node->data.while_expr.condition == nullptr)
- return nullptr;
- } else {
- TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt,
- &while_scope->node->data.while_expr.condition);
- if (end_cond_scope == nullptr)
- return nullptr;
- }
+ if (while_scope->node->data.while_expr.condition == nullptr)
+ return nullptr;
}
- const clang::Stmt *inc_stmt = stmt->getInc();
- if (inc_stmt != nullptr) {
- AstNode *inc_node;
- TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node);
- if (inc_scope == nullptr)
+ const ZigClangExpr *inc_expr = bitcast(stmt->getInc());
+ if (inc_expr != nullptr) {
+ AstNode *inc_node = trans_expr(c, ResultUsedNo, cond_scope, inc_expr, TransRValue);
+ if (inc_node == nullptr)
return nullptr;
while_scope->node->data.while_expr.continue_expr = inc_node;
}
AstNode *body_statement;
- TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(), &body_statement);
+ TransScope *body_scope = trans_stmt(c, &while_scope->base, bitcast(stmt->getBody()), &body_statement);
if (body_scope == nullptr)
return nullptr;
@@ -3030,7 +3195,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl
switch_scope = trans_scope_switch_create(c, &block_scope->base);
} else {
AstNode *vars_node;
- TransScope *var_scope = trans_stmt(c, &block_scope->base, var_decl_stmt, &vars_node);
+ TransScope *var_scope = trans_stmt(c, &block_scope->base, (const ZigClangStmt *)var_decl_stmt, &vars_node);
if (var_scope == nullptr)
return nullptr;
if (vars_node != nullptr)
@@ -3044,7 +3209,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl
switch_scope->end_label_name = end_label_name;
block_scope->node->data.block.name = end_label_name;
- const clang::Expr *cond_expr = stmt->getCond();
+ const ZigClangExpr *cond_expr = bitcast(stmt->getCond());
assert(cond_expr != nullptr);
AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue);
@@ -3053,9 +3218,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl
switch_scope->switch_node->data.switch_expr.expr = expr_node;
AstNode *body_node;
- const clang::Stmt *body_stmt = stmt->getBody();
- if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) {
- if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt,
+ const ZigClangStmt *body_stmt = bitcast(stmt->getBody());
+ if (ZigClangStmt_getStmtClass(body_stmt) == ZigClangStmt_CompoundStmtClass) {
+ if (trans_compound_stmt_inline(c, &switch_scope->base, (const ZigClangCompoundStmt *)body_stmt,
block_scope->node, nullptr))
{
return nullptr;
@@ -3092,7 +3257,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::
*out_node = nullptr;
if (stmt->getRHS() != nullptr) {
- emit_warning(c, stmt->getBeginLoc(), "TODO support GNU switch case a ... b extension");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support GNU switch case a ... b extension");
return ErrorUnexpected;
}
@@ -3105,7 +3270,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::
{
// Add the prong
AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng);
- AstNode *item_node = trans_expr(c, ResultUsedYes, &switch_scope->base, stmt->getLHS(), TransRValue);
+ AstNode *item_node = trans_expr(c, ResultUsedYes, &switch_scope->base, bitcast(stmt->getLHS()), TransRValue);
if (item_node == nullptr)
return ErrorUnexpected;
prong_node->data.switch_prong.items.append(item_node);
@@ -3122,7 +3287,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::
scope_block->node->data.block.statements.append(case_block);
AstNode *sub_stmt_node;
- TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node);
+ TransScope *new_scope = trans_stmt(c, parent_scope, bitcast(stmt->getSubStmt()), &sub_stmt_node);
if (new_scope == nullptr)
return ErrorUnexpected;
if (sub_stmt_node != nullptr)
@@ -3159,7 +3324,7 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const clan
scope_block->node->data.block.statements.append(case_block);
AstNode *sub_stmt_node;
- TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node);
+ TransScope *new_scope = trans_stmt(c, parent_scope, bitcast(stmt->getSubStmt()), &sub_stmt_node);
if (new_scope == nullptr)
return ErrorUnexpected;
if (sub_stmt_node != nullptr)
@@ -3177,13 +3342,13 @@ static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransSc
return maybe_suppress_result(c, result_used, node);
}
case clang::StringLiteral::UTF16:
- emit_warning(c, stmt->getBeginLoc(), "TODO support UTF16 string literals");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF16 string literals");
return nullptr;
case clang::StringLiteral::UTF32:
- emit_warning(c, stmt->getBeginLoc(), "TODO support UTF32 string literals");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF32 string literals");
return nullptr;
case clang::StringLiteral::Wide:
- emit_warning(c, stmt->getBeginLoc(), "TODO support wide string literals");
+ emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support wide string literals");
return nullptr;
}
zig_unreachable();
@@ -3222,45 +3387,45 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_
return ErrorNone;
}
-static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
+static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *stmt,
ResultUsed result_used, TransLRValue lrvalue,
AstNode **out_node, TransScope **out_child_scope,
TransScope **out_node_scope)
{
- clang::Stmt::StmtClass sc = stmt->getStmtClass();
+ ZigClangStmtClass sc = ZigClangStmt_getStmtClass(stmt);
switch (sc) {
- case clang::Stmt::ReturnStmtClass:
+ case ZigClangStmt_ReturnStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));
- case clang::Stmt::CompoundStmtClass:
+ case ZigClangStmt_CompoundStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));
- case clang::Stmt::IntegerLiteralClass:
+ trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt, out_node_scope));
+ case ZigClangStmt_IntegerLiteralClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_integer_literal(c, result_used, (const clang::IntegerLiteral *)stmt));
- case clang::Stmt::ConditionalOperatorClass:
+ case ZigClangStmt_ConditionalOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));
- case clang::Stmt::BinaryOperatorClass:
+ case ZigClangStmt_BinaryOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt));
- case clang::Stmt::CompoundAssignOperatorClass:
+ case ZigClangStmt_CompoundAssignOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));
- case clang::Stmt::ImplicitCastExprClass:
+ case ZigClangStmt_ImplicitCastExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_implicit_cast_expr(c, result_used, scope, (const clang::ImplicitCastExpr *)stmt));
- case clang::Stmt::DeclRefExprClass:
+ case ZigClangStmt_DeclRefExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));
- case clang::Stmt::UnaryOperatorClass:
+ case ZigClangStmt_UnaryOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt));
- case clang::Stmt::DeclStmtClass:
+ case ZigClangStmt_DeclStmtClass:
return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope);
- case clang::Stmt::DoStmtClass:
- case clang::Stmt::WhileStmtClass: {
- AstNode *while_node = sc == clang::Stmt::DoStmtClass
+ case ZigClangStmt_DoStmtClass:
+ case ZigClangStmt_WhileStmtClass: {
+ AstNode *while_node = sc == ZigClangStmt_DoStmtClass
? trans_do_loop(c, scope, (const clang::DoStmt *)stmt)
: trans_while_loop(c, scope, (const clang::WhileStmt *)stmt);
@@ -3273,572 +3438,574 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st
return wrap_stmt(out_node, out_child_scope, scope, while_node);
}
- case clang::Stmt::IfStmtClass:
+ case ZigClangStmt_IfStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_if_statement(c, scope, (const clang::IfStmt *)stmt));
- case clang::Stmt::CallExprClass:
+ case ZigClangStmt_CallExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));
- case clang::Stmt::NullStmtClass:
+ case ZigClangStmt_NullStmtClass:
*out_node = trans_create_node(c, NodeTypeBlock);
*out_child_scope = scope;
return ErrorNone;
- case clang::Stmt::MemberExprClass:
+ case ZigClangStmt_MemberExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_member_expr(c, result_used, scope, (const clang::MemberExpr *)stmt));
- case clang::Stmt::ArraySubscriptExprClass:
+ case ZigClangStmt_ArraySubscriptExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_array_subscript_expr(c, result_used, scope, (const clang::ArraySubscriptExpr *)stmt));
- case clang::Stmt::CStyleCastExprClass:
+ case ZigClangStmt_CStyleCastExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));
- case clang::Stmt::UnaryExprOrTypeTraitExprClass:
+ case ZigClangStmt_UnaryExprOrTypeTraitExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_unary_expr_or_type_trait_expr(c, result_used, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
- case clang::Stmt::ForStmtClass: {
+ case ZigClangStmt_ForStmtClass: {
AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);
return wrap_stmt(out_node, out_child_scope, scope, node);
}
- case clang::Stmt::StringLiteralClass:
+ case ZigClangStmt_StringLiteralClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_string_literal(c, result_used, scope, (const clang::StringLiteral *)stmt));
- case clang::Stmt::BreakStmtClass:
+ case ZigClangStmt_BreakStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));
- case clang::Stmt::ContinueStmtClass:
+ case ZigClangStmt_ContinueStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt));
- case clang::Stmt::ParenExprClass:
+ case ZigClangStmt_ParenExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue));
- case clang::Stmt::SwitchStmtClass:
+ trans_expr(c, result_used, scope,
+ bitcast(((const clang::ParenExpr*)stmt)->getSubExpr()), lrvalue));
+ case ZigClangStmt_SwitchStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt));
- case clang::Stmt::CaseStmtClass:
+ case ZigClangStmt_CaseStmtClass:
return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope);
- case clang::Stmt::DefaultStmtClass:
+ case ZigClangStmt_DefaultStmtClass:
return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope);
- case clang::Stmt::ConstantExprClass:
+ case ZigClangStmt_ConstantExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_constant_expr(c, result_used, (const clang::ConstantExpr *)stmt));
- case clang::Stmt::PredefinedExprClass:
+ case ZigClangStmt_PredefinedExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_predefined_expr(c, result_used, scope, (const clang::PredefinedExpr *)stmt));
- case clang::Stmt::StmtExprClass:
+ case ZigClangStmt_StmtExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
trans_stmt_expr(c, result_used, scope, (const clang::StmtExpr *)stmt, out_node_scope));
- case clang::Stmt::NoStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoStmtClass");
- return ErrorUnexpected;
- case clang::Stmt::GCCAsmStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C GCCAsmStmtClass");
+ case ZigClangStmt_NoStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C NoStmtClass");
return ErrorUnexpected;
- case clang::Stmt::MSAsmStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSAsmStmtClass");
+ case ZigClangStmt_GCCAsmStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GCCAsmStmtClass");
return ErrorUnexpected;
- case clang::Stmt::AttributedStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C AttributedStmtClass");
+ case ZigClangStmt_MSAsmStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSAsmStmtClass");
return ErrorUnexpected;
- case clang::Stmt::CXXCatchStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXCatchStmtClass");
+ case ZigClangStmt_AttributedStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AttributedStmtClass");
return ErrorUnexpected;
- case clang::Stmt::CXXForRangeStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXForRangeStmtClass");
+ case ZigClangStmt_CXXCatchStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXCatchStmtClass");
return ErrorUnexpected;
- case clang::Stmt::CXXTryStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTryStmtClass");
+ case ZigClangStmt_CXXForRangeStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXForRangeStmtClass");
return ErrorUnexpected;
- case clang::Stmt::CapturedStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CapturedStmtClass");
+ case ZigClangStmt_CXXTryStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTryStmtClass");
return ErrorUnexpected;
- case clang::Stmt::CoreturnStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoreturnStmtClass");
+ case ZigClangStmt_CapturedStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CapturedStmtClass");
return ErrorUnexpected;
- case clang::Stmt::CoroutineBodyStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoroutineBodyStmtClass");
+ case ZigClangStmt_CoreturnStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoreturnStmtClass");
return ErrorUnexpected;
- case clang::Stmt::BinaryConditionalOperatorClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C BinaryConditionalOperatorClass");
+ case ZigClangStmt_CoroutineBodyStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoroutineBodyStmtClass");
return ErrorUnexpected;
- case clang::Stmt::AddrLabelExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C AddrLabelExprClass");
+ case ZigClangStmt_BinaryConditionalOperatorClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C BinaryConditionalOperatorClass");
return ErrorUnexpected;
- case clang::Stmt::ArrayInitIndexExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitIndexExprClass");
+ case ZigClangStmt_AddrLabelExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AddrLabelExprClass");
return ErrorUnexpected;
- case clang::Stmt::ArrayInitLoopExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitLoopExprClass");
+ case ZigClangStmt_ArrayInitIndexExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayInitIndexExprClass");
return ErrorUnexpected;
- case clang::Stmt::ArrayTypeTraitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayTypeTraitExprClass");
+ case ZigClangStmt_ArrayInitLoopExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayInitLoopExprClass");
return ErrorUnexpected;
- case clang::Stmt::AsTypeExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C AsTypeExprClass");
+ case ZigClangStmt_ArrayTypeTraitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayTypeTraitExprClass");
return ErrorUnexpected;
- case clang::Stmt::AtomicExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C AtomicExprClass");
+ case ZigClangStmt_AsTypeExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AsTypeExprClass");
return ErrorUnexpected;
- case clang::Stmt::BlockExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C BlockExprClass");
+ case ZigClangStmt_AtomicExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AtomicExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXBindTemporaryExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBindTemporaryExprClass");
+ case ZigClangStmt_BlockExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C BlockExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXBoolLiteralExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBoolLiteralExprClass");
+ case ZigClangStmt_CXXBindTemporaryExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXBindTemporaryExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXConstructExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstructExprClass");
+ case ZigClangStmt_CXXBoolLiteralExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXBoolLiteralExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXTemporaryObjectExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTemporaryObjectExprClass");
+ case ZigClangStmt_CXXConstructExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXConstructExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXDefaultArgExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultArgExprClass");
+ case ZigClangStmt_CXXTemporaryObjectExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTemporaryObjectExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXDefaultInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultInitExprClass");
+ case ZigClangStmt_CXXDefaultArgExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDefaultArgExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXDeleteExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDeleteExprClass");
+ case ZigClangStmt_CXXDefaultInitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDefaultInitExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXDependentScopeMemberExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDependentScopeMemberExprClass");
+ case ZigClangStmt_CXXDeleteExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDeleteExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXFoldExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFoldExprClass");
+ case ZigClangStmt_CXXDependentScopeMemberExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDependentScopeMemberExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXInheritedCtorInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXInheritedCtorInitExprClass");
+ case ZigClangStmt_CXXFoldExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXFoldExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXNewExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNewExprClass");
+ case ZigClangStmt_CXXInheritedCtorInitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXInheritedCtorInitExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXNoexceptExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNoexceptExprClass");
+ case ZigClangStmt_CXXNewExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNewExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXNullPtrLiteralExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNullPtrLiteralExprClass");
+ case ZigClangStmt_CXXNoexceptExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNoexceptExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXPseudoDestructorExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXPseudoDestructorExprClass");
+ case ZigClangStmt_CXXNullPtrLiteralExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNullPtrLiteralExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXScalarValueInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXScalarValueInitExprClass");
+ case ZigClangStmt_CXXPseudoDestructorExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXPseudoDestructorExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXStdInitializerListExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStdInitializerListExprClass");
+ case ZigClangStmt_CXXScalarValueInitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXScalarValueInitExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXThisExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThisExprClass");
+ case ZigClangStmt_CXXStdInitializerListExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXStdInitializerListExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXThrowExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThrowExprClass");
+ case ZigClangStmt_CXXThisExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXThisExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXTypeidExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTypeidExprClass");
+ case ZigClangStmt_CXXThrowExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXThrowExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXUnresolvedConstructExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUnresolvedConstructExprClass");
+ case ZigClangStmt_CXXTypeidExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTypeidExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXUuidofExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUuidofExprClass");
+ case ZigClangStmt_CXXUnresolvedConstructExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXUnresolvedConstructExprClass");
return ErrorUnexpected;
- case clang::Stmt::CUDAKernelCallExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CUDAKernelCallExprClass");
+ case ZigClangStmt_CXXUuidofExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXUuidofExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXMemberCallExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXMemberCallExprClass");
+ case ZigClangStmt_CUDAKernelCallExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CUDAKernelCallExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXOperatorCallExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXOperatorCallExprClass");
+ case ZigClangStmt_CXXMemberCallExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXMemberCallExprClass");
return ErrorUnexpected;
- case clang::Stmt::UserDefinedLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UserDefinedLiteralClass");
+ case ZigClangStmt_CXXOperatorCallExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXOperatorCallExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXFunctionalCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFunctionalCastExprClass");
+ case ZigClangStmt_UserDefinedLiteralClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UserDefinedLiteralClass");
return ErrorUnexpected;
- case clang::Stmt::CXXConstCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstCastExprClass");
+ case ZigClangStmt_CXXFunctionalCastExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXFunctionalCastExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXDynamicCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDynamicCastExprClass");
+ case ZigClangStmt_CXXConstCastExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXConstCastExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXReinterpretCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXReinterpretCastExprClass");
+ case ZigClangStmt_CXXDynamicCastExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDynamicCastExprClass");
return ErrorUnexpected;
- case clang::Stmt::CXXStaticCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStaticCastExprClass");
+ case ZigClangStmt_CXXReinterpretCastExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXReinterpretCastExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCBridgedCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBridgedCastExprClass");
+ case ZigClangStmt_CXXStaticCastExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXStaticCastExprClass");
return ErrorUnexpected;
- case clang::Stmt::CharacterLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CharacterLiteralClass");
+ case ZigClangStmt_ObjCBridgedCastExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass");
return ErrorUnexpected;
- case clang::Stmt::ChooseExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ChooseExprClass");
+ case ZigClangStmt_CharacterLiteralClass:
+ return wrap_stmt(out_node, out_child_scope, scope,
+ trans_character_literal(c, result_used, (const clang::CharacterLiteral *)stmt));
return ErrorUnexpected;
- case clang::Stmt::CompoundLiteralExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CompoundLiteralExprClass");
+ case ZigClangStmt_ChooseExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ChooseExprClass");
return ErrorUnexpected;
- case clang::Stmt::ConvertVectorExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ConvertVectorExprClass");
+ case ZigClangStmt_CompoundLiteralExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CompoundLiteralExprClass");
return ErrorUnexpected;
- case clang::Stmt::CoawaitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoawaitExprClass");
+ case ZigClangStmt_ConvertVectorExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ConvertVectorExprClass");
return ErrorUnexpected;
- case clang::Stmt::CoyieldExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoyieldExprClass");
+ case ZigClangStmt_CoawaitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoawaitExprClass");
return ErrorUnexpected;
- case clang::Stmt::DependentCoawaitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentCoawaitExprClass");
+ case ZigClangStmt_CoyieldExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoyieldExprClass");
return ErrorUnexpected;
- case clang::Stmt::DependentScopeDeclRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentScopeDeclRefExprClass");
+ case ZigClangStmt_DependentCoawaitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DependentCoawaitExprClass");
return ErrorUnexpected;
- case clang::Stmt::DesignatedInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitExprClass");
+ case ZigClangStmt_DependentScopeDeclRefExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DependentScopeDeclRefExprClass");
return ErrorUnexpected;
- case clang::Stmt::DesignatedInitUpdateExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitUpdateExprClass");
+ case ZigClangStmt_DesignatedInitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DesignatedInitExprClass");
return ErrorUnexpected;
- case clang::Stmt::ExpressionTraitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExpressionTraitExprClass");
+ case ZigClangStmt_DesignatedInitUpdateExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DesignatedInitUpdateExprClass");
return ErrorUnexpected;
- case clang::Stmt::ExtVectorElementExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExtVectorElementExprClass");
+ case ZigClangStmt_ExpressionTraitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExpressionTraitExprClass");
return ErrorUnexpected;
- case clang::Stmt::FixedPointLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C FixedPointLiteralClass");
+ case ZigClangStmt_ExtVectorElementExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExtVectorElementExprClass");
return ErrorUnexpected;
- case clang::Stmt::FloatingLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C FloatingLiteralClass");
+ case ZigClangStmt_FixedPointLiteralClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass");
return ErrorUnexpected;
- case clang::Stmt::ExprWithCleanupsClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExprWithCleanupsClass");
+ case ZigClangStmt_FloatingLiteralClass:
+ return wrap_stmt(out_node, out_child_scope, scope,
+ trans_floating_literal(c, result_used, (const clang::FloatingLiteral *)stmt));
+ case ZigClangStmt_ExprWithCleanupsClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExprWithCleanupsClass");
return ErrorUnexpected;
- case clang::Stmt::FunctionParmPackExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C FunctionParmPackExprClass");
+ case ZigClangStmt_FunctionParmPackExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FunctionParmPackExprClass");
return ErrorUnexpected;
- case clang::Stmt::GNUNullExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C GNUNullExprClass");
+ case ZigClangStmt_GNUNullExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GNUNullExprClass");
return ErrorUnexpected;
- case clang::Stmt::GenericSelectionExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C GenericSelectionExprClass");
+ case ZigClangStmt_GenericSelectionExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GenericSelectionExprClass");
return ErrorUnexpected;
- case clang::Stmt::ImaginaryLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImaginaryLiteralClass");
+ case ZigClangStmt_ImaginaryLiteralClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ImaginaryLiteralClass");
return ErrorUnexpected;
- case clang::Stmt::ImplicitValueInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImplicitValueInitExprClass");
+ case ZigClangStmt_ImplicitValueInitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ImplicitValueInitExprClass");
return ErrorUnexpected;
- case clang::Stmt::InitListExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C InitListExprClass");
+ case ZigClangStmt_InitListExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C InitListExprClass");
return ErrorUnexpected;
- case clang::Stmt::LambdaExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C LambdaExprClass");
+ case ZigClangStmt_LambdaExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C LambdaExprClass");
return ErrorUnexpected;
- case clang::Stmt::MSPropertyRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertyRefExprClass");
+ case ZigClangStmt_MSPropertyRefExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSPropertyRefExprClass");
return ErrorUnexpected;
- case clang::Stmt::MSPropertySubscriptExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertySubscriptExprClass");
+ case ZigClangStmt_MSPropertySubscriptExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSPropertySubscriptExprClass");
return ErrorUnexpected;
- case clang::Stmt::MaterializeTemporaryExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MaterializeTemporaryExprClass");
+ case ZigClangStmt_MaterializeTemporaryExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MaterializeTemporaryExprClass");
return ErrorUnexpected;
- case clang::Stmt::NoInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoInitExprClass");
+ case ZigClangStmt_NoInitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C NoInitExprClass");
return ErrorUnexpected;
- case clang::Stmt::OMPArraySectionExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPArraySectionExprClass");
+ case ZigClangStmt_OMPArraySectionExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPArraySectionExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCArrayLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCArrayLiteralClass");
+ case ZigClangStmt_ObjCArrayLiteralClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCArrayLiteralClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCAvailabilityCheckExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAvailabilityCheckExprClass");
+ case ZigClangStmt_ObjCAvailabilityCheckExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAvailabilityCheckExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCBoolLiteralExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoolLiteralExprClass");
+ case ZigClangStmt_ObjCBoolLiteralExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBoolLiteralExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCBoxedExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoxedExprClass");
+ case ZigClangStmt_ObjCBoxedExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBoxedExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCDictionaryLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCDictionaryLiteralClass");
+ case ZigClangStmt_ObjCDictionaryLiteralClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCDictionaryLiteralClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCEncodeExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCEncodeExprClass");
+ case ZigClangStmt_ObjCEncodeExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCEncodeExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCIndirectCopyRestoreExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIndirectCopyRestoreExprClass");
+ case ZigClangStmt_ObjCIndirectCopyRestoreExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIndirectCopyRestoreExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCIsaExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIsaExprClass");
+ case ZigClangStmt_ObjCIsaExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIsaExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCIvarRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIvarRefExprClass");
+ case ZigClangStmt_ObjCIvarRefExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIvarRefExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCMessageExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCMessageExprClass");
+ case ZigClangStmt_ObjCMessageExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCMessageExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCPropertyRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCPropertyRefExprClass");
+ case ZigClangStmt_ObjCPropertyRefExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCPropertyRefExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCProtocolExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProtocolExprClass");
+ case ZigClangStmt_ObjCProtocolExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCProtocolExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCSelectorExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSelectorExprClass");
+ case ZigClangStmt_ObjCSelectorExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCSelectorExprClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCStringLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCStringLiteralClass");
+ case ZigClangStmt_ObjCStringLiteralClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCStringLiteralClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCSubscriptRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSubscriptRefExprClass");
+ case ZigClangStmt_ObjCSubscriptRefExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCSubscriptRefExprClass");
return ErrorUnexpected;
- case clang::Stmt::OffsetOfExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OffsetOfExprClass");
+ case ZigClangStmt_OffsetOfExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OffsetOfExprClass");
return ErrorUnexpected;
- case clang::Stmt::OpaqueValueExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OpaqueValueExprClass");
+ case ZigClangStmt_OpaqueValueExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OpaqueValueExprClass");
return ErrorUnexpected;
- case clang::Stmt::UnresolvedLookupExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedLookupExprClass");
+ case ZigClangStmt_UnresolvedLookupExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UnresolvedLookupExprClass");
return ErrorUnexpected;
- case clang::Stmt::UnresolvedMemberExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedMemberExprClass");
+ case ZigClangStmt_UnresolvedMemberExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UnresolvedMemberExprClass");
return ErrorUnexpected;
- case clang::Stmt::PackExpansionExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C PackExpansionExprClass");
+ case ZigClangStmt_PackExpansionExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C PackExpansionExprClass");
return ErrorUnexpected;
- case clang::Stmt::ParenListExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ParenListExprClass");
+ case ZigClangStmt_ParenListExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ParenListExprClass");
return ErrorUnexpected;
- case clang::Stmt::PseudoObjectExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C PseudoObjectExprClass");
+ case ZigClangStmt_PseudoObjectExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C PseudoObjectExprClass");
return ErrorUnexpected;
- case clang::Stmt::ShuffleVectorExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ShuffleVectorExprClass");
+ case ZigClangStmt_ShuffleVectorExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ShuffleVectorExprClass");
return ErrorUnexpected;
- case clang::Stmt::SizeOfPackExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SizeOfPackExprClass");
+ case ZigClangStmt_SizeOfPackExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SizeOfPackExprClass");
return ErrorUnexpected;
- case clang::Stmt::SubstNonTypeTemplateParmExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmExprClass");
+ case ZigClangStmt_SubstNonTypeTemplateParmExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SubstNonTypeTemplateParmExprClass");
return ErrorUnexpected;
- case clang::Stmt::SubstNonTypeTemplateParmPackExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
+ case ZigClangStmt_SubstNonTypeTemplateParmPackExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
return ErrorUnexpected;
- case clang::Stmt::TypeTraitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeTraitExprClass");
+ case ZigClangStmt_TypeTraitExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C TypeTraitExprClass");
return ErrorUnexpected;
- case clang::Stmt::TypoExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypoExprClass");
+ case ZigClangStmt_TypoExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C TypoExprClass");
return ErrorUnexpected;
- case clang::Stmt::VAArgExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C VAArgExprClass");
+ case ZigClangStmt_VAArgExprClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C VAArgExprClass");
return ErrorUnexpected;
- case clang::Stmt::GotoStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C GotoStmtClass");
+ case ZigClangStmt_GotoStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GotoStmtClass");
return ErrorUnexpected;
- case clang::Stmt::IndirectGotoStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C IndirectGotoStmtClass");
+ case ZigClangStmt_IndirectGotoStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C IndirectGotoStmtClass");
return ErrorUnexpected;
- case clang::Stmt::LabelStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C LabelStmtClass");
+ case ZigClangStmt_LabelStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C LabelStmtClass");
return ErrorUnexpected;
- case clang::Stmt::MSDependentExistsStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSDependentExistsStmtClass");
+ case ZigClangStmt_MSDependentExistsStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSDependentExistsStmtClass");
return ErrorUnexpected;
- case clang::Stmt::OMPAtomicDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPAtomicDirectiveClass");
+ case ZigClangStmt_OMPAtomicDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPAtomicDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPBarrierDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPBarrierDirectiveClass");
+ case ZigClangStmt_OMPBarrierDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPBarrierDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPCancelDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancelDirectiveClass");
+ case ZigClangStmt_OMPCancelDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCancelDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPCancellationPointDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancellationPointDirectiveClass");
+ case ZigClangStmt_OMPCancellationPointDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCancellationPointDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPCriticalDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCriticalDirectiveClass");
+ case ZigClangStmt_OMPCriticalDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCriticalDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPFlushDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPFlushDirectiveClass");
+ case ZigClangStmt_OMPFlushDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPFlushDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPDistributeDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeDirectiveClass");
+ case ZigClangStmt_OMPDistributeDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPDistributeParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForDirectiveClass");
+ case ZigClangStmt_OMPDistributeParallelForDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeParallelForDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
+ case ZigClangStmt_OMPDistributeParallelForSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPDistributeSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeSimdDirectiveClass");
+ case ZigClangStmt_OMPDistributeSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForDirectiveClass");
+ case ZigClangStmt_OMPForDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPForDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForSimdDirectiveClass");
+ case ZigClangStmt_OMPForSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPForSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForDirectiveClass");
+ case ZigClangStmt_OMPParallelForDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelForDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForSimdDirectiveClass");
+ case ZigClangStmt_OMPParallelForSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSimdDirectiveClass");
+ case ZigClangStmt_OMPSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
+ case ZigClangStmt_OMPTargetParallelForSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetSimdDirectiveClass");
+ case ZigClangStmt_OMPTargetSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
+ case ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
+ case ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
+ case ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
+ case ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTaskLoopDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopDirectiveClass");
+ case ZigClangStmt_OMPTaskLoopDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskLoopDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTaskLoopSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopSimdDirectiveClass");
+ case ZigClangStmt_OMPTaskLoopSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskLoopSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTeamsDistributeDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeDirectiveClass");
+ case ZigClangStmt_OMPTeamsDistributeDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
+ case ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
+ case ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
+ case ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPMasterDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPMasterDirectiveClass");
+ case ZigClangStmt_OMPMasterDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPMasterDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPOrderedDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPOrderedDirectiveClass");
+ case ZigClangStmt_OMPOrderedDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPOrderedDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPParallelDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelDirectiveClass");
+ case ZigClangStmt_OMPParallelDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPParallelSectionsDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelSectionsDirectiveClass");
+ case ZigClangStmt_OMPParallelSectionsDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelSectionsDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPSectionDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionDirectiveClass");
+ case ZigClangStmt_OMPSectionDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSectionDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPSectionsDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionsDirectiveClass");
+ case ZigClangStmt_OMPSectionsDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSectionsDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPSingleDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSingleDirectiveClass");
+ case ZigClangStmt_OMPSingleDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSingleDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetDataDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDataDirectiveClass");
+ case ZigClangStmt_OMPTargetDataDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetDataDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDirectiveClass");
+ case ZigClangStmt_OMPTargetDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetEnterDataDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetEnterDataDirectiveClass");
+ case ZigClangStmt_OMPTargetEnterDataDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetEnterDataDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetExitDataDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetExitDataDirectiveClass");
+ case ZigClangStmt_OMPTargetExitDataDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetExitDataDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetParallelDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelDirectiveClass");
+ case ZigClangStmt_OMPTargetParallelDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForDirectiveClass");
+ case ZigClangStmt_OMPTargetParallelForDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelForDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetTeamsDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDirectiveClass");
+ case ZigClangStmt_OMPTargetTeamsDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTargetUpdateDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetUpdateDirectiveClass");
+ case ZigClangStmt_OMPTargetUpdateDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetUpdateDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTaskDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskDirectiveClass");
+ case ZigClangStmt_OMPTaskDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTaskgroupDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskgroupDirectiveClass");
+ case ZigClangStmt_OMPTaskgroupDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskgroupDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTaskwaitDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskwaitDirectiveClass");
+ case ZigClangStmt_OMPTaskwaitDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskwaitDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTaskyieldDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskyieldDirectiveClass");
+ case ZigClangStmt_OMPTaskyieldDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskyieldDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::OMPTeamsDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDirectiveClass");
+ case ZigClangStmt_OMPTeamsDirectiveClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDirectiveClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCAtCatchStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtCatchStmtClass");
+ case ZigClangStmt_ObjCAtCatchStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtCatchStmtClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCAtFinallyStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtFinallyStmtClass");
+ case ZigClangStmt_ObjCAtFinallyStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtFinallyStmtClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCAtSynchronizedStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtSynchronizedStmtClass");
+ case ZigClangStmt_ObjCAtSynchronizedStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtSynchronizedStmtClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCAtThrowStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtThrowStmtClass");
+ case ZigClangStmt_ObjCAtThrowStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtThrowStmtClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCAtTryStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtTryStmtClass");
+ case ZigClangStmt_ObjCAtTryStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtTryStmtClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCAutoreleasePoolStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAutoreleasePoolStmtClass");
+ case ZigClangStmt_ObjCAutoreleasePoolStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAutoreleasePoolStmtClass");
return ErrorUnexpected;
- case clang::Stmt::ObjCForCollectionStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCForCollectionStmtClass");
+ case ZigClangStmt_ObjCForCollectionStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCForCollectionStmtClass");
return ErrorUnexpected;
- case clang::Stmt::SEHExceptStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHExceptStmtClass");
+ case ZigClangStmt_SEHExceptStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHExceptStmtClass");
return ErrorUnexpected;
- case clang::Stmt::SEHFinallyStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHFinallyStmtClass");
+ case ZigClangStmt_SEHFinallyStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHFinallyStmtClass");
return ErrorUnexpected;
- case clang::Stmt::SEHLeaveStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHLeaveStmtClass");
+ case ZigClangStmt_SEHLeaveStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHLeaveStmtClass");
return ErrorUnexpected;
- case clang::Stmt::SEHTryStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHTryStmtClass");
+ case ZigClangStmt_SEHTryStmtClass:
+ emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHTryStmtClass");
return ErrorUnexpected;
}
zig_unreachable();
}
// Returns null if there was an error
-static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr,
+static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr,
TransLRValue lrval)
{
AstNode *result_node;
TransScope *result_scope;
- if (trans_stmt_extra(c, scope, expr, result_used, lrval, &result_node, &result_scope, nullptr)) {
+ if (trans_stmt_extra(c, scope, (const ZigClangStmt *)expr, result_used, lrval, &result_node, &result_scope, nullptr)) {
return nullptr;
}
return result_node;
@@ -3846,7 +4013,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope
// Statements have no result and no concept of L or R value.
// Returns child scope, or null if there was an error
-static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node) {
+static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt *stmt, AstNode **out_node) {
TransScope *child_scope;
if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {
return nullptr;
@@ -3854,34 +4021,36 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *
return child_scope;
}
-static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
- Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
+static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
+ Buf *fn_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)fn_decl));
if (get_global(c, fn_name)) {
// we already saw this function
return;
}
- AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), fn_decl->getLocation());
+ AstNode *proto_node = trans_qual_type(c, ZigClangFunctionDecl_getType(fn_decl),
+ ZigClangFunctionDecl_getLocation(fn_decl));
if (proto_node == nullptr) {
- emit_warning(c, fn_decl->getLocation(), "unable to resolve prototype of function '%s'", buf_ptr(fn_name));
+ emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl),
+ "unable to resolve prototype of function '%s'", buf_ptr(fn_name));
return;
}
proto_node->data.fn_proto.name = fn_name;
- proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
+ proto_node->data.fn_proto.is_extern = !ZigClangFunctionDecl_hasBody(fn_decl);
- clang::StorageClass sc = fn_decl->getStorageClass();
- if (sc == clang::SC_None) {
+ ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl);
+ if (sc == ZigClangStorageClass_None) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
- proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false;
- } else if (sc == clang::SC_Extern || sc == clang::SC_Static) {
+ proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false;
+ } else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
- } else if (sc == clang::SC_PrivateExtern) {
- emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
+ } else if (sc == ZigClangStorageClass_PrivateExtern) {
+ emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern");
return;
} else {
- emit_warning(c, fn_decl->getLocation(), "unsupported storage class: unknown");
+ emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: unknown");
return;
}
@@ -3889,8 +4058,8 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
AstNode *param_node = proto_node->data.fn_proto.params.at(i);
- const clang::ParmVarDecl *param = fn_decl->getParamDecl(i);
- const char *name = decl_name(param);
+ const ZigClangParmVarDecl *param = ZigClangFunctionDecl_getParamDecl(fn_decl, i);
+ const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)param);
Buf *proto_param_name;
if (strlen(name) != 0) {
@@ -3908,7 +4077,7 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
param_node->data.param_decl.name = scope_var->zig_name;
}
- if (!fn_decl->hasBody()) {
+ if (!ZigClangFunctionDecl_hasBody(fn_decl)) {
// just a prototype
add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node);
return;
@@ -3916,11 +4085,11 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
// actual function definition with body
c->ptr_params.clear();
- clang::Stmt *body = fn_decl->getBody();
+ const ZigClangStmt *body = ZigClangFunctionDecl_getBody(fn_decl);
AstNode *actual_body_node;
TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
if (result_scope == nullptr) {
- emit_warning(c, fn_decl->getLocation(), "unable to translate function");
+ emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unable to translate function");
return;
}
assert(actual_body_node != nullptr);
@@ -3958,20 +4127,20 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
}
-static AstNode *resolve_typdef_as_builtin(Context *c, const clang::TypedefNameDecl *typedef_decl, const char *primitive_name) {
+static AstNode *resolve_typdef_as_builtin(Context *c, const ZigClangTypedefNameDecl *typedef_decl, const char *primitive_name) {
AstNode *node = trans_create_node_symbol_str(c, primitive_name);
c->decl_table.put(typedef_decl, node);
return node;
}
-static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) {
- auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
+static AstNode *resolve_typedef_decl(Context *c, const ZigClangTypedefNameDecl *typedef_decl) {
+ auto existing_entry = c->decl_table.maybe_get((void*)ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl));
if (existing_entry) {
return existing_entry->value;
}
- clang::QualType child_qt = typedef_decl->getUnderlyingType();
- Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
+ ZigClangQualType child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
+ Buf *type_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl));
if (buf_eql_str(type_name, "uint8_t")) {
return resolve_typdef_as_builtin(c, typedef_decl, "u8");
@@ -4005,11 +4174,12 @@ static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *t
// trans_qual_type here might cause us to look at this typedef again so we put the item in the map first
AstNode *symbol_node = trans_create_node_symbol(c, type_name);
- c->decl_table.put(typedef_decl->getCanonicalDecl(), symbol_node);
+ c->decl_table.put(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl), symbol_node);
- AstNode *type_node = trans_qual_type(c, child_qt, typedef_decl->getLocation());
+ AstNode *type_node = trans_qual_type(c, child_qt, ZigClangTypedefNameDecl_getLocation(typedef_decl));
if (type_node == nullptr) {
- emit_warning(c, typedef_decl->getLocation(), "typedef %s - unresolved child type", buf_ptr(type_name));
+ emit_warning(c, ZigClangTypedefNameDecl_getLocation(typedef_decl),
+ "typedef %s - unresolved child type", buf_ptr(type_name));
c->decl_table.put(typedef_decl, nullptr);
// TODO add global var with type_name equal to @compileError("unable to resolve C type")
return nullptr;
@@ -4019,33 +4189,33 @@ static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *t
return symbol_node;
}
-struct AstNode *demote_enum_to_opaque(Context *c, const clang::EnumDecl *enum_decl,
- Buf *full_type_name, Buf *bare_name)
+struct AstNode *demote_enum_to_opaque(Context *c, const ZigClangEnumDecl *enum_decl, Buf *full_type_name,
+ Buf *bare_name)
{
AstNode *opaque_node = trans_create_node_opaque(c);
if (full_type_name == nullptr) {
- c->decl_table.put(enum_decl->getCanonicalDecl(), opaque_node);
+ c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), opaque_node);
return opaque_node;
}
AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
add_global_weak_alias(c, bare_name, full_type_name);
add_global_var(c, full_type_name, opaque_node);
- c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
+ c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), symbol_node);
return symbol_node;
}
-static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) {
- auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());
+static AstNode *resolve_enum_decl(Context *c, const ZigClangEnumDecl *enum_decl) {
+ auto existing_entry = c->decl_table.maybe_get(ZigClangEnumDecl_getCanonicalDecl(enum_decl));
if (existing_entry) {
return existing_entry->value;
}
- const char *raw_name = decl_name(enum_decl);
+ const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_decl);
bool is_anonymous = (raw_name[0] == 0);
Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
- const clang::EnumDecl *enum_def = enum_decl->getDefinition();
+ const ZigClangEnumDecl *enum_def = ZigClangEnumDecl_getDefinition(enum_decl);
if (!enum_def) {
return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
}
@@ -4053,8 +4223,8 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
bool pure_enum = true;
uint32_t field_count = 0;
- for (auto it = enum_def->enumerator_begin(),
- it_end = enum_def->enumerator_end();
+ for (auto it = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_begin(),
+ it_end = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_end();
it != it_end; ++it, field_count += 1)
{
const clang::EnumConstantDecl *enum_const = *it;
@@ -4062,7 +4232,8 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
pure_enum = false;
}
}
- AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation());
+ AstNode *tag_int_type = trans_qual_type(c, ZigClangEnumDecl_getIntegerType(enum_decl),
+ ZigClangEnumDecl_getLocation(enum_decl));
assert(tag_int_type);
AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);
@@ -4071,20 +4242,20 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
// 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(), clang::BuiltinType::UInt) &&
- !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int))
+ if (!c_is_builtin_type(c, ZigClangEnumDecl_getIntegerType(enum_decl), ZigClangBuiltinTypeUInt) &&
+ !c_is_builtin_type(c, ZigClangEnumDecl_getIntegerType(enum_decl), ZigClangBuiltinTypeInt))
{
enum_node->data.container_decl.init_arg_expr = tag_int_type;
}
enum_node->data.container_decl.fields.resize(field_count);
uint32_t i = 0;
- for (auto it = enum_def->enumerator_begin(),
- it_end = enum_def->enumerator_end();
+ for (auto it = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_begin(),
+ it_end = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_end();
it != it_end; ++it, i += 1)
{
const clang::EnumConstantDecl *enum_const = *it;
- Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
+ Buf *enum_val_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_const));
Buf *field_name;
if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) {
field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
@@ -4092,7 +4263,8 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
field_name = enum_val_name;
}
- AstNode *int_node = pure_enum && !is_anonymous ? nullptr : trans_create_node_apint(c, enum_const->getInitVal());
+ AstNode *int_node = pure_enum && !is_anonymous ?
+ nullptr : trans_create_node_apint(c, bitcast(&enum_const->getInitVal()));
AstNode *field_node = trans_create_node(c, NodeTypeStructField);
field_node->data.struct_field.name = field_name;
field_node->data.struct_field.type = nullptr;
@@ -4102,7 +4274,7 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
// in C each enum value is in the global namespace. so we put them there too.
// at this point we can rely on the enum emitting successfully
if (is_anonymous) {
- Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
+ Buf *enum_val_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_const));
add_global_var(c, enum_val_name, int_node);
} else {
AstNode *field_access_node = trans_create_node_field_access(c,
@@ -4112,73 +4284,74 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
}
if (is_anonymous) {
- c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node);
+ c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), enum_node);
return enum_node;
} else {
AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
add_global_weak_alias(c, bare_name, full_type_name);
add_global_var(c, full_type_name, enum_node);
- c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
+ c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), symbol_node);
return enum_node;
}
}
-static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl,
+static AstNode *demote_struct_to_opaque(Context *c, const ZigClangRecordDecl *record_decl,
Buf *full_type_name, Buf *bare_name)
{
AstNode *opaque_node = trans_create_node_opaque(c);
if (full_type_name == nullptr) {
- c->decl_table.put(record_decl->getCanonicalDecl(), opaque_node);
+ c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), opaque_node);
return opaque_node;
}
AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
add_global_weak_alias(c, bare_name, full_type_name);
add_global_var(c, full_type_name, opaque_node);
- c->decl_table.put(record_decl->getCanonicalDecl(), symbol_node);
+ c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), symbol_node);
return symbol_node;
}
-static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) {
- auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());
+static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl) {
+ auto existing_entry = c->decl_table.maybe_get(ZigClangRecordDecl_getCanonicalDecl(record_decl));
if (existing_entry) {
return existing_entry->value;
}
- const char *raw_name = decl_name(record_decl);
+ const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)record_decl);
const char *container_kind_name;
ContainerKind container_kind;
- if (record_decl->isUnion()) {
+ if (ZigClangRecordDecl_isUnion(record_decl)) {
container_kind_name = "union";
container_kind = ContainerKindUnion;
- } else if (record_decl->isStruct()) {
+ } else if (ZigClangRecordDecl_isStruct(record_decl)) {
container_kind_name = "struct";
container_kind = ContainerKindStruct;
} else {
- emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct or union", raw_name);
- c->decl_table.put(record_decl->getCanonicalDecl(), nullptr);
+ emit_warning(c, ZigClangRecordDecl_getLocation(record_decl),
+ "skipping record %s, not a struct or union", raw_name);
+ c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), nullptr);
return nullptr;
}
- bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0;
+ bool is_anonymous = ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) || raw_name[0] == 0;
Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
Buf *full_type_name = (bare_name == nullptr) ?
nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));
- clang::RecordDecl *record_def = record_decl->getDefinition();
+ const ZigClangRecordDecl *record_def = ZigClangRecordDecl_getDefinition(record_decl);
if (record_def == nullptr) {
return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
}
// count fields and validate
uint32_t field_count = 0;
- for (auto it = record_def->field_begin(),
- it_end = record_def->field_end();
+ for (auto it = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_begin(),
+ it_end = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_end();
it != it_end; ++it, field_count += 1)
{
const clang::FieldDecl *field_decl = *it;
if (field_decl->isBitField()) {
- emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",
+ emit_warning(c, bitcast(field_decl->getLocation()), "%s %s demoted to opaque type - has bitfield",
container_kind_name,
is_anonymous ? "(anon)" : buf_ptr(bare_name));
return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
@@ -4195,24 +4368,25 @@ static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_
// must be before fields in case a circular reference happens
if (is_anonymous) {
- c->decl_table.put(record_decl->getCanonicalDecl(), struct_node);
+ c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), struct_node);
} else {
- c->decl_table.put(record_decl->getCanonicalDecl(), trans_create_node_symbol(c, full_type_name));
+ c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), trans_create_node_symbol(c, full_type_name));
}
uint32_t i = 0;
- for (auto it = record_def->field_begin(),
- it_end = record_def->field_end();
+ for (auto it = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_begin(),
+ it_end = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_end();
it != it_end; ++it, i += 1)
{
const clang::FieldDecl *field_decl = *it;
AstNode *field_node = trans_create_node(c, NodeTypeStructField);
- field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));
- field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation());
+ field_node->data.struct_field.name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)field_decl));
+ field_node->data.struct_field.type = trans_qual_type(c, bitcast(field_decl->getType()),
+ bitcast(field_decl->getLocation()));
if (field_node->data.struct_field.type == nullptr) {
- emit_warning(c, field_decl->getLocation(),
+ emit_warning(c, bitcast(field_decl->getLocation()),
"%s %s demoted to opaque type - unresolved type",
container_kind_name,
is_anonymous ? "(anon)" : buf_ptr(bare_name));
@@ -4232,17 +4406,19 @@ static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_
}
}
-static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) {
- switch (ap_value->getKind()) {
- case clang::APValue::Int:
- return trans_create_node_apint(c, ap_value->getInt());
- case clang::APValue::Uninitialized:
+static AstNode *trans_ap_value(Context *c, const ZigClangAPValue *ap_value, ZigClangQualType qt,
+ ZigClangSourceLocation source_loc)
+{
+ switch (ZigClangAPValue_getKind(ap_value)) {
+ case ZigClangAPValueInt:
+ return trans_create_node_apint(c, ZigClangAPValue_getInt(ap_value));
+ case ZigClangAPValueUninitialized:
return trans_create_node(c, NodeTypeUndefinedLiteral);
- case clang::APValue::Array: {
+ case ZigClangAPValueArray: {
emit_warning(c, source_loc, "TODO add a test case for this code");
- unsigned init_count = ap_value->getArrayInitializedElts();
- unsigned all_count = ap_value->getArraySize();
+ unsigned init_count = ZigClangAPValue_getArrayInitializedElts(ap_value);
+ unsigned all_count = ZigClangAPValue_getArraySize(ap_value);
unsigned leftover_count = all_count - init_count;
AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
AstNode *arr_type_node = trans_qual_type(c, qt, source_loc);
@@ -4252,11 +4428,12 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual
init_node->data.container_init_expr.type = arr_type_node;
init_node->data.container_init_expr.kind = ContainerInitKindArray;
- clang::QualType child_qt = qt.getTypePtr()->getAsArrayTypeUnsafe()->getElementType();
+ const clang::Type *qt_type = reinterpret_cast<const clang::Type *>(ZigClangQualType_getTypePtr(qt));
+ ZigClangQualType child_qt = bitcast(qt_type->getAsArrayTypeUnsafe()->getElementType());
for (size_t i = 0; i < init_count; i += 1) {
- clang::APValue &elem_ap_val = ap_value->getArrayInitializedElt(i);
- AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);
+ const ZigClangAPValue *elem_ap_val = ZigClangAPValue_getArrayInitializedElt(ap_value, i);
+ AstNode *elem_node = trans_ap_value(c, elem_ap_val, child_qt, source_loc);
if (elem_node == nullptr)
return nullptr;
init_node->data.container_init_expr.entries.append(elem_node);
@@ -4265,8 +4442,8 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual
return init_node;
}
- clang::APValue &filler_ap_val = ap_value->getArrayFiller();
- AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);
+ const ZigClangAPValue *filler_ap_val = ZigClangAPValue_getArrayFiller(ap_value);
+ AstNode *filler_node = trans_ap_value(c, filler_ap_val, child_qt, source_loc);
if (filler_node == nullptr)
return nullptr;
@@ -4293,37 +4470,37 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual
return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
}
- case clang::APValue::LValue: {
- const clang::APValue::LValueBase lval_base = ap_value->getLValueBase();
- if (const clang::Expr *expr = lval_base.dyn_cast<const clang::Expr *>()) {
+ case ZigClangAPValueLValue: {
+ const ZigClangAPValueLValueBase lval_base = ZigClangAPValue_getLValueBase(ap_value);
+ if (const ZigClangExpr *expr = ZigClangAPValueLValueBase_dyn_cast_Expr(lval_base)) {
return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
}
//const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>();
emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl");
return nullptr;
}
- case clang::APValue::Float:
+ case ZigClangAPValueFloat:
emit_warning(c, source_loc, "unsupported initializer value kind: Float");
return nullptr;
- case clang::APValue::ComplexInt:
+ case ZigClangAPValueComplexInt:
emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
return nullptr;
- case clang::APValue::ComplexFloat:
+ case ZigClangAPValueComplexFloat:
emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
return nullptr;
- case clang::APValue::Vector:
+ case ZigClangAPValueVector:
emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
return nullptr;
- case clang::APValue::Struct:
+ case ZigClangAPValueStruct:
emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
return nullptr;
- case clang::APValue::Union:
+ case ZigClangAPValueUnion:
emit_warning(c, source_loc, "unsupported initializer value kind: Union");
return nullptr;
- case clang::APValue::MemberPointer:
+ case ZigClangAPValueMemberPointer:
emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
return nullptr;
- case clang::APValue::AddrLabelDiff:
+ case ZigClangAPValueAddrLabelDiff:
emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
return nullptr;
}
@@ -4331,42 +4508,42 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual
}
static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
- Buf *name = buf_create_from_str(decl_name(var_decl));
+ Buf *name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)var_decl));
switch (var_decl->getTLSKind()) {
case clang::VarDecl::TLS_None:
break;
case clang::VarDecl::TLS_Static:
- emit_warning(c, var_decl->getLocation(),
+ emit_warning(c, bitcast(var_decl->getLocation()),
"ignoring variable '%s' - static thread local storage", buf_ptr(name));
return;
case clang::VarDecl::TLS_Dynamic:
- emit_warning(c, var_decl->getLocation(),
+ emit_warning(c, bitcast(var_decl->getLocation()),
"ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
return;
}
- clang::QualType qt = var_decl->getType();
- AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
+ ZigClangQualType qt = bitcast(var_decl->getType());
+ AstNode *var_type = trans_qual_type(c, qt, bitcast(var_decl->getLocation()));
if (var_type == nullptr) {
- emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));
+ emit_warning(c, bitcast(var_decl->getLocation()), "ignoring variable '%s' - unresolved type", buf_ptr(name));
return;
}
bool is_extern = var_decl->hasExternalStorage();
bool is_static = var_decl->isFileVarDecl();
- bool is_const = qt.isConstQualified();
+ bool is_const = ZigClangQualType_isConstQualified(qt);
if (is_static && !is_extern) {
AstNode *init_node;
if (var_decl->hasInit()) {
- clang::APValue *ap_value = var_decl->evaluateValue();
+ const ZigClangAPValue *ap_value = bitcast(var_decl->evaluateValue());
if (ap_value == nullptr) {
- emit_warning(c, var_decl->getLocation(),
+ emit_warning(c, bitcast(var_decl->getLocation()),
"ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
return;
}
- init_node = trans_ap_value(c, ap_value, qt, var_decl->getLocation());
+ init_node = trans_ap_value(c, ap_value, qt, bitcast(var_decl->getLocation()));
if (init_node == nullptr)
return;
} else {
@@ -4385,33 +4562,32 @@ static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
return;
}
- emit_warning(c, var_decl->getLocation(),
+ emit_warning(c, bitcast(var_decl->getLocation()),
"ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name));
return;
}
-static bool decl_visitor(void *context, const ZigClangDecl *zdecl) {
- const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zdecl);
+static bool decl_visitor(void *context, const ZigClangDecl *decl) {
Context *c = (Context*)context;
- switch (decl->getKind()) {
- case clang::Decl::Function:
- visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl));
+ switch (ZigClangDecl_getKind(decl)) {
+ case ZigClangDeclFunction:
+ visit_fn_decl(c, reinterpret_cast<const ZigClangFunctionDecl*>(decl));
break;
- case clang::Decl::Typedef:
- resolve_typedef_decl(c, static_cast<const clang::TypedefNameDecl *>(decl));
+ case ZigClangDeclTypedef:
+ resolve_typedef_decl(c, reinterpret_cast<const ZigClangTypedefNameDecl *>(decl));
break;
- case clang::Decl::Enum:
- resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl));
+ case ZigClangDeclEnum:
+ resolve_enum_decl(c, reinterpret_cast<const ZigClangEnumDecl *>(decl));
break;
- case clang::Decl::Record:
- resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl));
+ case ZigClangDeclRecord:
+ resolve_record_decl(c, reinterpret_cast<const ZigClangRecordDecl *>(decl));
break;
- case clang::Decl::Var:
- visit_var_decl(c, static_cast<const clang::VarDecl *>(decl));
+ case ZigClangDeclVar:
+ visit_var_decl(c, reinterpret_cast<const clang::VarDecl *>(decl));
break;
default:
- emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());
+ emit_warning(c, ZigClangDecl_getLocation(decl), "ignoring %s decl", ZigClangDecl_getDeclKindName(decl));
}
return true;
@@ -4720,6 +4896,8 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok
case CTokIdAsterisk:
case CTokIdBang:
case CTokIdTilde:
+ case CTokIdShl:
+ case CTokIdLt:
// not able to make sense of this
return nullptr;
}
@@ -4751,6 +4929,13 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
*tok_i += 1;
node = trans_create_node_ptr_type(c, false, false, node, PtrLenC);
+ } else if (first_tok->id == CTokIdShl) {
+ *tok_i += 1;
+
+ AstNode *rhs_node = parse_ctok_expr(c, ctok, tok_i);
+ if (rhs_node == nullptr)
+ return nullptr;
+ node = trans_create_node_bin_op(c, node, BinOpTypeBitShiftLeft, rhs_node);
} else {
return node;
}
@@ -4846,10 +5031,10 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity);
const char *raw_name = macro->getName()->getNameStart();
clang::SourceRange range = macro->getSourceRange();
- clang::SourceLocation begin_loc = range.getBegin();
- clang::SourceLocation end_loc = range.getEnd();
+ ZigClangSourceLocation begin_loc = bitcast(range.getBegin());
+ ZigClangSourceLocation end_loc = bitcast(range.getEnd());
- if (begin_loc == end_loc) {
+ if (ZigClangSourceLocation_eq(begin_loc, end_loc)) {
// this means it is a macro without a value
// we don't care about such things
continue;
@@ -4859,21 +5044,22 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
continue;
}
- const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, bitcast(begin_loc));
+ const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, begin_loc);
process_macro(c, &ctok, name, begin_c);
}
}
}
}
-Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file,
- CodeGen *codegen, Buf *tmp_dep_file)
+Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
+ Stage2ErrorMsg **errors_ptr, size_t *errors_len,
+ const char **args_begin, const char **args_end,
+ Stage2TranslateMode mode, const char *resources_path)
{
Context context = {0};
Context *c = &context;
c->warnings_on = codegen->verbose_cimport;
- c->errors = errors;
- if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) {
+ if (mode == Stage2TranslateModeImport) {
c->visib_mod = VisibModPub;
c->want_export = false;
} else {
@@ -4887,161 +5073,10 @@ Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const c
c->codegen = codegen;
c->global_scope = trans_scope_root_create(c);
- ZigList<const char *> clang_argv = {0};
-
- clang_argv.append("-x");
- clang_argv.append("c");
-
- if (tmp_dep_file != nullptr) {
- clang_argv.append("-MD");
- clang_argv.append("-MV");
- clang_argv.append("-MF");
- clang_argv.append(buf_ptr(tmp_dep_file));
- }
-
- if (c->codegen->zig_target->is_native) {
- char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS");
- if (ZIG_PARSEC_CFLAGS) {
- Buf tmp_buf = BUF_INIT;
- char *start = ZIG_PARSEC_CFLAGS;
- char *space = strstr(start, " ");
- while (space) {
- if (space - start > 0) {
- buf_init_from_mem(&tmp_buf, start, space - start);
- clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
- }
- start = space + 1;
- space = strstr(start, " ");
- }
- buf_init_from_str(&tmp_buf, start);
- clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
- }
- }
-
- clang_argv.append("-nobuiltininc");
- clang_argv.append("-nostdinc");
- clang_argv.append("-nostdinc++");
- if (codegen->libc_link_lib == nullptr) {
- clang_argv.append("-nolibc");
- }
-
- clang_argv.append("-isystem");
- clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
-
- for (size_t i = 0; i < codegen->libc_include_dir_len; i += 1) {
- Buf *include_dir = codegen->libc_include_dir_list[i];
- clang_argv.append("-isystem");
- clang_argv.append(buf_ptr(include_dir));
- }
-
- // windows c runtime requires -D_DEBUG if using debug libraries
- if (codegen->build_mode == BuildModeDebug) {
- clang_argv.append("-D_DEBUG");
- }
-
- for (size_t i = 0; i < codegen->clang_argv_len; i += 1) {
- clang_argv.append(codegen->clang_argv[i]);
- }
-
- // we don't need spell checking and it slows things down
- clang_argv.append("-fno-spell-checking");
-
- // this gives us access to preprocessing entities, presumably at
- // the cost of performance
- clang_argv.append("-Xclang");
- clang_argv.append("-detailed-preprocessing-record");
-
- if (c->codegen->zig_target->is_native) {
- clang_argv.append("-march=native");
- } else {
- clang_argv.append("-target");
- clang_argv.append(buf_ptr(&c->codegen->triple_str));
- }
-
- clang_argv.append(target_file);
-
- if (codegen->verbose_cc) {
- fprintf(stderr, "clang");
- for (size_t i = 0; i < clang_argv.length; i += 1) {
- fprintf(stderr, " %s", clang_argv.at(i));
- }
- fprintf(stderr, "\n");
- }
-
- // to make the [start...end] argument work
- clang_argv.append(nullptr);
-
- clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
-
- std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();
-
- bool only_local_decls = true;
- bool capture_diagnostics = true;
- bool user_files_are_volatile = true;
- bool allow_pch_with_compiler_errors = false;
- bool single_file_parse = false;
- bool for_serialization = false;
- const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
- std::unique_ptr<clang::ASTUnit> err_unit;
- ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine(
- &clang_argv.at(0), &clang_argv.last(),
- pch_container_ops, diags, resources_path,
- only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
- false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
- single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit,
- nullptr));
-
- // Early failures in LoadFromCommandLine may return with ErrUnit unset.
- if (!ast_unit && !err_unit) {
- return ErrorFileSystem;
- }
-
- if (diags->getClient()->getNumErrors() > 0) {
- if (ast_unit) {
- err_unit = std::unique_ptr<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(ast_unit));
- }
-
- for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
- it_end = err_unit->stored_diag_end();
- it != it_end; ++it)
- {
- switch (it->getLevel()) {
- case clang::DiagnosticsEngine::Ignored:
- case clang::DiagnosticsEngine::Note:
- case clang::DiagnosticsEngine::Remark:
- case clang::DiagnosticsEngine::Warning:
- continue;
- case clang::DiagnosticsEngine::Error:
- case clang::DiagnosticsEngine::Fatal:
- break;
- }
- llvm::StringRef msg_str_ref = it->getMessage();
- Buf *msg = string_ref_to_buf(msg_str_ref);
- clang::FullSourceLoc fsl = it->getLocation();
- if (fsl.hasManager()) {
- clang::FileID file_id = fsl.getFileID();
- clang::StringRef filename = fsl.getManager().getFilename(fsl);
- unsigned line = fsl.getSpellingLineNumber() - 1;
- unsigned column = fsl.getSpellingColumnNumber() - 1;
- unsigned offset = fsl.getManager().getFileOffset(fsl);
- const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
- Buf *path;
- if (filename.empty()) {
- path = buf_alloc();
- } else {
- path = string_ref_to_buf(filename);
- }
-
- ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
-
- c->errors->append(err_msg);
- } else {
- // NOTE the only known way this gets triggered right now is if you have a lot of errors
- // clang emits "too many errors emitted, stopping now"
- fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg));
- }
- }
-
+ ZigClangASTUnit *ast_unit = ZigClangLoadFromCommandLine(args_begin, args_end, errors_ptr, errors_len,
+ resources_path);
+ if (ast_unit == nullptr) {
+ if (*errors_len == 0) return ErrorNoMem;
return ErrorCCompileErrors;
}
@@ -5059,5 +5094,7 @@ Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const c
*out_root_node = c->root;
+ ZigClangASTUnit_delete(ast_unit);
+
return ErrorNone;
}
diff --git a/src/translate_c.hpp b/src/translate_c.hpp
index 21461d2813..4eac26ddb5 100644
--- a/src/translate_c.hpp
+++ b/src/translate_c.hpp
@@ -11,7 +11,9 @@
#include "all_types.hpp"
-Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file,
- CodeGen *codegen, Buf *tmp_dep_file);
+Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
+ Stage2ErrorMsg **errors_ptr, size_t *errors_len,
+ const char **args_begin, const char **args_end,
+ Stage2TranslateMode mode, const char *resources_path);
#endif
diff --git a/src/userland.cpp b/src/userland.cpp
new file mode 100644
index 0000000000..20740711e5
--- /dev/null
+++ b/src/userland.cpp
@@ -0,0 +1,44 @@
+// This file is a shim for zig1. The real implementations of these are in
+// src-self-hosted/stage1.zig
+
+#include "userland.h"
+#include "ast_render.hpp"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+Error stage2_translate_c(struct Stage2Ast **out_ast,
+ struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
+ const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
+ const char *resources_path)
+{
+ const char *msg = "stage0 called stage2_translate_c";
+ stage2_panic(msg, strlen(msg));
+}
+
+void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) {
+ const char *msg = "stage0 called stage2_free_clang_errors";
+ stage2_panic(msg, strlen(msg));
+}
+
+void stage2_zen(const char **ptr, size_t *len) {
+ const char *msg = "stage0 called stage2_zen";
+ stage2_panic(msg, strlen(msg));
+}
+
+void stage2_panic(const char *ptr, size_t len) {
+ fwrite(ptr, 1, len, stderr);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ abort();
+}
+
+void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) {
+ const char *msg = "stage0 called stage2_render_ast";
+ stage2_panic(msg, strlen(msg));
+}
+
+int stage2_fmt(int argc, char **argv) {
+ const char *msg = "stage0 called stage2_fmt";
+ stage2_panic(msg, strlen(msg));
+}
diff --git a/src/userland.h b/src/userland.h
new file mode 100644
index 0000000000..e48b80d0c2
--- /dev/null
+++ b/src/userland.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#ifndef ZIG_USERLAND_H
+#define ZIG_USERLAND_H
+
+#include <stddef.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+#define ZIG_EXTERN_C extern "C"
+#else
+#define ZIG_EXTERN_C
+#endif
+
+#if defined(_MSC_VER)
+#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn)
+#else
+#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn))
+#endif
+
+// ABI warning: the types and declarations in this file must match both those in
+// userland.cpp and src-self-hosted/stage1.zig.
+
+// ABI warning
+enum Error {
+ ErrorNone,
+ ErrorNoMem,
+ ErrorInvalidFormat,
+ ErrorSemanticAnalyzeFail,
+ ErrorAccess,
+ ErrorInterrupted,
+ ErrorSystemResources,
+ ErrorFileNotFound,
+ ErrorFileSystem,
+ ErrorFileTooBig,
+ ErrorDivByZero,
+ ErrorOverflow,
+ ErrorPathAlreadyExists,
+ ErrorUnexpected,
+ ErrorExactDivRemainder,
+ ErrorNegativeDenominator,
+ ErrorShiftedOutOneBits,
+ ErrorCCompileErrors,
+ ErrorEndOfFile,
+ ErrorIsDir,
+ ErrorNotDir,
+ ErrorUnsupportedOperatingSystem,
+ ErrorSharingViolation,
+ ErrorPipeBusy,
+ ErrorPrimitiveTypeNotFound,
+ ErrorCacheUnavailable,
+ ErrorPathTooLong,
+ ErrorCCompilerCannotFindFile,
+ ErrorReadingDepFile,
+ ErrorInvalidDepFile,
+ ErrorMissingArchitecture,
+ ErrorMissingOperatingSystem,
+ ErrorUnknownArchitecture,
+ ErrorUnknownOperatingSystem,
+ ErrorUnknownABI,
+ ErrorInvalidFilename,
+ ErrorDiskQuota,
+ ErrorDiskSpace,
+ ErrorUnexpectedWriteFailure,
+ ErrorUnexpectedSeekFailure,
+ ErrorUnexpectedFileTruncationFailure,
+ ErrorUnimplemented,
+ ErrorOperationAborted,
+ ErrorBrokenPipe,
+ ErrorNoSpaceLeft,
+};
+
+// ABI warning
+enum Stage2TranslateMode {
+ Stage2TranslateModeImport,
+ Stage2TranslateModeTranslate,
+};
+
+// ABI warning
+struct Stage2ErrorMsg {
+ const char *filename_ptr; // can be null
+ size_t filename_len;
+ const char *msg_ptr;
+ size_t msg_len;
+ const char *source; // valid until the ASTUnit is freed. can be null
+ unsigned line; // 0 based
+ unsigned column; // 0 based
+ unsigned offset; // byte offset into source
+};
+
+// ABI warning
+struct Stage2Ast;
+
+// ABI warning
+ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast,
+ struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
+ const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
+ const char *resources_path);
+
+// ABI warning
+ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
+
+// ABI warning
+ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
+
+// ABI warning
+ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
+
+// ABI warning
+ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
+
+// ABI warning
+ZIG_EXTERN_C int stage2_fmt(int argc, char **argv);
+
+#endif
diff --git a/src/util.cpp b/src/util.cpp
index 192d74e766..9a6a382993 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -10,17 +10,25 @@
#include <stdarg.h>
#include "util.hpp"
+#include "userland.h"
void zig_panic(const char *format, ...) {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
- fprintf(stderr, "\n");
fflush(stderr);
va_end(ap);
+ stage2_panic(nullptr, 0);
abort();
}
+void assert(bool ok) {
+ if (!ok) {
+ const char *msg = "Assertion failed. This is a bug in the Zig compiler.";
+ stage2_panic(msg, strlen(msg));
+ }
+}
+
uint32_t int_hash(int i) {
return (uint32_t)(i % UINT32_MAX);
}
diff --git a/src/util.hpp b/src/util.hpp
index 64c85033e3..f1942dd480 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -48,6 +48,10 @@ void zig_panic(const char *format, ...);
#define zig_unreachable() zig_panic("unreachable: %s:%s:%d", __FILE__, __func__, __LINE__)
+// Assertions in stage1 are always on, and they call zig @panic.
+#undef assert
+void assert(bool ok);
+
#if defined(_MSC_VER)
static inline int clzll(unsigned long long mask) {
unsigned long lz;
diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp
index 230c3c3116..b558fa318c 100644
--- a/src/zig_clang.cpp
+++ b/src/zig_clang.cpp
@@ -28,41 +28,41 @@
#endif
// Detect additions to the enum
-void zig2clang_BO(ZigClangBO op) {
+void ZigClang_detect_enum_BO(clang::BinaryOperatorKind op) {
switch (op) {
- case ZigClangBO_PtrMemD:
- case ZigClangBO_PtrMemI:
- case ZigClangBO_Cmp:
- case ZigClangBO_Mul:
- case ZigClangBO_Div:
- case ZigClangBO_Rem:
- case ZigClangBO_Add:
- case ZigClangBO_Sub:
- case ZigClangBO_Shl:
- case ZigClangBO_Shr:
- case ZigClangBO_LT:
- case ZigClangBO_GT:
- case ZigClangBO_LE:
- case ZigClangBO_GE:
- case ZigClangBO_EQ:
- case ZigClangBO_NE:
- case ZigClangBO_And:
- case ZigClangBO_Xor:
- case ZigClangBO_Or:
- case ZigClangBO_LAnd:
- case ZigClangBO_LOr:
- case ZigClangBO_Assign:
- case ZigClangBO_Comma:
- case ZigClangBO_MulAssign:
- case ZigClangBO_DivAssign:
- case ZigClangBO_RemAssign:
- case ZigClangBO_AddAssign:
- case ZigClangBO_SubAssign:
- case ZigClangBO_ShlAssign:
- case ZigClangBO_ShrAssign:
- case ZigClangBO_AndAssign:
- case ZigClangBO_XorAssign:
- case ZigClangBO_OrAssign:
+ case clang::BO_PtrMemD:
+ case clang::BO_PtrMemI:
+ case clang::BO_Cmp:
+ case clang::BO_Mul:
+ case clang::BO_Div:
+ case clang::BO_Rem:
+ case clang::BO_Add:
+ case clang::BO_Sub:
+ case clang::BO_Shl:
+ case clang::BO_Shr:
+ case clang::BO_LT:
+ case clang::BO_GT:
+ case clang::BO_LE:
+ case clang::BO_GE:
+ case clang::BO_EQ:
+ case clang::BO_NE:
+ case clang::BO_And:
+ case clang::BO_Xor:
+ case clang::BO_Or:
+ case clang::BO_LAnd:
+ case clang::BO_LOr:
+ case clang::BO_Assign:
+ case clang::BO_Comma:
+ case clang::BO_MulAssign:
+ case clang::BO_DivAssign:
+ case clang::BO_RemAssign:
+ case clang::BO_AddAssign:
+ case clang::BO_SubAssign:
+ case clang::BO_ShlAssign:
+ case clang::BO_ShrAssign:
+ case clang::BO_AndAssign:
+ case clang::BO_XorAssign:
+ case clang::BO_OrAssign:
break;
}
}
@@ -101,23 +101,23 @@ static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAs
static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, "");
static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, "");
-// This function detects additions to the enum
-void zig2clang_UO(ZigClangUO op) {
+// Detect additions to the enum
+void ZigClang_detect_enum_UO(clang::UnaryOperatorKind op) {
switch (op) {
- case ZigClangUO_AddrOf:
- case ZigClangUO_Coawait:
- case ZigClangUO_Deref:
- case ZigClangUO_Extension:
- case ZigClangUO_Imag:
- case ZigClangUO_LNot:
- case ZigClangUO_Minus:
- case ZigClangUO_Not:
- case ZigClangUO_Plus:
- case ZigClangUO_PostDec:
- case ZigClangUO_PostInc:
- case ZigClangUO_PreDec:
- case ZigClangUO_PreInc:
- case ZigClangUO_Real:
+ case clang::UO_AddrOf:
+ case clang::UO_Coawait:
+ case clang::UO_Deref:
+ case clang::UO_Extension:
+ case clang::UO_Imag:
+ case clang::UO_LNot:
+ case clang::UO_Minus:
+ case clang::UO_Not:
+ case clang::UO_Plus:
+ case clang::UO_PostDec:
+ case clang::UO_PostInc:
+ case clang::UO_PreDec:
+ case clang::UO_PreInc:
+ case clang::UO_Real:
break;
}
}
@@ -137,6 +137,1125 @@ static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, "
static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, "");
static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, "");
+// Detect additions to the enum
+void ZigClang_detect_enum_CK(clang::CastKind x) {
+ switch (x) {
+ case clang::CK_ARCConsumeObject:
+ case clang::CK_ARCExtendBlockObject:
+ case clang::CK_ARCProduceObject:
+ case clang::CK_ARCReclaimReturnedObject:
+ case clang::CK_AddressSpaceConversion:
+ case clang::CK_AnyPointerToBlockPointerCast:
+ case clang::CK_ArrayToPointerDecay:
+ case clang::CK_AtomicToNonAtomic:
+ case clang::CK_BaseToDerived:
+ case clang::CK_BaseToDerivedMemberPointer:
+ case clang::CK_BitCast:
+ case clang::CK_BlockPointerToObjCPointerCast:
+ case clang::CK_BooleanToSignedIntegral:
+ case clang::CK_BuiltinFnToFnPtr:
+ case clang::CK_CPointerToObjCPointerCast:
+ case clang::CK_ConstructorConversion:
+ case clang::CK_CopyAndAutoreleaseBlockObject:
+ case clang::CK_Dependent:
+ case clang::CK_DerivedToBase:
+ case clang::CK_DerivedToBaseMemberPointer:
+ case clang::CK_Dynamic:
+ case clang::CK_FloatingCast:
+ case clang::CK_FloatingComplexCast:
+ case clang::CK_FloatingComplexToBoolean:
+ case clang::CK_FloatingComplexToIntegralComplex:
+ case clang::CK_FloatingComplexToReal:
+ case clang::CK_FloatingRealToComplex:
+ case clang::CK_FloatingToBoolean:
+ case clang::CK_FloatingToIntegral:
+ case clang::CK_FunctionToPointerDecay:
+ case clang::CK_IntToOCLSampler:
+ case clang::CK_IntegralCast:
+ case clang::CK_IntegralComplexCast:
+ case clang::CK_IntegralComplexToBoolean:
+ case clang::CK_IntegralComplexToFloatingComplex:
+ case clang::CK_IntegralComplexToReal:
+ case clang::CK_IntegralRealToComplex:
+ case clang::CK_IntegralToBoolean:
+ case clang::CK_IntegralToFloating:
+ case clang::CK_IntegralToPointer:
+ case clang::CK_LValueBitCast:
+ case clang::CK_LValueToRValue:
+ case clang::CK_MemberPointerToBoolean:
+ case clang::CK_NoOp:
+ case clang::CK_NonAtomicToAtomic:
+ case clang::CK_NullToMemberPointer:
+ case clang::CK_NullToPointer:
+ case clang::CK_ObjCObjectLValueCast:
+ case clang::CK_PointerToBoolean:
+ case clang::CK_PointerToIntegral:
+ case clang::CK_ReinterpretMemberPointer:
+ case clang::CK_ToUnion:
+ case clang::CK_ToVoid:
+ case clang::CK_UncheckedDerivedToBase:
+ case clang::CK_UserDefinedConversion:
+ case clang::CK_VectorSplat:
+ case clang::CK_ZeroToOCLOpaqueType:
+ case clang::CK_FixedPointCast:
+ case clang::CK_FixedPointToBoolean:
+ break;
+ }
+};
+
+static_assert((clang::CastKind)ZigClangCK_Dependent == clang::CK_Dependent, "");
+static_assert((clang::CastKind)ZigClangCK_BitCast == clang::CK_BitCast, "");
+static_assert((clang::CastKind)ZigClangCK_LValueBitCast == clang::CK_LValueBitCast, "");
+static_assert((clang::CastKind)ZigClangCK_LValueToRValue == clang::CK_LValueToRValue, "");
+static_assert((clang::CastKind)ZigClangCK_NoOp == clang::CK_NoOp, "");
+static_assert((clang::CastKind)ZigClangCK_BaseToDerived == clang::CK_BaseToDerived, "");
+static_assert((clang::CastKind)ZigClangCK_DerivedToBase == clang::CK_DerivedToBase, "");
+static_assert((clang::CastKind)ZigClangCK_UncheckedDerivedToBase == clang::CK_UncheckedDerivedToBase, "");
+static_assert((clang::CastKind)ZigClangCK_Dynamic == clang::CK_Dynamic, "");
+static_assert((clang::CastKind)ZigClangCK_ToUnion == clang::CK_ToUnion, "");
+static_assert((clang::CastKind)ZigClangCK_ArrayToPointerDecay == clang::CK_ArrayToPointerDecay, "");
+static_assert((clang::CastKind)ZigClangCK_FunctionToPointerDecay == clang::CK_FunctionToPointerDecay, "");
+static_assert((clang::CastKind)ZigClangCK_NullToPointer == clang::CK_NullToPointer, "");
+static_assert((clang::CastKind)ZigClangCK_NullToMemberPointer == clang::CK_NullToMemberPointer, "");
+static_assert((clang::CastKind)ZigClangCK_BaseToDerivedMemberPointer == clang::CK_BaseToDerivedMemberPointer, "");
+static_assert((clang::CastKind)ZigClangCK_DerivedToBaseMemberPointer == clang::CK_DerivedToBaseMemberPointer, "");
+static_assert((clang::CastKind)ZigClangCK_MemberPointerToBoolean == clang::CK_MemberPointerToBoolean, "");
+static_assert((clang::CastKind)ZigClangCK_ReinterpretMemberPointer == clang::CK_ReinterpretMemberPointer, "");
+static_assert((clang::CastKind)ZigClangCK_UserDefinedConversion == clang::CK_UserDefinedConversion, "");
+static_assert((clang::CastKind)ZigClangCK_ConstructorConversion == clang::CK_ConstructorConversion, "");
+static_assert((clang::CastKind)ZigClangCK_IntegralToPointer == clang::CK_IntegralToPointer, "");
+static_assert((clang::CastKind)ZigClangCK_PointerToIntegral == clang::CK_PointerToIntegral, "");
+static_assert((clang::CastKind)ZigClangCK_PointerToBoolean == clang::CK_PointerToBoolean, "");
+static_assert((clang::CastKind)ZigClangCK_ToVoid == clang::CK_ToVoid, "");
+static_assert((clang::CastKind)ZigClangCK_VectorSplat == clang::CK_VectorSplat, "");
+static_assert((clang::CastKind)ZigClangCK_IntegralCast == clang::CK_IntegralCast, "");
+static_assert((clang::CastKind)ZigClangCK_IntegralToBoolean == clang::CK_IntegralToBoolean, "");
+static_assert((clang::CastKind)ZigClangCK_IntegralToFloating == clang::CK_IntegralToFloating, "");
+static_assert((clang::CastKind)ZigClangCK_FixedPointCast == clang::CK_FixedPointCast, "");
+static_assert((clang::CastKind)ZigClangCK_FixedPointToBoolean == clang::CK_FixedPointToBoolean, "");
+static_assert((clang::CastKind)ZigClangCK_FloatingToIntegral == clang::CK_FloatingToIntegral, "");
+static_assert((clang::CastKind)ZigClangCK_FloatingToBoolean == clang::CK_FloatingToBoolean, "");
+static_assert((clang::CastKind)ZigClangCK_BooleanToSignedIntegral == clang::CK_BooleanToSignedIntegral, "");
+static_assert((clang::CastKind)ZigClangCK_FloatingCast == clang::CK_FloatingCast, "");
+static_assert((clang::CastKind)ZigClangCK_CPointerToObjCPointerCast == clang::CK_CPointerToObjCPointerCast, "");
+static_assert((clang::CastKind)ZigClangCK_BlockPointerToObjCPointerCast == clang::CK_BlockPointerToObjCPointerCast, "");
+static_assert((clang::CastKind)ZigClangCK_AnyPointerToBlockPointerCast == clang::CK_AnyPointerToBlockPointerCast, "");
+static_assert((clang::CastKind)ZigClangCK_ObjCObjectLValueCast == clang::CK_ObjCObjectLValueCast, "");
+static_assert((clang::CastKind)ZigClangCK_FloatingRealToComplex == clang::CK_FloatingRealToComplex, "");
+static_assert((clang::CastKind)ZigClangCK_FloatingComplexToReal == clang::CK_FloatingComplexToReal, "");
+static_assert((clang::CastKind)ZigClangCK_FloatingComplexToBoolean == clang::CK_FloatingComplexToBoolean, "");
+static_assert((clang::CastKind)ZigClangCK_FloatingComplexCast == clang::CK_FloatingComplexCast, "");
+static_assert((clang::CastKind)ZigClangCK_FloatingComplexToIntegralComplex == clang::CK_FloatingComplexToIntegralComplex, "");
+static_assert((clang::CastKind)ZigClangCK_IntegralRealToComplex == clang::CK_IntegralRealToComplex, "");
+static_assert((clang::CastKind)ZigClangCK_IntegralComplexToReal == clang::CK_IntegralComplexToReal, "");
+static_assert((clang::CastKind)ZigClangCK_IntegralComplexToBoolean == clang::CK_IntegralComplexToBoolean, "");
+static_assert((clang::CastKind)ZigClangCK_IntegralComplexCast == clang::CK_IntegralComplexCast, "");
+static_assert((clang::CastKind)ZigClangCK_IntegralComplexToFloatingComplex == clang::CK_IntegralComplexToFloatingComplex, "");
+static_assert((clang::CastKind)ZigClangCK_ARCProduceObject == clang::CK_ARCProduceObject, "");
+static_assert((clang::CastKind)ZigClangCK_ARCConsumeObject == clang::CK_ARCConsumeObject, "");
+static_assert((clang::CastKind)ZigClangCK_ARCReclaimReturnedObject == clang::CK_ARCReclaimReturnedObject, "");
+static_assert((clang::CastKind)ZigClangCK_ARCExtendBlockObject == clang::CK_ARCExtendBlockObject, "");
+static_assert((clang::CastKind)ZigClangCK_AtomicToNonAtomic == clang::CK_AtomicToNonAtomic, "");
+static_assert((clang::CastKind)ZigClangCK_NonAtomicToAtomic == clang::CK_NonAtomicToAtomic, "");
+static_assert((clang::CastKind)ZigClangCK_CopyAndAutoreleaseBlockObject == clang::CK_CopyAndAutoreleaseBlockObject, "");
+static_assert((clang::CastKind)ZigClangCK_BuiltinFnToFnPtr == clang::CK_BuiltinFnToFnPtr, "");
+static_assert((clang::CastKind)ZigClangCK_ZeroToOCLOpaqueType == clang::CK_ZeroToOCLOpaqueType, "");
+static_assert((clang::CastKind)ZigClangCK_AddressSpaceConversion == clang::CK_AddressSpaceConversion, "");
+static_assert((clang::CastKind)ZigClangCK_IntToOCLSampler == clang::CK_IntToOCLSampler, "");
+
+// Detect additions to the enum
+void ZigClang_detect_enum_TypeClass(clang::Type::TypeClass ty) {
+ switch (ty) {
+ case clang::Type::Builtin:
+ case clang::Type::Complex:
+ case clang::Type::Pointer:
+ case clang::Type::BlockPointer:
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ case clang::Type::MemberPointer:
+ case clang::Type::ConstantArray:
+ case clang::Type::IncompleteArray:
+ case clang::Type::VariableArray:
+ case clang::Type::DependentSizedArray:
+ case clang::Type::DependentSizedExtVector:
+ case clang::Type::DependentAddressSpace:
+ case clang::Type::Vector:
+ case clang::Type::DependentVector:
+ case clang::Type::ExtVector:
+ case clang::Type::FunctionProto:
+ case clang::Type::FunctionNoProto:
+ case clang::Type::UnresolvedUsing:
+ case clang::Type::Paren:
+ case clang::Type::Typedef:
+ case clang::Type::Adjusted:
+ case clang::Type::Decayed:
+ case clang::Type::TypeOfExpr:
+ case clang::Type::TypeOf:
+ case clang::Type::Decltype:
+ case clang::Type::UnaryTransform:
+ case clang::Type::Record:
+ case clang::Type::Enum:
+ case clang::Type::Elaborated:
+ case clang::Type::Attributed:
+ case clang::Type::TemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParmPack:
+ case clang::Type::TemplateSpecialization:
+ case clang::Type::Auto:
+ case clang::Type::DeducedTemplateSpecialization:
+ case clang::Type::InjectedClassName:
+ case clang::Type::DependentName:
+ case clang::Type::DependentTemplateSpecialization:
+ case clang::Type::PackExpansion:
+ case clang::Type::ObjCTypeParam:
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ case clang::Type::ObjCObjectPointer:
+ case clang::Type::Pipe:
+ case clang::Type::Atomic:
+ break;
+ }
+}
+
+static_assert((clang::Type::TypeClass)ZigClangType_Builtin == clang::Type::Builtin, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Complex == clang::Type::Complex, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Pointer == clang::Type::Pointer, "");
+static_assert((clang::Type::TypeClass)ZigClangType_BlockPointer == clang::Type::BlockPointer, "");
+static_assert((clang::Type::TypeClass)ZigClangType_LValueReference == clang::Type::LValueReference, "");
+static_assert((clang::Type::TypeClass)ZigClangType_RValueReference == clang::Type::RValueReference, "");
+static_assert((clang::Type::TypeClass)ZigClangType_MemberPointer == clang::Type::MemberPointer, "");
+static_assert((clang::Type::TypeClass)ZigClangType_ConstantArray == clang::Type::ConstantArray, "");
+static_assert((clang::Type::TypeClass)ZigClangType_IncompleteArray == clang::Type::IncompleteArray, "");
+static_assert((clang::Type::TypeClass)ZigClangType_VariableArray == clang::Type::VariableArray, "");
+static_assert((clang::Type::TypeClass)ZigClangType_DependentSizedArray == clang::Type::DependentSizedArray, "");
+static_assert((clang::Type::TypeClass)ZigClangType_DependentSizedExtVector == clang::Type::DependentSizedExtVector, "");
+static_assert((clang::Type::TypeClass)ZigClangType_DependentAddressSpace == clang::Type::DependentAddressSpace, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Vector == clang::Type::Vector, "");
+static_assert((clang::Type::TypeClass)ZigClangType_DependentVector == clang::Type::DependentVector, "");
+static_assert((clang::Type::TypeClass)ZigClangType_ExtVector == clang::Type::ExtVector, "");
+static_assert((clang::Type::TypeClass)ZigClangType_FunctionProto == clang::Type::FunctionProto, "");
+static_assert((clang::Type::TypeClass)ZigClangType_FunctionNoProto == clang::Type::FunctionNoProto, "");
+static_assert((clang::Type::TypeClass)ZigClangType_UnresolvedUsing == clang::Type::UnresolvedUsing, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Paren == clang::Type::Paren, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Typedef == clang::Type::Typedef, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Adjusted == clang::Type::Adjusted, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Decayed == clang::Type::Decayed, "");
+static_assert((clang::Type::TypeClass)ZigClangType_TypeOfExpr == clang::Type::TypeOfExpr, "");
+static_assert((clang::Type::TypeClass)ZigClangType_TypeOf == clang::Type::TypeOf, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Decltype == clang::Type::Decltype, "");
+static_assert((clang::Type::TypeClass)ZigClangType_UnaryTransform == clang::Type::UnaryTransform, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Record == clang::Type::Record, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Enum == clang::Type::Enum, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Elaborated == clang::Type::Elaborated, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Attributed == clang::Type::Attributed, "");
+static_assert((clang::Type::TypeClass)ZigClangType_TemplateTypeParm == clang::Type::TemplateTypeParm, "");
+static_assert((clang::Type::TypeClass)ZigClangType_SubstTemplateTypeParm == clang::Type::SubstTemplateTypeParm, "");
+static_assert((clang::Type::TypeClass)ZigClangType_SubstTemplateTypeParmPack == clang::Type::SubstTemplateTypeParmPack, "");
+static_assert((clang::Type::TypeClass)ZigClangType_TemplateSpecialization == clang::Type::TemplateSpecialization, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Auto == clang::Type::Auto, "");
+static_assert((clang::Type::TypeClass)ZigClangType_DeducedTemplateSpecialization == clang::Type::DeducedTemplateSpecialization, "");
+static_assert((clang::Type::TypeClass)ZigClangType_InjectedClassName == clang::Type::InjectedClassName, "");
+static_assert((clang::Type::TypeClass)ZigClangType_DependentName == clang::Type::DependentName, "");
+static_assert((clang::Type::TypeClass)ZigClangType_DependentTemplateSpecialization == clang::Type::DependentTemplateSpecialization, "");
+static_assert((clang::Type::TypeClass)ZigClangType_PackExpansion == clang::Type::PackExpansion, "");
+static_assert((clang::Type::TypeClass)ZigClangType_ObjCTypeParam == clang::Type::ObjCTypeParam, "");
+static_assert((clang::Type::TypeClass)ZigClangType_ObjCObject == clang::Type::ObjCObject, "");
+static_assert((clang::Type::TypeClass)ZigClangType_ObjCInterface == clang::Type::ObjCInterface, "");
+static_assert((clang::Type::TypeClass)ZigClangType_ObjCObjectPointer == clang::Type::ObjCObjectPointer, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Pipe == clang::Type::Pipe, "");
+static_assert((clang::Type::TypeClass)ZigClangType_Atomic == clang::Type::Atomic, "");
+
+// Detect additions to the enum
+void ZigClang_detect_enum_StmtClass(clang::Stmt::StmtClass x) {
+ switch (x) {
+ case clang::Stmt::NoStmtClass:
+ case clang::Stmt::NullStmtClass:
+ case clang::Stmt::CompoundStmtClass:
+ case clang::Stmt::LabelStmtClass:
+ case clang::Stmt::AttributedStmtClass:
+ case clang::Stmt::IfStmtClass:
+ case clang::Stmt::SwitchStmtClass:
+ case clang::Stmt::WhileStmtClass:
+ case clang::Stmt::DoStmtClass:
+ case clang::Stmt::ForStmtClass:
+ case clang::Stmt::GotoStmtClass:
+ case clang::Stmt::IndirectGotoStmtClass:
+ case clang::Stmt::ContinueStmtClass:
+ case clang::Stmt::BreakStmtClass:
+ case clang::Stmt::ReturnStmtClass:
+ case clang::Stmt::DeclStmtClass:
+ case clang::Stmt::CaseStmtClass:
+ case clang::Stmt::DefaultStmtClass:
+ case clang::Stmt::CapturedStmtClass:
+ case clang::Stmt::GCCAsmStmtClass:
+ case clang::Stmt::MSAsmStmtClass:
+ case clang::Stmt::ObjCAtTryStmtClass:
+ case clang::Stmt::ObjCAtCatchStmtClass:
+ case clang::Stmt::ObjCAtFinallyStmtClass:
+ case clang::Stmt::ObjCAtThrowStmtClass:
+ case clang::Stmt::ObjCAtSynchronizedStmtClass:
+ case clang::Stmt::ObjCForCollectionStmtClass:
+ case clang::Stmt::ObjCAutoreleasePoolStmtClass:
+ case clang::Stmt::CXXCatchStmtClass:
+ case clang::Stmt::CXXTryStmtClass:
+ case clang::Stmt::CXXForRangeStmtClass:
+ case clang::Stmt::CoroutineBodyStmtClass:
+ case clang::Stmt::CoreturnStmtClass:
+ case clang::Stmt::PredefinedExprClass:
+ case clang::Stmt::DeclRefExprClass:
+ case clang::Stmt::IntegerLiteralClass:
+ case clang::Stmt::FixedPointLiteralClass:
+ case clang::Stmt::FloatingLiteralClass:
+ case clang::Stmt::ImaginaryLiteralClass:
+ case clang::Stmt::StringLiteralClass:
+ case clang::Stmt::CharacterLiteralClass:
+ case clang::Stmt::ParenExprClass:
+ case clang::Stmt::UnaryOperatorClass:
+ case clang::Stmt::OffsetOfExprClass:
+ case clang::Stmt::UnaryExprOrTypeTraitExprClass:
+ case clang::Stmt::ArraySubscriptExprClass:
+ case clang::Stmt::OMPArraySectionExprClass:
+ case clang::Stmt::CallExprClass:
+ case clang::Stmt::MemberExprClass:
+ case clang::Stmt::BinaryOperatorClass:
+ case clang::Stmt::CompoundAssignOperatorClass:
+ case clang::Stmt::ConditionalOperatorClass:
+ case clang::Stmt::BinaryConditionalOperatorClass:
+ case clang::Stmt::ImplicitCastExprClass:
+ case clang::Stmt::CStyleCastExprClass:
+ case clang::Stmt::CompoundLiteralExprClass:
+ case clang::Stmt::ExtVectorElementExprClass:
+ case clang::Stmt::InitListExprClass:
+ case clang::Stmt::DesignatedInitExprClass:
+ case clang::Stmt::DesignatedInitUpdateExprClass:
+ case clang::Stmt::ImplicitValueInitExprClass:
+ case clang::Stmt::NoInitExprClass:
+ case clang::Stmt::ArrayInitLoopExprClass:
+ case clang::Stmt::ArrayInitIndexExprClass:
+ case clang::Stmt::ParenListExprClass:
+ case clang::Stmt::VAArgExprClass:
+ case clang::Stmt::GenericSelectionExprClass:
+ case clang::Stmt::PseudoObjectExprClass:
+ case clang::Stmt::ConstantExprClass:
+ case clang::Stmt::AtomicExprClass:
+ case clang::Stmt::AddrLabelExprClass:
+ case clang::Stmt::StmtExprClass:
+ case clang::Stmt::ChooseExprClass:
+ case clang::Stmt::GNUNullExprClass:
+ case clang::Stmt::CXXOperatorCallExprClass:
+ case clang::Stmt::CXXMemberCallExprClass:
+ case clang::Stmt::CXXStaticCastExprClass:
+ case clang::Stmt::CXXDynamicCastExprClass:
+ case clang::Stmt::CXXReinterpretCastExprClass:
+ case clang::Stmt::CXXConstCastExprClass:
+ case clang::Stmt::CXXFunctionalCastExprClass:
+ case clang::Stmt::CXXTypeidExprClass:
+ case clang::Stmt::UserDefinedLiteralClass:
+ case clang::Stmt::CXXBoolLiteralExprClass:
+ case clang::Stmt::CXXNullPtrLiteralExprClass:
+ case clang::Stmt::CXXThisExprClass:
+ case clang::Stmt::CXXThrowExprClass:
+ case clang::Stmt::CXXDefaultArgExprClass:
+ case clang::Stmt::CXXDefaultInitExprClass:
+ case clang::Stmt::CXXScalarValueInitExprClass:
+ case clang::Stmt::CXXStdInitializerListExprClass:
+ case clang::Stmt::CXXNewExprClass:
+ case clang::Stmt::CXXDeleteExprClass:
+ case clang::Stmt::CXXPseudoDestructorExprClass:
+ case clang::Stmt::TypeTraitExprClass:
+ case clang::Stmt::ArrayTypeTraitExprClass:
+ case clang::Stmt::ExpressionTraitExprClass:
+ case clang::Stmt::DependentScopeDeclRefExprClass:
+ case clang::Stmt::CXXConstructExprClass:
+ case clang::Stmt::CXXInheritedCtorInitExprClass:
+ case clang::Stmt::CXXBindTemporaryExprClass:
+ case clang::Stmt::ExprWithCleanupsClass:
+ case clang::Stmt::CXXTemporaryObjectExprClass:
+ case clang::Stmt::CXXUnresolvedConstructExprClass:
+ case clang::Stmt::CXXDependentScopeMemberExprClass:
+ case clang::Stmt::UnresolvedLookupExprClass:
+ case clang::Stmt::UnresolvedMemberExprClass:
+ case clang::Stmt::CXXNoexceptExprClass:
+ case clang::Stmt::PackExpansionExprClass:
+ case clang::Stmt::SizeOfPackExprClass:
+ case clang::Stmt::SubstNonTypeTemplateParmExprClass:
+ case clang::Stmt::SubstNonTypeTemplateParmPackExprClass:
+ case clang::Stmt::FunctionParmPackExprClass:
+ case clang::Stmt::MaterializeTemporaryExprClass:
+ case clang::Stmt::LambdaExprClass:
+ case clang::Stmt::CXXFoldExprClass:
+ case clang::Stmt::CoawaitExprClass:
+ case clang::Stmt::DependentCoawaitExprClass:
+ case clang::Stmt::CoyieldExprClass:
+ case clang::Stmt::ObjCStringLiteralClass:
+ case clang::Stmt::ObjCBoxedExprClass:
+ case clang::Stmt::ObjCArrayLiteralClass:
+ case clang::Stmt::ObjCDictionaryLiteralClass:
+ case clang::Stmt::ObjCEncodeExprClass:
+ case clang::Stmt::ObjCMessageExprClass:
+ case clang::Stmt::ObjCSelectorExprClass:
+ case clang::Stmt::ObjCProtocolExprClass:
+ case clang::Stmt::ObjCIvarRefExprClass:
+ case clang::Stmt::ObjCPropertyRefExprClass:
+ case clang::Stmt::ObjCIsaExprClass:
+ case clang::Stmt::ObjCIndirectCopyRestoreExprClass:
+ case clang::Stmt::ObjCBoolLiteralExprClass:
+ case clang::Stmt::ObjCSubscriptRefExprClass:
+ case clang::Stmt::ObjCAvailabilityCheckExprClass:
+ case clang::Stmt::ObjCBridgedCastExprClass:
+ case clang::Stmt::CUDAKernelCallExprClass:
+ case clang::Stmt::ShuffleVectorExprClass:
+ case clang::Stmt::ConvertVectorExprClass:
+ case clang::Stmt::BlockExprClass:
+ case clang::Stmt::OpaqueValueExprClass:
+ case clang::Stmt::TypoExprClass:
+ case clang::Stmt::MSPropertyRefExprClass:
+ case clang::Stmt::MSPropertySubscriptExprClass:
+ case clang::Stmt::CXXUuidofExprClass:
+ case clang::Stmt::SEHTryStmtClass:
+ case clang::Stmt::SEHExceptStmtClass:
+ case clang::Stmt::SEHFinallyStmtClass:
+ case clang::Stmt::SEHLeaveStmtClass:
+ case clang::Stmt::MSDependentExistsStmtClass:
+ case clang::Stmt::AsTypeExprClass:
+ case clang::Stmt::OMPParallelDirectiveClass:
+ case clang::Stmt::OMPSimdDirectiveClass:
+ case clang::Stmt::OMPForDirectiveClass:
+ case clang::Stmt::OMPForSimdDirectiveClass:
+ case clang::Stmt::OMPSectionsDirectiveClass:
+ case clang::Stmt::OMPSectionDirectiveClass:
+ case clang::Stmt::OMPSingleDirectiveClass:
+ case clang::Stmt::OMPMasterDirectiveClass:
+ case clang::Stmt::OMPCriticalDirectiveClass:
+ case clang::Stmt::OMPParallelForDirectiveClass:
+ case clang::Stmt::OMPParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPParallelSectionsDirectiveClass:
+ case clang::Stmt::OMPTaskDirectiveClass:
+ case clang::Stmt::OMPTaskyieldDirectiveClass:
+ case clang::Stmt::OMPBarrierDirectiveClass:
+ case clang::Stmt::OMPTaskwaitDirectiveClass:
+ case clang::Stmt::OMPTaskgroupDirectiveClass:
+ case clang::Stmt::OMPFlushDirectiveClass:
+ case clang::Stmt::OMPOrderedDirectiveClass:
+ case clang::Stmt::OMPAtomicDirectiveClass:
+ case clang::Stmt::OMPTargetDirectiveClass:
+ case clang::Stmt::OMPTargetDataDirectiveClass:
+ case clang::Stmt::OMPTargetEnterDataDirectiveClass:
+ case clang::Stmt::OMPTargetExitDataDirectiveClass:
+ case clang::Stmt::OMPTargetParallelDirectiveClass:
+ case clang::Stmt::OMPTargetParallelForDirectiveClass:
+ case clang::Stmt::OMPTargetUpdateDirectiveClass:
+ case clang::Stmt::OMPTeamsDirectiveClass:
+ case clang::Stmt::OMPCancellationPointDirectiveClass:
+ case clang::Stmt::OMPCancelDirectiveClass:
+ case clang::Stmt::OMPTaskLoopDirectiveClass:
+ case clang::Stmt::OMPTaskLoopSimdDirectiveClass:
+ case clang::Stmt::OMPDistributeDirectiveClass:
+ case clang::Stmt::OMPDistributeParallelForDirectiveClass:
+ case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPDistributeSimdDirectiveClass:
+ case clang::Stmt::OMPTargetParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPTargetSimdDirectiveClass:
+ case clang::Stmt::OMPTeamsDistributeDirectiveClass:
+ case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
+ break;
+ }
+}
+
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_NoStmtClass == clang::Stmt::NoStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_NullStmtClass == clang::Stmt::NullStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CompoundStmtClass == clang::Stmt::CompoundStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_LabelStmtClass == clang::Stmt::LabelStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_AttributedStmtClass == clang::Stmt::AttributedStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_IfStmtClass == clang::Stmt::IfStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_SwitchStmtClass == clang::Stmt::SwitchStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_WhileStmtClass == clang::Stmt::WhileStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_DoStmtClass == clang::Stmt::DoStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ForStmtClass == clang::Stmt::ForStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_GotoStmtClass == clang::Stmt::GotoStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_IndirectGotoStmtClass == clang::Stmt::IndirectGotoStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ContinueStmtClass == clang::Stmt::ContinueStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_BreakStmtClass == clang::Stmt::BreakStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ReturnStmtClass == clang::Stmt::ReturnStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_DeclStmtClass == clang::Stmt::DeclStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CaseStmtClass == clang::Stmt::CaseStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_DefaultStmtClass == clang::Stmt::DefaultStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CapturedStmtClass == clang::Stmt::CapturedStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_GCCAsmStmtClass == clang::Stmt::GCCAsmStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSAsmStmtClass == clang::Stmt::MSAsmStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtTryStmtClass == clang::Stmt::ObjCAtTryStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtCatchStmtClass == clang::Stmt::ObjCAtCatchStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtFinallyStmtClass == clang::Stmt::ObjCAtFinallyStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtThrowStmtClass == clang::Stmt::ObjCAtThrowStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtSynchronizedStmtClass == clang::Stmt::ObjCAtSynchronizedStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCForCollectionStmtClass == clang::Stmt::ObjCForCollectionStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAutoreleasePoolStmtClass == clang::Stmt::ObjCAutoreleasePoolStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXCatchStmtClass == clang::Stmt::CXXCatchStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXTryStmtClass == clang::Stmt::CXXTryStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXForRangeStmtClass == clang::Stmt::CXXForRangeStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoroutineBodyStmtClass == clang::Stmt::CoroutineBodyStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoreturnStmtClass == clang::Stmt::CoreturnStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_PredefinedExprClass == clang::Stmt::PredefinedExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_DeclRefExprClass == clang::Stmt::DeclRefExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_IntegerLiteralClass == clang::Stmt::IntegerLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_FixedPointLiteralClass == clang::Stmt::FixedPointLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_FloatingLiteralClass == clang::Stmt::FloatingLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ImaginaryLiteralClass == clang::Stmt::ImaginaryLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_StringLiteralClass == clang::Stmt::StringLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CharacterLiteralClass == clang::Stmt::CharacterLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ParenExprClass == clang::Stmt::ParenExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnaryOperatorClass == clang::Stmt::UnaryOperatorClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OffsetOfExprClass == clang::Stmt::OffsetOfExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnaryExprOrTypeTraitExprClass == clang::Stmt::UnaryExprOrTypeTraitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArraySubscriptExprClass == clang::Stmt::ArraySubscriptExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPArraySectionExprClass == clang::Stmt::OMPArraySectionExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CallExprClass == clang::Stmt::CallExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_MemberExprClass == clang::Stmt::MemberExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_BinaryOperatorClass == clang::Stmt::BinaryOperatorClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CompoundAssignOperatorClass == clang::Stmt::CompoundAssignOperatorClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ConditionalOperatorClass == clang::Stmt::ConditionalOperatorClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_BinaryConditionalOperatorClass == clang::Stmt::BinaryConditionalOperatorClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ImplicitCastExprClass == clang::Stmt::ImplicitCastExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CStyleCastExprClass == clang::Stmt::CStyleCastExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CompoundLiteralExprClass == clang::Stmt::CompoundLiteralExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ExtVectorElementExprClass == clang::Stmt::ExtVectorElementExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_InitListExprClass == clang::Stmt::InitListExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_DesignatedInitExprClass == clang::Stmt::DesignatedInitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_DesignatedInitUpdateExprClass == clang::Stmt::DesignatedInitUpdateExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ImplicitValueInitExprClass == clang::Stmt::ImplicitValueInitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_NoInitExprClass == clang::Stmt::NoInitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArrayInitLoopExprClass == clang::Stmt::ArrayInitLoopExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArrayInitIndexExprClass == clang::Stmt::ArrayInitIndexExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ParenListExprClass == clang::Stmt::ParenListExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_VAArgExprClass == clang::Stmt::VAArgExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_GenericSelectionExprClass == clang::Stmt::GenericSelectionExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_PseudoObjectExprClass == clang::Stmt::PseudoObjectExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ConstantExprClass == clang::Stmt::ConstantExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_AtomicExprClass == clang::Stmt::AtomicExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_AddrLabelExprClass == clang::Stmt::AddrLabelExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_StmtExprClass == clang::Stmt::StmtExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ChooseExprClass == clang::Stmt::ChooseExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_GNUNullExprClass == clang::Stmt::GNUNullExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXOperatorCallExprClass == clang::Stmt::CXXOperatorCallExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXMemberCallExprClass == clang::Stmt::CXXMemberCallExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXStaticCastExprClass == clang::Stmt::CXXStaticCastExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDynamicCastExprClass == clang::Stmt::CXXDynamicCastExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXReinterpretCastExprClass == clang::Stmt::CXXReinterpretCastExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXConstCastExprClass == clang::Stmt::CXXConstCastExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXFunctionalCastExprClass == clang::Stmt::CXXFunctionalCastExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXTypeidExprClass == clang::Stmt::CXXTypeidExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_UserDefinedLiteralClass == clang::Stmt::UserDefinedLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXBoolLiteralExprClass == clang::Stmt::CXXBoolLiteralExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXNullPtrLiteralExprClass == clang::Stmt::CXXNullPtrLiteralExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXThisExprClass == clang::Stmt::CXXThisExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXThrowExprClass == clang::Stmt::CXXThrowExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDefaultArgExprClass == clang::Stmt::CXXDefaultArgExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDefaultInitExprClass == clang::Stmt::CXXDefaultInitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXScalarValueInitExprClass == clang::Stmt::CXXScalarValueInitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXStdInitializerListExprClass == clang::Stmt::CXXStdInitializerListExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXNewExprClass == clang::Stmt::CXXNewExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDeleteExprClass == clang::Stmt::CXXDeleteExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXPseudoDestructorExprClass == clang::Stmt::CXXPseudoDestructorExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_TypeTraitExprClass == clang::Stmt::TypeTraitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArrayTypeTraitExprClass == clang::Stmt::ArrayTypeTraitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ExpressionTraitExprClass == clang::Stmt::ExpressionTraitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_DependentScopeDeclRefExprClass == clang::Stmt::DependentScopeDeclRefExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXConstructExprClass == clang::Stmt::CXXConstructExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXInheritedCtorInitExprClass == clang::Stmt::CXXInheritedCtorInitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXBindTemporaryExprClass == clang::Stmt::CXXBindTemporaryExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ExprWithCleanupsClass == clang::Stmt::ExprWithCleanupsClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXTemporaryObjectExprClass == clang::Stmt::CXXTemporaryObjectExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXUnresolvedConstructExprClass == clang::Stmt::CXXUnresolvedConstructExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDependentScopeMemberExprClass == clang::Stmt::CXXDependentScopeMemberExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnresolvedLookupExprClass == clang::Stmt::UnresolvedLookupExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnresolvedMemberExprClass == clang::Stmt::UnresolvedMemberExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXNoexceptExprClass == clang::Stmt::CXXNoexceptExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_PackExpansionExprClass == clang::Stmt::PackExpansionExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_SizeOfPackExprClass == clang::Stmt::SizeOfPackExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_SubstNonTypeTemplateParmExprClass == clang::Stmt::SubstNonTypeTemplateParmExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_SubstNonTypeTemplateParmPackExprClass == clang::Stmt::SubstNonTypeTemplateParmPackExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_FunctionParmPackExprClass == clang::Stmt::FunctionParmPackExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_MaterializeTemporaryExprClass == clang::Stmt::MaterializeTemporaryExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_LambdaExprClass == clang::Stmt::LambdaExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXFoldExprClass == clang::Stmt::CXXFoldExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoawaitExprClass == clang::Stmt::CoawaitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_DependentCoawaitExprClass == clang::Stmt::DependentCoawaitExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoyieldExprClass == clang::Stmt::CoyieldExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCStringLiteralClass == clang::Stmt::ObjCStringLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCBoxedExprClass == clang::Stmt::ObjCBoxedExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCArrayLiteralClass == clang::Stmt::ObjCArrayLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCDictionaryLiteralClass == clang::Stmt::ObjCDictionaryLiteralClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCEncodeExprClass == clang::Stmt::ObjCEncodeExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCMessageExprClass == clang::Stmt::ObjCMessageExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCSelectorExprClass == clang::Stmt::ObjCSelectorExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCProtocolExprClass == clang::Stmt::ObjCProtocolExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCIvarRefExprClass == clang::Stmt::ObjCIvarRefExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCPropertyRefExprClass == clang::Stmt::ObjCPropertyRefExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCIsaExprClass == clang::Stmt::ObjCIsaExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCIndirectCopyRestoreExprClass == clang::Stmt::ObjCIndirectCopyRestoreExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCBoolLiteralExprClass == clang::Stmt::ObjCBoolLiteralExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCSubscriptRefExprClass == clang::Stmt::ObjCSubscriptRefExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAvailabilityCheckExprClass == clang::Stmt::ObjCAvailabilityCheckExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCBridgedCastExprClass == clang::Stmt::ObjCBridgedCastExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CUDAKernelCallExprClass == clang::Stmt::CUDAKernelCallExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ShuffleVectorExprClass == clang::Stmt::ShuffleVectorExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_ConvertVectorExprClass == clang::Stmt::ConvertVectorExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_BlockExprClass == clang::Stmt::BlockExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OpaqueValueExprClass == clang::Stmt::OpaqueValueExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_TypoExprClass == clang::Stmt::TypoExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSPropertyRefExprClass == clang::Stmt::MSPropertyRefExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSPropertySubscriptExprClass == clang::Stmt::MSPropertySubscriptExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXUuidofExprClass == clang::Stmt::CXXUuidofExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHTryStmtClass == clang::Stmt::SEHTryStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHExceptStmtClass == clang::Stmt::SEHExceptStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHFinallyStmtClass == clang::Stmt::SEHFinallyStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHLeaveStmtClass == clang::Stmt::SEHLeaveStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSDependentExistsStmtClass == clang::Stmt::MSDependentExistsStmtClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_AsTypeExprClass == clang::Stmt::AsTypeExprClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelDirectiveClass == clang::Stmt::OMPParallelDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSimdDirectiveClass == clang::Stmt::OMPSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPForDirectiveClass == clang::Stmt::OMPForDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPForSimdDirectiveClass == clang::Stmt::OMPForSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSectionsDirectiveClass == clang::Stmt::OMPSectionsDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSectionDirectiveClass == clang::Stmt::OMPSectionDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSingleDirectiveClass == clang::Stmt::OMPSingleDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMasterDirectiveClass == clang::Stmt::OMPMasterDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPCriticalDirectiveClass == clang::Stmt::OMPCriticalDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelForDirectiveClass == clang::Stmt::OMPParallelForDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelForSimdDirectiveClass == clang::Stmt::OMPParallelForSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelSectionsDirectiveClass == clang::Stmt::OMPParallelSectionsDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskDirectiveClass == clang::Stmt::OMPTaskDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskyieldDirectiveClass == clang::Stmt::OMPTaskyieldDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPBarrierDirectiveClass == clang::Stmt::OMPBarrierDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskwaitDirectiveClass == clang::Stmt::OMPTaskwaitDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskgroupDirectiveClass == clang::Stmt::OMPTaskgroupDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPFlushDirectiveClass == clang::Stmt::OMPFlushDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPOrderedDirectiveClass == clang::Stmt::OMPOrderedDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPAtomicDirectiveClass == clang::Stmt::OMPAtomicDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetDirectiveClass == clang::Stmt::OMPTargetDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetDataDirectiveClass == clang::Stmt::OMPTargetDataDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetEnterDataDirectiveClass == clang::Stmt::OMPTargetEnterDataDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetExitDataDirectiveClass == clang::Stmt::OMPTargetExitDataDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelDirectiveClass == clang::Stmt::OMPTargetParallelDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelForDirectiveClass == clang::Stmt::OMPTargetParallelForDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetUpdateDirectiveClass == clang::Stmt::OMPTargetUpdateDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDirectiveClass == clang::Stmt::OMPTeamsDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPCancellationPointDirectiveClass == clang::Stmt::OMPCancellationPointDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPCancelDirectiveClass == clang::Stmt::OMPCancelDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskLoopDirectiveClass == clang::Stmt::OMPTaskLoopDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskLoopSimdDirectiveClass == clang::Stmt::OMPTaskLoopSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeDirectiveClass == clang::Stmt::OMPDistributeDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeParallelForDirectiveClass == clang::Stmt::OMPDistributeParallelForDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPDistributeParallelForSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeSimdDirectiveClass == clang::Stmt::OMPDistributeSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelForSimdDirectiveClass == clang::Stmt::OMPTargetParallelForSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetSimdDirectiveClass == clang::Stmt::OMPTargetSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeDirectiveClass == clang::Stmt::OMPTeamsDistributeDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass == clang::Stmt::OMPTeamsDistributeSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass == clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDirectiveClass == clang::Stmt::OMPTargetTeamsDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass, "");
+static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass, "");
+
+void ZigClang_detect_enum_APValueKind(clang::APValue::ValueKind x) {
+ switch (x) {
+ case clang::APValue::Uninitialized:
+ case clang::APValue::Int:
+ case clang::APValue::Float:
+ case clang::APValue::ComplexInt:
+ case clang::APValue::ComplexFloat:
+ case clang::APValue::LValue:
+ case clang::APValue::Vector:
+ case clang::APValue::Array:
+ case clang::APValue::Struct:
+ case clang::APValue::Union:
+ case clang::APValue::MemberPointer:
+ case clang::APValue::AddrLabelDiff:
+ break;
+ }
+}
+
+static_assert((clang::APValue::ValueKind)ZigClangAPValueUninitialized == clang::APValue::Uninitialized, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueInt == clang::APValue::Int, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueFloat == clang::APValue::Float, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueComplexInt == clang::APValue::ComplexInt, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueComplexFloat == clang::APValue::ComplexFloat, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueLValue == clang::APValue::LValue, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueVector == clang::APValue::Vector, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueArray == clang::APValue::Array, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueStruct == clang::APValue::Struct, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueUnion == clang::APValue::Union, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueMemberPointer == clang::APValue::MemberPointer, "");
+static_assert((clang::APValue::ValueKind)ZigClangAPValueAddrLabelDiff == clang::APValue::AddrLabelDiff, "");
+
+
+void ZigClang_detect_enum_DeclKind(clang::Decl::Kind x) {
+ switch (x) {
+ case clang::Decl::AccessSpec:
+ case clang::Decl::Block:
+ case clang::Decl::Captured:
+ case clang::Decl::ClassScopeFunctionSpecialization:
+ case clang::Decl::Empty:
+ case clang::Decl::Export:
+ case clang::Decl::ExternCContext:
+ case clang::Decl::FileScopeAsm:
+ case clang::Decl::Friend:
+ case clang::Decl::FriendTemplate:
+ case clang::Decl::Import:
+ case clang::Decl::LinkageSpec:
+ case clang::Decl::Label:
+ case clang::Decl::Namespace:
+ case clang::Decl::NamespaceAlias:
+ case clang::Decl::ObjCCompatibleAlias:
+ case clang::Decl::ObjCCategory:
+ case clang::Decl::ObjCCategoryImpl:
+ case clang::Decl::ObjCImplementation:
+ case clang::Decl::ObjCInterface:
+ case clang::Decl::ObjCProtocol:
+ case clang::Decl::ObjCMethod:
+ case clang::Decl::ObjCProperty:
+ case clang::Decl::BuiltinTemplate:
+ case clang::Decl::ClassTemplate:
+ case clang::Decl::FunctionTemplate:
+ case clang::Decl::TypeAliasTemplate:
+ case clang::Decl::VarTemplate:
+ case clang::Decl::TemplateTemplateParm:
+ case clang::Decl::Enum:
+ case clang::Decl::Record:
+ case clang::Decl::CXXRecord:
+ case clang::Decl::ClassTemplateSpecialization:
+ case clang::Decl::ClassTemplatePartialSpecialization:
+ case clang::Decl::TemplateTypeParm:
+ case clang::Decl::ObjCTypeParam:
+ case clang::Decl::TypeAlias:
+ case clang::Decl::Typedef:
+ case clang::Decl::UnresolvedUsingTypename:
+ case clang::Decl::Using:
+ case clang::Decl::UsingDirective:
+ case clang::Decl::UsingPack:
+ case clang::Decl::UsingShadow:
+ case clang::Decl::ConstructorUsingShadow:
+ case clang::Decl::Binding:
+ case clang::Decl::Field:
+ case clang::Decl::ObjCAtDefsField:
+ case clang::Decl::ObjCIvar:
+ case clang::Decl::Function:
+ case clang::Decl::CXXDeductionGuide:
+ case clang::Decl::CXXMethod:
+ case clang::Decl::CXXConstructor:
+ case clang::Decl::CXXConversion:
+ case clang::Decl::CXXDestructor:
+ case clang::Decl::MSProperty:
+ case clang::Decl::NonTypeTemplateParm:
+ case clang::Decl::Var:
+ case clang::Decl::Decomposition:
+ case clang::Decl::ImplicitParam:
+ case clang::Decl::OMPCapturedExpr:
+ case clang::Decl::ParmVar:
+ case clang::Decl::VarTemplateSpecialization:
+ case clang::Decl::VarTemplatePartialSpecialization:
+ case clang::Decl::EnumConstant:
+ case clang::Decl::IndirectField:
+ case clang::Decl::OMPDeclareReduction:
+ case clang::Decl::UnresolvedUsingValue:
+ case clang::Decl::OMPRequires:
+ case clang::Decl::OMPThreadPrivate:
+ case clang::Decl::ObjCPropertyImpl:
+ case clang::Decl::PragmaComment:
+ case clang::Decl::PragmaDetectMismatch:
+ case clang::Decl::StaticAssert:
+ case clang::Decl::TranslationUnit:
+ break;
+ }
+}
+
+static_assert((clang::Decl::Kind)ZigClangDeclAccessSpec == clang::Decl::AccessSpec, "");
+static_assert((clang::Decl::Kind)ZigClangDeclBlock == clang::Decl::Block, "");
+static_assert((clang::Decl::Kind)ZigClangDeclCaptured == clang::Decl::Captured, "");
+static_assert((clang::Decl::Kind)ZigClangDeclClassScopeFunctionSpecialization == clang::Decl::ClassScopeFunctionSpecialization, "");
+static_assert((clang::Decl::Kind)ZigClangDeclEmpty == clang::Decl::Empty, "");
+static_assert((clang::Decl::Kind)ZigClangDeclExport == clang::Decl::Export, "");
+static_assert((clang::Decl::Kind)ZigClangDeclExternCContext == clang::Decl::ExternCContext, "");
+static_assert((clang::Decl::Kind)ZigClangDeclFileScopeAsm == clang::Decl::FileScopeAsm, "");
+static_assert((clang::Decl::Kind)ZigClangDeclFriend == clang::Decl::Friend, "");
+static_assert((clang::Decl::Kind)ZigClangDeclFriendTemplate == clang::Decl::FriendTemplate, "");
+static_assert((clang::Decl::Kind)ZigClangDeclImport == clang::Decl::Import, "");
+static_assert((clang::Decl::Kind)ZigClangDeclLinkageSpec == clang::Decl::LinkageSpec, "");
+static_assert((clang::Decl::Kind)ZigClangDeclLabel == clang::Decl::Label, "");
+static_assert((clang::Decl::Kind)ZigClangDeclNamespace == clang::Decl::Namespace, "");
+static_assert((clang::Decl::Kind)ZigClangDeclNamespaceAlias == clang::Decl::NamespaceAlias, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCCompatibleAlias == clang::Decl::ObjCCompatibleAlias, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCCategory == clang::Decl::ObjCCategory, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCCategoryImpl == clang::Decl::ObjCCategoryImpl, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCImplementation == clang::Decl::ObjCImplementation, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCInterface == clang::Decl::ObjCInterface, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCProtocol == clang::Decl::ObjCProtocol, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCMethod == clang::Decl::ObjCMethod, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCProperty == clang::Decl::ObjCProperty, "");
+static_assert((clang::Decl::Kind)ZigClangDeclBuiltinTemplate == clang::Decl::BuiltinTemplate, "");
+static_assert((clang::Decl::Kind)ZigClangDeclClassTemplate == clang::Decl::ClassTemplate, "");
+static_assert((clang::Decl::Kind)ZigClangDeclFunctionTemplate == clang::Decl::FunctionTemplate, "");
+static_assert((clang::Decl::Kind)ZigClangDeclTypeAliasTemplate == clang::Decl::TypeAliasTemplate, "");
+static_assert((clang::Decl::Kind)ZigClangDeclVarTemplate == clang::Decl::VarTemplate, "");
+static_assert((clang::Decl::Kind)ZigClangDeclTemplateTemplateParm == clang::Decl::TemplateTemplateParm, "");
+static_assert((clang::Decl::Kind)ZigClangDeclEnum == clang::Decl::Enum, "");
+static_assert((clang::Decl::Kind)ZigClangDeclRecord == clang::Decl::Record, "");
+static_assert((clang::Decl::Kind)ZigClangDeclCXXRecord == clang::Decl::CXXRecord, "");
+static_assert((clang::Decl::Kind)ZigClangDeclClassTemplateSpecialization == clang::Decl::ClassTemplateSpecialization, "");
+static_assert((clang::Decl::Kind)ZigClangDeclClassTemplatePartialSpecialization == clang::Decl::ClassTemplatePartialSpecialization, "");
+static_assert((clang::Decl::Kind)ZigClangDeclTemplateTypeParm == clang::Decl::TemplateTypeParm, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCTypeParam == clang::Decl::ObjCTypeParam, "");
+static_assert((clang::Decl::Kind)ZigClangDeclTypeAlias == clang::Decl::TypeAlias, "");
+static_assert((clang::Decl::Kind)ZigClangDeclTypedef == clang::Decl::Typedef, "");
+static_assert((clang::Decl::Kind)ZigClangDeclUnresolvedUsingTypename == clang::Decl::UnresolvedUsingTypename, "");
+static_assert((clang::Decl::Kind)ZigClangDeclUsing == clang::Decl::Using, "");
+static_assert((clang::Decl::Kind)ZigClangDeclUsingDirective == clang::Decl::UsingDirective, "");
+static_assert((clang::Decl::Kind)ZigClangDeclUsingPack == clang::Decl::UsingPack, "");
+static_assert((clang::Decl::Kind)ZigClangDeclUsingShadow == clang::Decl::UsingShadow, "");
+static_assert((clang::Decl::Kind)ZigClangDeclConstructorUsingShadow == clang::Decl::ConstructorUsingShadow, "");
+static_assert((clang::Decl::Kind)ZigClangDeclBinding == clang::Decl::Binding, "");
+static_assert((clang::Decl::Kind)ZigClangDeclField == clang::Decl::Field, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCAtDefsField == clang::Decl::ObjCAtDefsField, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCIvar == clang::Decl::ObjCIvar, "");
+static_assert((clang::Decl::Kind)ZigClangDeclFunction == clang::Decl::Function, "");
+static_assert((clang::Decl::Kind)ZigClangDeclCXXDeductionGuide == clang::Decl::CXXDeductionGuide, "");
+static_assert((clang::Decl::Kind)ZigClangDeclCXXMethod == clang::Decl::CXXMethod, "");
+static_assert((clang::Decl::Kind)ZigClangDeclCXXConstructor == clang::Decl::CXXConstructor, "");
+static_assert((clang::Decl::Kind)ZigClangDeclCXXConversion == clang::Decl::CXXConversion, "");
+static_assert((clang::Decl::Kind)ZigClangDeclCXXDestructor == clang::Decl::CXXDestructor, "");
+static_assert((clang::Decl::Kind)ZigClangDeclMSProperty == clang::Decl::MSProperty, "");
+static_assert((clang::Decl::Kind)ZigClangDeclNonTypeTemplateParm == clang::Decl::NonTypeTemplateParm, "");
+static_assert((clang::Decl::Kind)ZigClangDeclVar == clang::Decl::Var, "");
+static_assert((clang::Decl::Kind)ZigClangDeclDecomposition == clang::Decl::Decomposition, "");
+static_assert((clang::Decl::Kind)ZigClangDeclImplicitParam == clang::Decl::ImplicitParam, "");
+static_assert((clang::Decl::Kind)ZigClangDeclOMPCapturedExpr == clang::Decl::OMPCapturedExpr, "");
+static_assert((clang::Decl::Kind)ZigClangDeclParmVar == clang::Decl::ParmVar, "");
+static_assert((clang::Decl::Kind)ZigClangDeclVarTemplateSpecialization == clang::Decl::VarTemplateSpecialization, "");
+static_assert((clang::Decl::Kind)ZigClangDeclVarTemplatePartialSpecialization == clang::Decl::VarTemplatePartialSpecialization, "");
+static_assert((clang::Decl::Kind)ZigClangDeclEnumConstant == clang::Decl::EnumConstant, "");
+static_assert((clang::Decl::Kind)ZigClangDeclIndirectField == clang::Decl::IndirectField, "");
+static_assert((clang::Decl::Kind)ZigClangDeclOMPDeclareReduction == clang::Decl::OMPDeclareReduction, "");
+static_assert((clang::Decl::Kind)ZigClangDeclUnresolvedUsingValue == clang::Decl::UnresolvedUsingValue, "");
+static_assert((clang::Decl::Kind)ZigClangDeclOMPRequires == clang::Decl::OMPRequires, "");
+static_assert((clang::Decl::Kind)ZigClangDeclOMPThreadPrivate == clang::Decl::OMPThreadPrivate, "");
+static_assert((clang::Decl::Kind)ZigClangDeclObjCPropertyImpl == clang::Decl::ObjCPropertyImpl, "");
+static_assert((clang::Decl::Kind)ZigClangDeclPragmaComment == clang::Decl::PragmaComment, "");
+static_assert((clang::Decl::Kind)ZigClangDeclPragmaDetectMismatch == clang::Decl::PragmaDetectMismatch, "");
+static_assert((clang::Decl::Kind)ZigClangDeclStaticAssert == clang::Decl::StaticAssert, "");
+static_assert((clang::Decl::Kind)ZigClangDeclTranslationUnit == clang::Decl::TranslationUnit, "");
+
+void ZigClang_detect_enum_BuiltinTypeKind(clang::BuiltinType::Kind x) {
+ switch (x) {
+ case clang::BuiltinType::OCLImage1dRO:
+ case clang::BuiltinType::OCLImage1dArrayRO:
+ case clang::BuiltinType::OCLImage1dBufferRO:
+ case clang::BuiltinType::OCLImage2dRO:
+ case clang::BuiltinType::OCLImage2dArrayRO:
+ case clang::BuiltinType::OCLImage2dDepthRO:
+ case clang::BuiltinType::OCLImage2dArrayDepthRO:
+ case clang::BuiltinType::OCLImage2dMSAARO:
+ case clang::BuiltinType::OCLImage2dArrayMSAARO:
+ case clang::BuiltinType::OCLImage2dMSAADepthRO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
+ case clang::BuiltinType::OCLImage3dRO:
+ case clang::BuiltinType::OCLImage1dWO:
+ case clang::BuiltinType::OCLImage1dArrayWO:
+ case clang::BuiltinType::OCLImage1dBufferWO:
+ case clang::BuiltinType::OCLImage2dWO:
+ case clang::BuiltinType::OCLImage2dArrayWO:
+ case clang::BuiltinType::OCLImage2dDepthWO:
+ case clang::BuiltinType::OCLImage2dArrayDepthWO:
+ case clang::BuiltinType::OCLImage2dMSAAWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAAWO:
+ case clang::BuiltinType::OCLImage2dMSAADepthWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
+ case clang::BuiltinType::OCLImage3dWO:
+ case clang::BuiltinType::OCLImage1dRW:
+ case clang::BuiltinType::OCLImage1dArrayRW:
+ case clang::BuiltinType::OCLImage1dBufferRW:
+ case clang::BuiltinType::OCLImage2dRW:
+ case clang::BuiltinType::OCLImage2dArrayRW:
+ case clang::BuiltinType::OCLImage2dDepthRW:
+ case clang::BuiltinType::OCLImage2dArrayDepthRW:
+ case clang::BuiltinType::OCLImage2dMSAARW:
+ case clang::BuiltinType::OCLImage2dArrayMSAARW:
+ case clang::BuiltinType::OCLImage2dMSAADepthRW:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
+ case clang::BuiltinType::OCLImage3dRW:
+ case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
+ case clang::BuiltinType::Void:
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char8:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::ShortAccum:
+ case clang::BuiltinType::Accum:
+ case clang::BuiltinType::LongAccum:
+ case clang::BuiltinType::UShortAccum:
+ case clang::BuiltinType::UAccum:
+ case clang::BuiltinType::ULongAccum:
+ case clang::BuiltinType::ShortFract:
+ case clang::BuiltinType::Fract:
+ case clang::BuiltinType::LongFract:
+ case clang::BuiltinType::UShortFract:
+ case clang::BuiltinType::UFract:
+ case clang::BuiltinType::ULongFract:
+ case clang::BuiltinType::SatShortAccum:
+ case clang::BuiltinType::SatAccum:
+ case clang::BuiltinType::SatLongAccum:
+ case clang::BuiltinType::SatUShortAccum:
+ case clang::BuiltinType::SatUAccum:
+ case clang::BuiltinType::SatULongAccum:
+ case clang::BuiltinType::SatShortFract:
+ case clang::BuiltinType::SatFract:
+ case clang::BuiltinType::SatLongFract:
+ case clang::BuiltinType::SatUShortFract:
+ case clang::BuiltinType::SatUFract:
+ case clang::BuiltinType::SatULongFract:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::LongDouble:
+ case clang::BuiltinType::Float16:
+ case clang::BuiltinType::Float128:
+ case clang::BuiltinType::NullPtr:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
+ case clang::BuiltinType::OCLSampler:
+ case clang::BuiltinType::OCLEvent:
+ case clang::BuiltinType::OCLClkEvent:
+ case clang::BuiltinType::OCLQueue:
+ case clang::BuiltinType::OCLReserveID:
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::BoundMember:
+ case clang::BuiltinType::PseudoObject:
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::BuiltinFn:
+ case clang::BuiltinType::ARCUnbridgedCast:
+ case clang::BuiltinType::OMPArraySection:
+ break;
+ }
+}
+
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dRO == clang::BuiltinType::OCLImage1dRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dArrayRO == clang::BuiltinType::OCLImage1dArrayRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dBufferRO == clang::BuiltinType::OCLImage1dBufferRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dRO == clang::BuiltinType::OCLImage2dRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayRO == clang::BuiltinType::OCLImage2dArrayRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dDepthRO == clang::BuiltinType::OCLImage2dDepthRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayDepthRO == clang::BuiltinType::OCLImage2dArrayDepthRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAARO == clang::BuiltinType::OCLImage2dMSAARO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAARO == clang::BuiltinType::OCLImage2dArrayMSAARO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAADepthRO == clang::BuiltinType::OCLImage2dMSAADepthRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO == clang::BuiltinType::OCLImage2dArrayMSAADepthRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage3dRO == clang::BuiltinType::OCLImage3dRO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dWO == clang::BuiltinType::OCLImage1dWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dArrayWO == clang::BuiltinType::OCLImage1dArrayWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dBufferWO == clang::BuiltinType::OCLImage1dBufferWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dWO == clang::BuiltinType::OCLImage2dWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayWO == clang::BuiltinType::OCLImage2dArrayWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dDepthWO == clang::BuiltinType::OCLImage2dDepthWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayDepthWO == clang::BuiltinType::OCLImage2dArrayDepthWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAAWO == clang::BuiltinType::OCLImage2dMSAAWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAAWO == clang::BuiltinType::OCLImage2dArrayMSAAWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAADepthWO == clang::BuiltinType::OCLImage2dMSAADepthWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO == clang::BuiltinType::OCLImage2dArrayMSAADepthWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage3dWO == clang::BuiltinType::OCLImage3dWO, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dRW == clang::BuiltinType::OCLImage1dRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dArrayRW == clang::BuiltinType::OCLImage1dArrayRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dBufferRW == clang::BuiltinType::OCLImage1dBufferRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dRW == clang::BuiltinType::OCLImage2dRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayRW == clang::BuiltinType::OCLImage2dArrayRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dDepthRW == clang::BuiltinType::OCLImage2dDepthRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayDepthRW == clang::BuiltinType::OCLImage2dArrayDepthRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAARW == clang::BuiltinType::OCLImage2dMSAARW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAARW == clang::BuiltinType::OCLImage2dArrayMSAARW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAADepthRW == clang::BuiltinType::OCLImage2dMSAADepthRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW == clang::BuiltinType::OCLImage2dArrayMSAADepthRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage3dRW == clang::BuiltinType::OCLImage3dRW, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload == clang::BuiltinType::OCLIntelSubgroupAVCMcePayload, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload == clang::BuiltinType::OCLIntelSubgroupAVCImePayload, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload == clang::BuiltinType::OCLIntelSubgroupAVCRefPayload, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload == clang::BuiltinType::OCLIntelSubgroupAVCSicPayload, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult == clang::BuiltinType::OCLIntelSubgroupAVCMceResult, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult == clang::BuiltinType::OCLIntelSubgroupAVCImeResult, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult == clang::BuiltinType::OCLIntelSubgroupAVCRefResult, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult == clang::BuiltinType::OCLIntelSubgroupAVCSicResult, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout == clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout == clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin == clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin == clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeVoid == clang::BuiltinType::Void, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeBool == clang::BuiltinType::Bool, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar_U == clang::BuiltinType::Char_U, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUChar == clang::BuiltinType::UChar, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeWChar_U == clang::BuiltinType::WChar_U, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar8 == clang::BuiltinType::Char8, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar16 == clang::BuiltinType::Char16, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar32 == clang::BuiltinType::Char32, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUShort == clang::BuiltinType::UShort, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUInt == clang::BuiltinType::UInt, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULong == clang::BuiltinType::ULong, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULongLong == clang::BuiltinType::ULongLong, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUInt128 == clang::BuiltinType::UInt128, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar_S == clang::BuiltinType::Char_S, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSChar == clang::BuiltinType::SChar, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeWChar_S == clang::BuiltinType::WChar_S, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeShort == clang::BuiltinType::Short, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeInt == clang::BuiltinType::Int, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLong == clang::BuiltinType::Long, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongLong == clang::BuiltinType::LongLong, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeInt128 == clang::BuiltinType::Int128, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeShortAccum == clang::BuiltinType::ShortAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeAccum == clang::BuiltinType::Accum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongAccum == clang::BuiltinType::LongAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUShortAccum == clang::BuiltinType::UShortAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUAccum == clang::BuiltinType::UAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULongAccum == clang::BuiltinType::ULongAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeShortFract == clang::BuiltinType::ShortFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFract == clang::BuiltinType::Fract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongFract == clang::BuiltinType::LongFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUShortFract == clang::BuiltinType::UShortFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUFract == clang::BuiltinType::UFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULongFract == clang::BuiltinType::ULongFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatShortAccum == clang::BuiltinType::SatShortAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatAccum == clang::BuiltinType::SatAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatLongAccum == clang::BuiltinType::SatLongAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUShortAccum == clang::BuiltinType::SatUShortAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUAccum == clang::BuiltinType::SatUAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatULongAccum == clang::BuiltinType::SatULongAccum, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatShortFract == clang::BuiltinType::SatShortFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatFract == clang::BuiltinType::SatFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatLongFract == clang::BuiltinType::SatLongFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUShortFract == clang::BuiltinType::SatUShortFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUFract == clang::BuiltinType::SatUFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatULongFract == clang::BuiltinType::SatULongFract, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeHalf == clang::BuiltinType::Half, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFloat == clang::BuiltinType::Float, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeDouble == clang::BuiltinType::Double, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongDouble == clang::BuiltinType::LongDouble, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFloat16 == clang::BuiltinType::Float16, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFloat128 == clang::BuiltinType::Float128, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeNullPtr == clang::BuiltinType::NullPtr, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeObjCId == clang::BuiltinType::ObjCId, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeObjCClass == clang::BuiltinType::ObjCClass, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeObjCSel == clang::BuiltinType::ObjCSel, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLSampler == clang::BuiltinType::OCLSampler, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLEvent == clang::BuiltinType::OCLEvent, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLClkEvent == clang::BuiltinType::OCLClkEvent, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLQueue == clang::BuiltinType::OCLQueue, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLReserveID == clang::BuiltinType::OCLReserveID, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeDependent == clang::BuiltinType::Dependent, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOverload == clang::BuiltinType::Overload, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeBoundMember == clang::BuiltinType::BoundMember, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypePseudoObject == clang::BuiltinType::PseudoObject, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUnknownAny == clang::BuiltinType::UnknownAny, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeBuiltinFn == clang::BuiltinType::BuiltinFn, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeARCUnbridgedCast == clang::BuiltinType::ARCUnbridgedCast, "");
+static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOMPArraySection == clang::BuiltinType::OMPArraySection, "");
+
+void ZigClang_detect_enum_CallingConv(clang::CallingConv x) {
+ switch (x) {
+ case clang::CC_C:
+ case clang::CC_X86StdCall:
+ case clang::CC_X86FastCall:
+ case clang::CC_X86ThisCall:
+ case clang::CC_X86VectorCall:
+ case clang::CC_X86Pascal:
+ case clang::CC_Win64:
+ case clang::CC_X86_64SysV:
+ case clang::CC_X86RegCall:
+ case clang::CC_AAPCS:
+ case clang::CC_AAPCS_VFP:
+ case clang::CC_IntelOclBicc:
+ case clang::CC_SpirFunction:
+ case clang::CC_OpenCLKernel:
+ case clang::CC_Swift:
+ case clang::CC_PreserveMost:
+ case clang::CC_PreserveAll:
+ case clang::CC_AArch64VectorCall:
+ break;
+ }
+}
+
+static_assert((clang::CallingConv)ZigClangCallingConv_C == clang::CC_C, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_X86StdCall == clang::CC_X86StdCall, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_X86FastCall == clang::CC_X86FastCall, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_X86ThisCall == clang::CC_X86ThisCall, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_X86VectorCall == clang::CC_X86VectorCall, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_X86Pascal == clang::CC_X86Pascal, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_Win64 == clang::CC_Win64, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_X86_64SysV == clang::CC_X86_64SysV, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_X86RegCall == clang::CC_X86RegCall, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_AAPCS == clang::CC_AAPCS, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_AAPCS_VFP == clang::CC_AAPCS_VFP, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_IntelOclBicc == clang::CC_IntelOclBicc, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_SpirFunction == clang::CC_SpirFunction, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_OpenCLKernel == clang::CC_OpenCLKernel, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_Swift == clang::CC_Swift, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_PreserveMost == clang::CC_PreserveMost, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_PreserveAll == clang::CC_PreserveAll, "");
+static_assert((clang::CallingConv)ZigClangCallingConv_AArch64VectorCall == clang::CC_AArch64VectorCall, "");
+
+void ZigClang_detect_enum_StorageClass(clang::StorageClass x) {
+ switch (x) {
+ case clang::SC_None:
+ case clang::SC_Extern:
+ case clang::SC_Static:
+ case clang::SC_PrivateExtern:
+ case clang::SC_Auto:
+ case clang::SC_Register:
+ break;
+ }
+}
+
+static_assert((clang::StorageClass)ZigClangStorageClass_None == clang::SC_None, "");
+static_assert((clang::StorageClass)ZigClangStorageClass_Extern == clang::SC_Extern, "");
+static_assert((clang::StorageClass)ZigClangStorageClass_Static == clang::SC_Static, "");
+static_assert((clang::StorageClass)ZigClangStorageClass_PrivateExtern == clang::SC_PrivateExtern, "");
+static_assert((clang::StorageClass)ZigClangStorageClass_Auto == clang::SC_Auto, "");
+static_assert((clang::StorageClass)ZigClangStorageClass_Register == clang::SC_Register, "");
+
+
static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
ZigClangSourceLocation dest;
@@ -161,6 +1280,26 @@ static clang::QualType bitcast(ZigClangQualType src) {
return dest;
}
+static_assert(sizeof(ZigClangAPValueLValueBase) == sizeof(clang::APValue::LValueBase), "");
+static ZigClangAPValueLValueBase bitcast(clang::APValue::LValueBase src) {
+ ZigClangAPValueLValueBase dest;
+ memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangAPValueLValueBase));
+ return dest;
+}
+static clang::APValue::LValueBase bitcast(ZigClangAPValueLValueBase src) {
+ clang::APValue::LValueBase dest;
+ memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangAPValueLValueBase));
+ return dest;
+}
+
+static_assert(sizeof(ZigClangCompoundStmt_const_body_iterator) == sizeof(clang::CompoundStmt::const_body_iterator), "");
+static ZigClangCompoundStmt_const_body_iterator bitcast(clang::CompoundStmt::const_body_iterator src) {
+ ZigClangCompoundStmt_const_body_iterator dest;
+ memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangCompoundStmt_const_body_iterator));
+ return dest;
+}
+
+
ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
ZigClangSourceLocation Loc)
{
@@ -196,6 +1335,10 @@ ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* sel
return bitcast(reinterpret_cast<const clang::ASTContext *>(self)->getPointerType(bitcast(T)));
}
+unsigned ZigClangASTContext_getTypeAlign(const ZigClangASTContext* self, ZigClangQualType T) {
+ return reinterpret_cast<const clang::ASTContext *>(self)->getTypeAlign(bitcast(T));
+}
+
ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) {
clang::ASTContext *result = &reinterpret_cast<clang::ASTUnit *>(self)->getASTContext();
return reinterpret_cast<ZigClangASTContext *>(result);
@@ -212,3 +1355,477 @@ bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *contex
return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context,
reinterpret_cast<bool (*)(void *, const clang::Decl *)>(Fn));
}
+
+const ZigClangRecordDecl *ZigClangRecordType_getDecl(const ZigClangRecordType *record_ty) {
+ const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordType *>(record_ty)->getDecl();
+ return reinterpret_cast<const ZigClangRecordDecl *>(record_decl);
+}
+
+const ZigClangEnumDecl *ZigClangEnumType_getDecl(const ZigClangEnumType *enum_ty) {
+ const clang::EnumDecl *enum_decl = reinterpret_cast<const clang::EnumType *>(enum_ty)->getDecl();
+ return reinterpret_cast<const ZigClangEnumDecl *>(enum_decl);
+}
+
+const ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const ZigClangRecordDecl *record_decl) {
+ const clang::TagDecl *tag_decl = reinterpret_cast<const clang::RecordDecl*>(record_decl)->getCanonicalDecl();
+ return reinterpret_cast<const ZigClangTagDecl *>(tag_decl);
+}
+
+const ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const ZigClangEnumDecl *enum_decl) {
+ const clang::TagDecl *tag_decl = reinterpret_cast<const clang::EnumDecl*>(enum_decl)->getCanonicalDecl();
+ return reinterpret_cast<const ZigClangTagDecl *>(tag_decl);
+}
+
+const ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCanonicalDecl(const ZigClangTypedefNameDecl *self) {
+ const clang::TypedefNameDecl *decl = reinterpret_cast<const clang::TypedefNameDecl*>(self)->getCanonicalDecl();
+ return reinterpret_cast<const ZigClangTypedefNameDecl *>(decl);
+}
+
+const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) {
+ const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl);
+ const clang::RecordDecl *definition = record_decl->getDefinition();
+ return reinterpret_cast<const ZigClangRecordDecl *>(definition);
+}
+
+const ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const ZigClangEnumDecl *zig_enum_decl) {
+ const clang::EnumDecl *enum_decl = reinterpret_cast<const clang::EnumDecl *>(zig_enum_decl);
+ const clang::EnumDecl *definition = enum_decl->getDefinition();
+ return reinterpret_cast<const ZigClangEnumDecl *>(definition);
+}
+
+bool ZigClangRecordDecl_isUnion(const ZigClangRecordDecl *record_decl) {
+ return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isUnion();
+}
+
+bool ZigClangRecordDecl_isStruct(const ZigClangRecordDecl *record_decl) {
+ return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isStruct();
+}
+
+bool ZigClangRecordDecl_isAnonymousStructOrUnion(const ZigClangRecordDecl *record_decl) {
+ return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isAnonymousStructOrUnion();
+}
+
+const char *ZigClangDecl_getName_bytes_begin(const ZigClangDecl *zig_decl) {
+ const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zig_decl);
+ const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl);
+ return (const char *)named_decl->getName().bytes_begin();
+}
+
+ZigClangDeclKind ZigClangDecl_getKind(const struct ZigClangDecl *self) {
+ auto casted = reinterpret_cast<const clang::Decl *>(self);
+ return (ZigClangDeclKind)casted->getKind();
+}
+
+const char *ZigClangDecl_getDeclKindName(const struct ZigClangDecl *self) {
+ auto casted = reinterpret_cast<const clang::Decl *>(self);
+ return casted->getDeclKindName();
+}
+
+ZigClangSourceLocation ZigClangRecordDecl_getLocation(const ZigClangRecordDecl *zig_record_decl) {
+ const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl);
+ return bitcast(record_decl->getLocation());
+}
+
+ZigClangSourceLocation ZigClangEnumDecl_getLocation(const ZigClangEnumDecl *self) {
+ auto casted = reinterpret_cast<const clang::EnumDecl *>(self);
+ return bitcast(casted->getLocation());
+}
+
+ZigClangSourceLocation ZigClangTypedefNameDecl_getLocation(const ZigClangTypedefNameDecl *self) {
+ auto casted = reinterpret_cast<const clang::TypedefNameDecl *>(self);
+ return bitcast(casted->getLocation());
+}
+
+ZigClangSourceLocation ZigClangDecl_getLocation(const ZigClangDecl *self) {
+ auto casted = reinterpret_cast<const clang::Decl *>(self);
+ return bitcast(casted->getLocation());
+}
+
+bool ZigClangSourceLocation_eq(ZigClangSourceLocation zig_a, ZigClangSourceLocation zig_b) {
+ clang::SourceLocation a = bitcast(zig_a);
+ clang::SourceLocation b = bitcast(zig_b);
+ return a == b;
+}
+
+ZigClangQualType ZigClangEnumDecl_getIntegerType(const ZigClangEnumDecl *self) {
+ return bitcast(reinterpret_cast<const clang::EnumDecl *>(self)->getIntegerType());
+}
+
+struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *self) {
+ auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
+ return bitcast(casted->getType());
+}
+
+struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *self) {
+ auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
+ return bitcast(casted->getLocation());
+}
+
+bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *self) {
+ auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
+ return casted->hasBody();
+}
+
+enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *self) {
+ auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
+ return (ZigClangStorageClass)casted->getStorageClass();
+}
+
+const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *self,
+ unsigned i)
+{
+ auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
+ const clang::ParmVarDecl *parm_var_decl = casted->getParamDecl(i);
+ return reinterpret_cast<const ZigClangParmVarDecl *>(parm_var_decl);
+}
+
+const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *self) {
+ auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
+ const clang::Stmt *stmt = casted->getBody();
+ return reinterpret_cast<const ZigClangStmt *>(stmt);
+}
+
+const ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const ZigClangTypedefType *self) {
+ auto casted = reinterpret_cast<const clang::TypedefType *>(self);
+ const clang::TypedefNameDecl *name_decl = casted->getDecl();
+ return reinterpret_cast<const ZigClangTypedefNameDecl *>(name_decl);
+}
+
+ZigClangQualType ZigClangTypedefNameDecl_getUnderlyingType(const ZigClangTypedefNameDecl *self) {
+ auto casted = reinterpret_cast<const clang::TypedefNameDecl *>(self);
+ clang::QualType ty = casted->getUnderlyingType();
+ return bitcast(ty);
+}
+
+ZigClangQualType ZigClangQualType_getCanonicalType(ZigClangQualType self) {
+ clang::QualType qt = bitcast(self);
+ return bitcast(qt.getCanonicalType());
+}
+
+const ZigClangType *ZigClangQualType_getTypePtr(ZigClangQualType self) {
+ clang::QualType qt = bitcast(self);
+ const clang::Type *ty = qt.getTypePtr();
+ return reinterpret_cast<const ZigClangType *>(ty);
+}
+
+void ZigClangQualType_addConst(ZigClangQualType *self) {
+ reinterpret_cast<clang::QualType *>(self)->addConst();
+}
+
+bool ZigClangQualType_eq(ZigClangQualType zig_t1, ZigClangQualType zig_t2) {
+ clang::QualType t1 = bitcast(zig_t1);
+ clang::QualType t2 = bitcast(zig_t2);
+ if (t1.isConstQualified() != t2.isConstQualified()) {
+ return false;
+ }
+ if (t1.isVolatileQualified() != t2.isVolatileQualified()) {
+ return false;
+ }
+ if (t1.isRestrictQualified() != t2.isRestrictQualified()) {
+ return false;
+ }
+ return t1.getTypePtr() == t2.getTypePtr();
+}
+
+bool ZigClangQualType_isConstQualified(ZigClangQualType self) {
+ clang::QualType qt = bitcast(self);
+ return qt.isConstQualified();
+}
+
+bool ZigClangQualType_isVolatileQualified(ZigClangQualType self) {
+ clang::QualType qt = bitcast(self);
+ return qt.isVolatileQualified();
+}
+
+bool ZigClangQualType_isRestrictQualified(ZigClangQualType self) {
+ clang::QualType qt = bitcast(self);
+ return qt.isRestrictQualified();
+}
+
+ZigClangTypeClass ZigClangType_getTypeClass(const ZigClangType *self) {
+ auto casted = reinterpret_cast<const clang::Type *>(self);
+ clang::Type::TypeClass tc = casted->getTypeClass();
+ return (ZigClangTypeClass)tc;
+}
+
+ZigClangQualType ZigClangType_getPointeeType(const ZigClangType *self) {
+ auto casted = reinterpret_cast<const clang::Type *>(self);
+ return bitcast(casted->getPointeeType());
+}
+
+bool ZigClangType_isVoidType(const ZigClangType *self) {
+ auto casted = reinterpret_cast<const clang::Type *>(self);
+ return casted->isVoidType();
+}
+
+const char *ZigClangType_getTypeClassName(const ZigClangType *self) {
+ auto casted = reinterpret_cast<const clang::Type *>(self);
+ return casted->getTypeClassName();
+}
+
+ZigClangSourceLocation ZigClangStmt_getBeginLoc(const ZigClangStmt *self) {
+ auto casted = reinterpret_cast<const clang::Stmt *>(self);
+ return bitcast(casted->getBeginLoc());
+}
+
+bool ZigClangStmt_classof_Expr(const ZigClangStmt *self) {
+ auto casted = reinterpret_cast<const clang::Stmt *>(self);
+ return clang::Expr::classof(casted);
+}
+
+ZigClangStmtClass ZigClangStmt_getStmtClass(const ZigClangStmt *self) {
+ auto casted = reinterpret_cast<const clang::Stmt *>(self);
+ return (ZigClangStmtClass)casted->getStmtClass();
+}
+
+ZigClangStmtClass ZigClangExpr_getStmtClass(const ZigClangExpr *self) {
+ auto casted = reinterpret_cast<const clang::Expr *>(self);
+ return (ZigClangStmtClass)casted->getStmtClass();
+}
+
+ZigClangQualType ZigClangExpr_getType(const ZigClangExpr *self) {
+ auto casted = reinterpret_cast<const clang::Expr *>(self);
+ return bitcast(casted->getType());
+}
+
+ZigClangSourceLocation ZigClangExpr_getBeginLoc(const ZigClangExpr *self) {
+ auto casted = reinterpret_cast<const clang::Expr *>(self);
+ return bitcast(casted->getBeginLoc());
+}
+
+ZigClangAPValueKind ZigClangAPValue_getKind(const ZigClangAPValue *self) {
+ auto casted = reinterpret_cast<const clang::APValue *>(self);
+ return (ZigClangAPValueKind)casted->getKind();
+}
+
+const ZigClangAPSInt *ZigClangAPValue_getInt(const ZigClangAPValue *self) {
+ auto casted = reinterpret_cast<const clang::APValue *>(self);
+ const llvm::APSInt *result = &casted->getInt();
+ return reinterpret_cast<const ZigClangAPSInt *>(result);
+}
+
+unsigned ZigClangAPValue_getArrayInitializedElts(const ZigClangAPValue *self) {
+ auto casted = reinterpret_cast<const clang::APValue *>(self);
+ return casted->getArrayInitializedElts();
+}
+
+const ZigClangAPValue *ZigClangAPValue_getArrayInitializedElt(const ZigClangAPValue *self, unsigned i) {
+ auto casted = reinterpret_cast<const clang::APValue *>(self);
+ const clang::APValue *result = &casted->getArrayInitializedElt(i);
+ return reinterpret_cast<const ZigClangAPValue *>(result);
+}
+
+const ZigClangAPValue *ZigClangAPValue_getArrayFiller(const ZigClangAPValue *self) {
+ auto casted = reinterpret_cast<const clang::APValue *>(self);
+ const clang::APValue *result = &casted->getArrayFiller();
+ return reinterpret_cast<const ZigClangAPValue *>(result);
+}
+
+unsigned ZigClangAPValue_getArraySize(const ZigClangAPValue *self) {
+ auto casted = reinterpret_cast<const clang::APValue *>(self);
+ return casted->getArraySize();
+}
+
+const ZigClangAPSInt *ZigClangAPSInt_negate(const ZigClangAPSInt *self) {
+ auto casted = reinterpret_cast<const llvm::APSInt *>(self);
+ llvm::APSInt *result = new llvm::APSInt();
+ *result = *casted;
+ *result = -*result;
+ return reinterpret_cast<const ZigClangAPSInt *>(result);
+}
+
+void ZigClangAPSInt_free(const ZigClangAPSInt *self) {
+ auto casted = reinterpret_cast<const llvm::APSInt *>(self);
+ delete casted;
+}
+
+bool ZigClangAPSInt_isSigned(const ZigClangAPSInt *self) {
+ auto casted = reinterpret_cast<const llvm::APSInt *>(self);
+ return casted->isSigned();
+}
+
+bool ZigClangAPSInt_isNegative(const ZigClangAPSInt *self) {
+ auto casted = reinterpret_cast<const llvm::APSInt *>(self);
+ return casted->isNegative();
+}
+
+const uint64_t *ZigClangAPSInt_getRawData(const ZigClangAPSInt *self) {
+ auto casted = reinterpret_cast<const llvm::APSInt *>(self);
+ return casted->getRawData();
+}
+
+unsigned ZigClangAPSInt_getNumWords(const ZigClangAPSInt *self) {
+ auto casted = reinterpret_cast<const llvm::APSInt *>(self);
+ return casted->getNumWords();
+}
+
+const ZigClangExpr *ZigClangAPValueLValueBase_dyn_cast_Expr(ZigClangAPValueLValueBase self) {
+ clang::APValue::LValueBase casted = bitcast(self);
+ const clang::Expr *expr = casted.dyn_cast<const clang::Expr *>();
+ return reinterpret_cast<const ZigClangExpr *>(expr);
+}
+
+ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const ZigClangAPValue *self) {
+ auto casted = reinterpret_cast<const clang::APValue *>(self);
+ clang::APValue::LValueBase lval_base = casted->getLValueBase();
+ return bitcast(lval_base);
+}
+
+ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end,
+ struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path)
+{
+ clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
+
+ std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();
+
+ bool only_local_decls = true;
+ bool capture_diagnostics = true;
+ bool user_files_are_volatile = true;
+ bool allow_pch_with_compiler_errors = false;
+ bool single_file_parse = false;
+ bool for_serialization = false;
+ std::unique_ptr<clang::ASTUnit> *err_unit = new std::unique_ptr<clang::ASTUnit>();
+ clang::ASTUnit *ast_unit = clang::ASTUnit::LoadFromCommandLine(
+ args_begin, args_end,
+ pch_container_ops, diags, resources_path,
+ only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
+ false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
+ single_file_parse, user_files_are_volatile, for_serialization, clang::None, err_unit,
+ nullptr);
+
+ // Early failures in LoadFromCommandLine may return with ErrUnit unset.
+ if (!ast_unit && !err_unit) {
+ return nullptr;
+ }
+
+ if (diags->getClient()->getNumErrors() > 0) {
+ if (ast_unit) {
+ *err_unit = std::unique_ptr<clang::ASTUnit>(ast_unit);
+ }
+
+ size_t cap = 4;
+ *errors_len = 0;
+ *errors_ptr = reinterpret_cast<Stage2ErrorMsg*>(malloc(cap * sizeof(Stage2ErrorMsg)));
+ if (*errors_ptr == nullptr) {
+ return nullptr;
+ }
+
+ for (clang::ASTUnit::stored_diag_iterator it = (*err_unit)->stored_diag_begin(),
+ it_end = (*err_unit)->stored_diag_end();
+ it != it_end; ++it)
+ {
+ switch (it->getLevel()) {
+ case clang::DiagnosticsEngine::Ignored:
+ case clang::DiagnosticsEngine::Note:
+ case clang::DiagnosticsEngine::Remark:
+ case clang::DiagnosticsEngine::Warning:
+ continue;
+ case clang::DiagnosticsEngine::Error:
+ case clang::DiagnosticsEngine::Fatal:
+ break;
+ }
+ llvm::StringRef msg_str_ref = it->getMessage();
+ if (*errors_len >= cap) {
+ cap *= 2;
+ Stage2ErrorMsg *new_errors = reinterpret_cast<Stage2ErrorMsg *>(
+ realloc(*errors_ptr, cap * sizeof(Stage2ErrorMsg)));
+ if (new_errors == nullptr) {
+ free(*errors_ptr);
+ *errors_ptr = nullptr;
+ *errors_len = 0;
+ return nullptr;
+ }
+ *errors_ptr = new_errors;
+ }
+ Stage2ErrorMsg *msg = *errors_ptr + *errors_len;
+ *errors_len += 1;
+ msg->msg_ptr = (const char *)msg_str_ref.bytes_begin();
+ msg->msg_len = msg_str_ref.size();
+
+ clang::FullSourceLoc fsl = it->getLocation();
+ if (fsl.hasManager()) {
+ clang::FileID file_id = fsl.getFileID();
+ clang::StringRef filename = fsl.getManager().getFilename(fsl);
+ if (filename.empty()) {
+ msg->filename_ptr = nullptr;
+ } else {
+ msg->filename_ptr = (const char *)filename.bytes_begin();
+ msg->filename_len = filename.size();
+ }
+ msg->source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
+ msg->line = fsl.getSpellingLineNumber() - 1;
+ msg->column = fsl.getSpellingColumnNumber() - 1;
+ msg->offset = fsl.getManager().getFileOffset(fsl);
+ } else {
+ // The only known way this gets triggered right now is if you have a lot of errors
+ // clang emits "too many errors emitted, stopping now"
+ msg->filename_ptr = nullptr;
+ msg->source = nullptr;
+ }
+ }
+
+ if (*errors_len == 0) {
+ free(*errors_ptr);
+ *errors_ptr = nullptr;
+ }
+
+ return nullptr;
+ }
+
+ return reinterpret_cast<ZigClangASTUnit *>(ast_unit);
+}
+
+void ZigClangErrorMsg_delete(Stage2ErrorMsg *ptr, size_t len) {
+ free(ptr);
+}
+
+void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) {
+ delete reinterpret_cast<clang::ASTUnit *>(self);
+}
+
+enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self) {
+ auto casted = reinterpret_cast<const clang::BuiltinType *>(self);
+ return (ZigClangBuiltinTypeKind)casted->getKind();
+}
+
+bool ZigClangFunctionType_getNoReturnAttr(const struct ZigClangFunctionType *self) {
+ auto casted = reinterpret_cast<const clang::FunctionType *>(self);
+ return casted->getNoReturnAttr();
+}
+
+enum ZigClangCallingConv ZigClangFunctionType_getCallConv(const struct ZigClangFunctionType *self) {
+ auto casted = reinterpret_cast<const clang::FunctionType *>(self);
+ return (ZigClangCallingConv)casted->getCallConv();
+}
+
+struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClangFunctionType *self) {
+ auto casted = reinterpret_cast<const clang::FunctionType *>(self);
+ return bitcast(casted->getReturnType());
+}
+
+bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self) {
+ auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);
+ return casted->isVariadic();
+}
+
+unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self) {
+ auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);
+ return casted->getNumParams();
+}
+
+struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self,
+ unsigned index)
+{
+ auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);
+ return bitcast(casted->getParamType(index));
+}
+
+ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self) {
+ auto casted = reinterpret_cast<const clang::CompoundStmt *>(self);
+ return bitcast(casted->body_begin());
+}
+
+ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self) {
+ auto casted = reinterpret_cast<const clang::CompoundStmt *>(self);
+ return bitcast(casted->body_end());
+}
diff --git a/src/zig_clang.h b/src/zig_clang.h
index c7d749cbd9..fd74536b28 100644
--- a/src/zig_clang.h
+++ b/src/zig_clang.h
@@ -8,14 +8,13 @@
#ifndef ZIG_ZIG_CLANG_H
#define ZIG_ZIG_CLANG_H
-#ifdef __cplusplus
-#define ZIG_EXTERN_C extern "C"
-#else
-#define ZIG_EXTERN_C
-#endif
+#include "userland.h"
+#include <inttypes.h>
+#include <stdbool.h>
// ATTENTION: If you modify this file, be sure to update the corresponding
-// extern function declarations in the self-hosted compiler.
+// extern function declarations in the self-hosted compiler file
+// src-self-hosted/clang.zig.
struct ZigClangSourceLocation {
unsigned ID;
@@ -25,7 +24,14 @@ struct ZigClangQualType {
void *ptr;
};
+struct ZigClangAPValueLValueBase {
+ void *Ptr;
+ unsigned CallIndex;
+ unsigned Version;
+};
+
struct ZigClangAPValue;
+struct ZigClangAPSInt;
struct ZigClangASTContext;
struct ZigClangASTUnit;
struct ZigClangArraySubscriptExpr;
@@ -82,10 +88,10 @@ struct ZigClangSkipFunctionBodiesScope;
struct ZigClangSourceManager;
struct ZigClangSourceRange;
struct ZigClangStmt;
-struct ZigClangStorageClass;
struct ZigClangStringLiteral;
struct ZigClangStringRef;
struct ZigClangSwitchStmt;
+struct ZigClangTagDecl;
struct ZigClangType;
struct ZigClangTypedefNameDecl;
struct ZigClangTypedefType;
@@ -94,6 +100,9 @@ struct ZigClangUnaryOperator;
struct ZigClangValueDecl;
struct ZigClangVarDecl;
struct ZigClangWhileStmt;
+struct ZigClangFunctionType;
+
+typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator;
enum ZigClangBO {
ZigClangBO_PtrMemD,
@@ -148,112 +157,674 @@ enum ZigClangUO {
ZigClangUO_Coawait,
};
-//struct ZigClangCC_AAPCS;
-//struct ZigClangCC_AAPCS_VFP;
-//struct ZigClangCC_C;
-//struct ZigClangCC_IntelOclBicc;
-//struct ZigClangCC_OpenCLKernel;
-//struct ZigClangCC_PreserveAll;
-//struct ZigClangCC_PreserveMost;
-//struct ZigClangCC_SpirFunction;
-//struct ZigClangCC_Swift;
-//struct ZigClangCC_Win64;
-//struct ZigClangCC_X86FastCall;
-//struct ZigClangCC_X86Pascal;
-//struct ZigClangCC_X86RegCall;
-//struct ZigClangCC_X86StdCall;
-//struct ZigClangCC_X86ThisCall;
-//struct ZigClangCC_X86VectorCall;
-//struct ZigClangCC_X86_64SysV;
-
-//struct ZigClangCK_ARCConsumeObject;
-//struct ZigClangCK_ARCExtendBlockObject;
-//struct ZigClangCK_ARCProduceObject;
-//struct ZigClangCK_ARCReclaimReturnedObject;
-//struct ZigClangCK_AddressSpaceConversion;
-//struct ZigClangCK_AnyPointerToBlockPointerCast;
-//struct ZigClangCK_ArrayToPointerDecay;
-//struct ZigClangCK_AtomicToNonAtomic;
-//struct ZigClangCK_BaseToDerived;
-//struct ZigClangCK_BaseToDerivedMemberPointer;
-//struct ZigClangCK_BitCast;
-//struct ZigClangCK_BlockPointerToObjCPointerCast;
-//struct ZigClangCK_BooleanToSignedIntegral;
-//struct ZigClangCK_BuiltinFnToFnPtr;
-//struct ZigClangCK_CPointerToObjCPointerCast;
-//struct ZigClangCK_ConstructorConversion;
-//struct ZigClangCK_CopyAndAutoreleaseBlockObject;
-//struct ZigClangCK_Dependent;
-//struct ZigClangCK_DerivedToBase;
-//struct ZigClangCK_DerivedToBaseMemberPointer;
-//struct ZigClangCK_Dynamic;
-//struct ZigClangCK_FloatingCast;
-//struct ZigClangCK_FloatingComplexCast;
-//struct ZigClangCK_FloatingComplexToBoolean;
-//struct ZigClangCK_FloatingComplexToIntegralComplex;
-//struct ZigClangCK_FloatingComplexToReal;
-//struct ZigClangCK_FloatingRealToComplex;
-//struct ZigClangCK_FloatingToBoolean;
-//struct ZigClangCK_FloatingToIntegral;
-//struct ZigClangCK_FunctionToPointerDecay;
-//struct ZigClangCK_IntToOCLSampler;
-//struct ZigClangCK_IntegralCast;
-//struct ZigClangCK_IntegralComplexCast;
-//struct ZigClangCK_IntegralComplexToBoolean;
-//struct ZigClangCK_IntegralComplexToFloatingComplex;
-//struct ZigClangCK_IntegralComplexToReal;
-//struct ZigClangCK_IntegralRealToComplex;
-//struct ZigClangCK_IntegralToBoolean;
-//struct ZigClangCK_IntegralToFloating;
-//struct ZigClangCK_IntegralToPointer;
-//struct ZigClangCK_LValueBitCast;
-//struct ZigClangCK_LValueToRValue;
-//struct ZigClangCK_MemberPointerToBoolean;
-//struct ZigClangCK_NoOp;
-//struct ZigClangCK_NonAtomicToAtomic;
-//struct ZigClangCK_NullToMemberPointer;
-//struct ZigClangCK_NullToPointer;
-//struct ZigClangCK_ObjCObjectLValueCast;
-//struct ZigClangCK_PointerToBoolean;
-//struct ZigClangCK_PointerToIntegral;
-//struct ZigClangCK_ReinterpretMemberPointer;
-//struct ZigClangCK_ToUnion;
-//struct ZigClangCK_ToVoid;
-//struct ZigClangCK_UncheckedDerivedToBase;
-//struct ZigClangCK_UserDefinedConversion;
-//struct ZigClangCK_VectorSplat;
-//struct ZigClangCK_ZeroToOCLEvent;
-//struct ZigClangCK_ZeroToOCLQueue;
-
-//struct ZigClangETK_Class;
-//struct ZigClangETK_Enum;
-//struct ZigClangETK_Interface;
-//struct ZigClangETK_None;
-//struct ZigClangETK_Struct;
-//struct ZigClangETK_Typename;
-//struct ZigClangETK_Union;
-
-//struct ZigClangSC_None;
-//struct ZigClangSC_PrivateExtern;
-//struct ZigClangSC_Static;
-
-//struct ZigClangTU_Complete;
-
-ZIG_EXTERN_C ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *,
- ZigClangSourceLocation Loc);
-ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *,
- ZigClangSourceLocation SpellingLoc);
-ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *,
- ZigClangSourceLocation Loc);
-ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *,
- ZigClangSourceLocation Loc);
-ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *,
- ZigClangSourceLocation SL);
-
-ZIG_EXTERN_C ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext*, ZigClangQualType T);
-
-ZIG_EXTERN_C ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *);
-ZIG_EXTERN_C ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *);
-ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *, void *context,
- bool (*Fn)(void *context, const ZigClangDecl *decl));
+enum ZigClangTypeClass {
+ ZigClangType_Builtin,
+ ZigClangType_Complex,
+ ZigClangType_Pointer,
+ ZigClangType_BlockPointer,
+ ZigClangType_LValueReference,
+ ZigClangType_RValueReference,
+ ZigClangType_MemberPointer,
+ ZigClangType_ConstantArray,
+ ZigClangType_IncompleteArray,
+ ZigClangType_VariableArray,
+ ZigClangType_DependentSizedArray,
+ ZigClangType_DependentSizedExtVector,
+ ZigClangType_DependentAddressSpace,
+ ZigClangType_Vector,
+ ZigClangType_DependentVector,
+ ZigClangType_ExtVector,
+ ZigClangType_FunctionProto,
+ ZigClangType_FunctionNoProto,
+ ZigClangType_UnresolvedUsing,
+ ZigClangType_Paren,
+ ZigClangType_Typedef,
+ ZigClangType_Adjusted,
+ ZigClangType_Decayed,
+ ZigClangType_TypeOfExpr,
+ ZigClangType_TypeOf,
+ ZigClangType_Decltype,
+ ZigClangType_UnaryTransform,
+ ZigClangType_Record,
+ ZigClangType_Enum,
+ ZigClangType_Elaborated,
+ ZigClangType_Attributed,
+ ZigClangType_TemplateTypeParm,
+ ZigClangType_SubstTemplateTypeParm,
+ ZigClangType_SubstTemplateTypeParmPack,
+ ZigClangType_TemplateSpecialization,
+ ZigClangType_Auto,
+ ZigClangType_DeducedTemplateSpecialization,
+ ZigClangType_InjectedClassName,
+ ZigClangType_DependentName,
+ ZigClangType_DependentTemplateSpecialization,
+ ZigClangType_PackExpansion,
+ ZigClangType_ObjCTypeParam,
+ ZigClangType_ObjCObject,
+ ZigClangType_ObjCInterface,
+ ZigClangType_ObjCObjectPointer,
+ ZigClangType_Pipe,
+ ZigClangType_Atomic,
+};
+
+enum ZigClangStmtClass {
+ ZigClangStmt_NoStmtClass = 0,
+ ZigClangStmt_GCCAsmStmtClass,
+ ZigClangStmt_MSAsmStmtClass,
+ ZigClangStmt_AttributedStmtClass,
+ ZigClangStmt_BreakStmtClass,
+ ZigClangStmt_CXXCatchStmtClass,
+ ZigClangStmt_CXXForRangeStmtClass,
+ ZigClangStmt_CXXTryStmtClass,
+ ZigClangStmt_CapturedStmtClass,
+ ZigClangStmt_CompoundStmtClass,
+ ZigClangStmt_ContinueStmtClass,
+ ZigClangStmt_CoreturnStmtClass,
+ ZigClangStmt_CoroutineBodyStmtClass,
+ ZigClangStmt_DeclStmtClass,
+ ZigClangStmt_DoStmtClass,
+ ZigClangStmt_BinaryConditionalOperatorClass,
+ ZigClangStmt_ConditionalOperatorClass,
+ ZigClangStmt_AddrLabelExprClass,
+ ZigClangStmt_ArrayInitIndexExprClass,
+ ZigClangStmt_ArrayInitLoopExprClass,
+ ZigClangStmt_ArraySubscriptExprClass,
+ ZigClangStmt_ArrayTypeTraitExprClass,
+ ZigClangStmt_AsTypeExprClass,
+ ZigClangStmt_AtomicExprClass,
+ ZigClangStmt_BinaryOperatorClass,
+ ZigClangStmt_CompoundAssignOperatorClass,
+ ZigClangStmt_BlockExprClass,
+ ZigClangStmt_CXXBindTemporaryExprClass,
+ ZigClangStmt_CXXBoolLiteralExprClass,
+ ZigClangStmt_CXXConstructExprClass,
+ ZigClangStmt_CXXTemporaryObjectExprClass,
+ ZigClangStmt_CXXDefaultArgExprClass,
+ ZigClangStmt_CXXDefaultInitExprClass,
+ ZigClangStmt_CXXDeleteExprClass,
+ ZigClangStmt_CXXDependentScopeMemberExprClass,
+ ZigClangStmt_CXXFoldExprClass,
+ ZigClangStmt_CXXInheritedCtorInitExprClass,
+ ZigClangStmt_CXXNewExprClass,
+ ZigClangStmt_CXXNoexceptExprClass,
+ ZigClangStmt_CXXNullPtrLiteralExprClass,
+ ZigClangStmt_CXXPseudoDestructorExprClass,
+ ZigClangStmt_CXXScalarValueInitExprClass,
+ ZigClangStmt_CXXStdInitializerListExprClass,
+ ZigClangStmt_CXXThisExprClass,
+ ZigClangStmt_CXXThrowExprClass,
+ ZigClangStmt_CXXTypeidExprClass,
+ ZigClangStmt_CXXUnresolvedConstructExprClass,
+ ZigClangStmt_CXXUuidofExprClass,
+ ZigClangStmt_CallExprClass,
+ ZigClangStmt_CUDAKernelCallExprClass,
+ ZigClangStmt_CXXMemberCallExprClass,
+ ZigClangStmt_CXXOperatorCallExprClass,
+ ZigClangStmt_UserDefinedLiteralClass,
+ ZigClangStmt_CStyleCastExprClass,
+ ZigClangStmt_CXXFunctionalCastExprClass,
+ ZigClangStmt_CXXConstCastExprClass,
+ ZigClangStmt_CXXDynamicCastExprClass,
+ ZigClangStmt_CXXReinterpretCastExprClass,
+ ZigClangStmt_CXXStaticCastExprClass,
+ ZigClangStmt_ObjCBridgedCastExprClass,
+ ZigClangStmt_ImplicitCastExprClass,
+ ZigClangStmt_CharacterLiteralClass,
+ ZigClangStmt_ChooseExprClass,
+ ZigClangStmt_CompoundLiteralExprClass,
+ ZigClangStmt_ConvertVectorExprClass,
+ ZigClangStmt_CoawaitExprClass,
+ ZigClangStmt_CoyieldExprClass,
+ ZigClangStmt_DeclRefExprClass,
+ ZigClangStmt_DependentCoawaitExprClass,
+ ZigClangStmt_DependentScopeDeclRefExprClass,
+ ZigClangStmt_DesignatedInitExprClass,
+ ZigClangStmt_DesignatedInitUpdateExprClass,
+ ZigClangStmt_ExpressionTraitExprClass,
+ ZigClangStmt_ExtVectorElementExprClass,
+ ZigClangStmt_FixedPointLiteralClass,
+ ZigClangStmt_FloatingLiteralClass,
+ ZigClangStmt_ConstantExprClass,
+ ZigClangStmt_ExprWithCleanupsClass,
+ ZigClangStmt_FunctionParmPackExprClass,
+ ZigClangStmt_GNUNullExprClass,
+ ZigClangStmt_GenericSelectionExprClass,
+ ZigClangStmt_ImaginaryLiteralClass,
+ ZigClangStmt_ImplicitValueInitExprClass,
+ ZigClangStmt_InitListExprClass,
+ ZigClangStmt_IntegerLiteralClass,
+ ZigClangStmt_LambdaExprClass,
+ ZigClangStmt_MSPropertyRefExprClass,
+ ZigClangStmt_MSPropertySubscriptExprClass,
+ ZigClangStmt_MaterializeTemporaryExprClass,
+ ZigClangStmt_MemberExprClass,
+ ZigClangStmt_NoInitExprClass,
+ ZigClangStmt_OMPArraySectionExprClass,
+ ZigClangStmt_ObjCArrayLiteralClass,
+ ZigClangStmt_ObjCAvailabilityCheckExprClass,
+ ZigClangStmt_ObjCBoolLiteralExprClass,
+ ZigClangStmt_ObjCBoxedExprClass,
+ ZigClangStmt_ObjCDictionaryLiteralClass,
+ ZigClangStmt_ObjCEncodeExprClass,
+ ZigClangStmt_ObjCIndirectCopyRestoreExprClass,
+ ZigClangStmt_ObjCIsaExprClass,
+ ZigClangStmt_ObjCIvarRefExprClass,
+ ZigClangStmt_ObjCMessageExprClass,
+ ZigClangStmt_ObjCPropertyRefExprClass,
+ ZigClangStmt_ObjCProtocolExprClass,
+ ZigClangStmt_ObjCSelectorExprClass,
+ ZigClangStmt_ObjCStringLiteralClass,
+ ZigClangStmt_ObjCSubscriptRefExprClass,
+ ZigClangStmt_OffsetOfExprClass,
+ ZigClangStmt_OpaqueValueExprClass,
+ ZigClangStmt_UnresolvedLookupExprClass,
+ ZigClangStmt_UnresolvedMemberExprClass,
+ ZigClangStmt_PackExpansionExprClass,
+ ZigClangStmt_ParenExprClass,
+ ZigClangStmt_ParenListExprClass,
+ ZigClangStmt_PredefinedExprClass,
+ ZigClangStmt_PseudoObjectExprClass,
+ ZigClangStmt_ShuffleVectorExprClass,
+ ZigClangStmt_SizeOfPackExprClass,
+ ZigClangStmt_StmtExprClass,
+ ZigClangStmt_StringLiteralClass,
+ ZigClangStmt_SubstNonTypeTemplateParmExprClass,
+ ZigClangStmt_SubstNonTypeTemplateParmPackExprClass,
+ ZigClangStmt_TypeTraitExprClass,
+ ZigClangStmt_TypoExprClass,
+ ZigClangStmt_UnaryExprOrTypeTraitExprClass,
+ ZigClangStmt_UnaryOperatorClass,
+ ZigClangStmt_VAArgExprClass,
+ ZigClangStmt_ForStmtClass,
+ ZigClangStmt_GotoStmtClass,
+ ZigClangStmt_IfStmtClass,
+ ZigClangStmt_IndirectGotoStmtClass,
+ ZigClangStmt_LabelStmtClass,
+ ZigClangStmt_MSDependentExistsStmtClass,
+ ZigClangStmt_NullStmtClass,
+ ZigClangStmt_OMPAtomicDirectiveClass,
+ ZigClangStmt_OMPBarrierDirectiveClass,
+ ZigClangStmt_OMPCancelDirectiveClass,
+ ZigClangStmt_OMPCancellationPointDirectiveClass,
+ ZigClangStmt_OMPCriticalDirectiveClass,
+ ZigClangStmt_OMPFlushDirectiveClass,
+ ZigClangStmt_OMPDistributeDirectiveClass,
+ ZigClangStmt_OMPDistributeParallelForDirectiveClass,
+ ZigClangStmt_OMPDistributeParallelForSimdDirectiveClass,
+ ZigClangStmt_OMPDistributeSimdDirectiveClass,
+ ZigClangStmt_OMPForDirectiveClass,
+ ZigClangStmt_OMPForSimdDirectiveClass,
+ ZigClangStmt_OMPParallelForDirectiveClass,
+ ZigClangStmt_OMPParallelForSimdDirectiveClass,
+ ZigClangStmt_OMPSimdDirectiveClass,
+ ZigClangStmt_OMPTargetParallelForSimdDirectiveClass,
+ ZigClangStmt_OMPTargetSimdDirectiveClass,
+ ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass,
+ ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass,
+ ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
+ ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass,
+ ZigClangStmt_OMPTaskLoopDirectiveClass,
+ ZigClangStmt_OMPTaskLoopSimdDirectiveClass,
+ ZigClangStmt_OMPTeamsDistributeDirectiveClass,
+ ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass,
+ ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass,
+ ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass,
+ ZigClangStmt_OMPMasterDirectiveClass,
+ ZigClangStmt_OMPOrderedDirectiveClass,
+ ZigClangStmt_OMPParallelDirectiveClass,
+ ZigClangStmt_OMPParallelSectionsDirectiveClass,
+ ZigClangStmt_OMPSectionDirectiveClass,
+ ZigClangStmt_OMPSectionsDirectiveClass,
+ ZigClangStmt_OMPSingleDirectiveClass,
+ ZigClangStmt_OMPTargetDataDirectiveClass,
+ ZigClangStmt_OMPTargetDirectiveClass,
+ ZigClangStmt_OMPTargetEnterDataDirectiveClass,
+ ZigClangStmt_OMPTargetExitDataDirectiveClass,
+ ZigClangStmt_OMPTargetParallelDirectiveClass,
+ ZigClangStmt_OMPTargetParallelForDirectiveClass,
+ ZigClangStmt_OMPTargetTeamsDirectiveClass,
+ ZigClangStmt_OMPTargetUpdateDirectiveClass,
+ ZigClangStmt_OMPTaskDirectiveClass,
+ ZigClangStmt_OMPTaskgroupDirectiveClass,
+ ZigClangStmt_OMPTaskwaitDirectiveClass,
+ ZigClangStmt_OMPTaskyieldDirectiveClass,
+ ZigClangStmt_OMPTeamsDirectiveClass,
+ ZigClangStmt_ObjCAtCatchStmtClass,
+ ZigClangStmt_ObjCAtFinallyStmtClass,
+ ZigClangStmt_ObjCAtSynchronizedStmtClass,
+ ZigClangStmt_ObjCAtThrowStmtClass,
+ ZigClangStmt_ObjCAtTryStmtClass,
+ ZigClangStmt_ObjCAutoreleasePoolStmtClass,
+ ZigClangStmt_ObjCForCollectionStmtClass,
+ ZigClangStmt_ReturnStmtClass,
+ ZigClangStmt_SEHExceptStmtClass,
+ ZigClangStmt_SEHFinallyStmtClass,
+ ZigClangStmt_SEHLeaveStmtClass,
+ ZigClangStmt_SEHTryStmtClass,
+ ZigClangStmt_CaseStmtClass,
+ ZigClangStmt_DefaultStmtClass,
+ ZigClangStmt_SwitchStmtClass,
+ ZigClangStmt_WhileStmtClass,
+};
+
+enum ZigClangCK {
+ ZigClangCK_Dependent,
+ ZigClangCK_BitCast,
+ ZigClangCK_LValueBitCast,
+ ZigClangCK_LValueToRValue,
+ ZigClangCK_NoOp,
+ ZigClangCK_BaseToDerived,
+ ZigClangCK_DerivedToBase,
+ ZigClangCK_UncheckedDerivedToBase,
+ ZigClangCK_Dynamic,
+ ZigClangCK_ToUnion,
+ ZigClangCK_ArrayToPointerDecay,
+ ZigClangCK_FunctionToPointerDecay,
+ ZigClangCK_NullToPointer,
+ ZigClangCK_NullToMemberPointer,
+ ZigClangCK_BaseToDerivedMemberPointer,
+ ZigClangCK_DerivedToBaseMemberPointer,
+ ZigClangCK_MemberPointerToBoolean,
+ ZigClangCK_ReinterpretMemberPointer,
+ ZigClangCK_UserDefinedConversion,
+ ZigClangCK_ConstructorConversion,
+ ZigClangCK_IntegralToPointer,
+ ZigClangCK_PointerToIntegral,
+ ZigClangCK_PointerToBoolean,
+ ZigClangCK_ToVoid,
+ ZigClangCK_VectorSplat,
+ ZigClangCK_IntegralCast,
+ ZigClangCK_IntegralToBoolean,
+ ZigClangCK_IntegralToFloating,
+ ZigClangCK_FixedPointCast,
+ ZigClangCK_FixedPointToBoolean,
+ ZigClangCK_FloatingToIntegral,
+ ZigClangCK_FloatingToBoolean,
+ ZigClangCK_BooleanToSignedIntegral,
+ ZigClangCK_FloatingCast,
+ ZigClangCK_CPointerToObjCPointerCast,
+ ZigClangCK_BlockPointerToObjCPointerCast,
+ ZigClangCK_AnyPointerToBlockPointerCast,
+ ZigClangCK_ObjCObjectLValueCast,
+ ZigClangCK_FloatingRealToComplex,
+ ZigClangCK_FloatingComplexToReal,
+ ZigClangCK_FloatingComplexToBoolean,
+ ZigClangCK_FloatingComplexCast,
+ ZigClangCK_FloatingComplexToIntegralComplex,
+ ZigClangCK_IntegralRealToComplex,
+ ZigClangCK_IntegralComplexToReal,
+ ZigClangCK_IntegralComplexToBoolean,
+ ZigClangCK_IntegralComplexCast,
+ ZigClangCK_IntegralComplexToFloatingComplex,
+ ZigClangCK_ARCProduceObject,
+ ZigClangCK_ARCConsumeObject,
+ ZigClangCK_ARCReclaimReturnedObject,
+ ZigClangCK_ARCExtendBlockObject,
+ ZigClangCK_AtomicToNonAtomic,
+ ZigClangCK_NonAtomicToAtomic,
+ ZigClangCK_CopyAndAutoreleaseBlockObject,
+ ZigClangCK_BuiltinFnToFnPtr,
+ ZigClangCK_ZeroToOCLOpaqueType,
+ ZigClangCK_AddressSpaceConversion,
+ ZigClangCK_IntToOCLSampler,
+};
+
+enum ZigClangAPValueKind {
+ ZigClangAPValueUninitialized,
+ ZigClangAPValueInt,
+ ZigClangAPValueFloat,
+ ZigClangAPValueComplexInt,
+ ZigClangAPValueComplexFloat,
+ ZigClangAPValueLValue,
+ ZigClangAPValueVector,
+ ZigClangAPValueArray,
+ ZigClangAPValueStruct,
+ ZigClangAPValueUnion,
+ ZigClangAPValueMemberPointer,
+ ZigClangAPValueAddrLabelDiff,
+};
+
+enum ZigClangDeclKind {
+ ZigClangDeclAccessSpec,
+ ZigClangDeclBlock,
+ ZigClangDeclCaptured,
+ ZigClangDeclClassScopeFunctionSpecialization,
+ ZigClangDeclEmpty,
+ ZigClangDeclExport,
+ ZigClangDeclExternCContext,
+ ZigClangDeclFileScopeAsm,
+ ZigClangDeclFriend,
+ ZigClangDeclFriendTemplate,
+ ZigClangDeclImport,
+ ZigClangDeclLinkageSpec,
+ ZigClangDeclLabel,
+ ZigClangDeclNamespace,
+ ZigClangDeclNamespaceAlias,
+ ZigClangDeclObjCCompatibleAlias,
+ ZigClangDeclObjCCategory,
+ ZigClangDeclObjCCategoryImpl,
+ ZigClangDeclObjCImplementation,
+ ZigClangDeclObjCInterface,
+ ZigClangDeclObjCProtocol,
+ ZigClangDeclObjCMethod,
+ ZigClangDeclObjCProperty,
+ ZigClangDeclBuiltinTemplate,
+ ZigClangDeclClassTemplate,
+ ZigClangDeclFunctionTemplate,
+ ZigClangDeclTypeAliasTemplate,
+ ZigClangDeclVarTemplate,
+ ZigClangDeclTemplateTemplateParm,
+ ZigClangDeclEnum,
+ ZigClangDeclRecord,
+ ZigClangDeclCXXRecord,
+ ZigClangDeclClassTemplateSpecialization,
+ ZigClangDeclClassTemplatePartialSpecialization,
+ ZigClangDeclTemplateTypeParm,
+ ZigClangDeclObjCTypeParam,
+ ZigClangDeclTypeAlias,
+ ZigClangDeclTypedef,
+ ZigClangDeclUnresolvedUsingTypename,
+ ZigClangDeclUsing,
+ ZigClangDeclUsingDirective,
+ ZigClangDeclUsingPack,
+ ZigClangDeclUsingShadow,
+ ZigClangDeclConstructorUsingShadow,
+ ZigClangDeclBinding,
+ ZigClangDeclField,
+ ZigClangDeclObjCAtDefsField,
+ ZigClangDeclObjCIvar,
+ ZigClangDeclFunction,
+ ZigClangDeclCXXDeductionGuide,
+ ZigClangDeclCXXMethod,
+ ZigClangDeclCXXConstructor,
+ ZigClangDeclCXXConversion,
+ ZigClangDeclCXXDestructor,
+ ZigClangDeclMSProperty,
+ ZigClangDeclNonTypeTemplateParm,
+ ZigClangDeclVar,
+ ZigClangDeclDecomposition,
+ ZigClangDeclImplicitParam,
+ ZigClangDeclOMPCapturedExpr,
+ ZigClangDeclParmVar,
+ ZigClangDeclVarTemplateSpecialization,
+ ZigClangDeclVarTemplatePartialSpecialization,
+ ZigClangDeclEnumConstant,
+ ZigClangDeclIndirectField,
+ ZigClangDeclOMPDeclareReduction,
+ ZigClangDeclUnresolvedUsingValue,
+ ZigClangDeclOMPRequires,
+ ZigClangDeclOMPThreadPrivate,
+ ZigClangDeclObjCPropertyImpl,
+ ZigClangDeclPragmaComment,
+ ZigClangDeclPragmaDetectMismatch,
+ ZigClangDeclStaticAssert,
+ ZigClangDeclTranslationUnit,
+};
+
+enum ZigClangBuiltinTypeKind {
+ ZigClangBuiltinTypeOCLImage1dRO,
+ ZigClangBuiltinTypeOCLImage1dArrayRO,
+ ZigClangBuiltinTypeOCLImage1dBufferRO,
+ ZigClangBuiltinTypeOCLImage2dRO,
+ ZigClangBuiltinTypeOCLImage2dArrayRO,
+ ZigClangBuiltinTypeOCLImage2dDepthRO,
+ ZigClangBuiltinTypeOCLImage2dArrayDepthRO,
+ ZigClangBuiltinTypeOCLImage2dMSAARO,
+ ZigClangBuiltinTypeOCLImage2dArrayMSAARO,
+ ZigClangBuiltinTypeOCLImage2dMSAADepthRO,
+ ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO,
+ ZigClangBuiltinTypeOCLImage3dRO,
+ ZigClangBuiltinTypeOCLImage1dWO,
+ ZigClangBuiltinTypeOCLImage1dArrayWO,
+ ZigClangBuiltinTypeOCLImage1dBufferWO,
+ ZigClangBuiltinTypeOCLImage2dWO,
+ ZigClangBuiltinTypeOCLImage2dArrayWO,
+ ZigClangBuiltinTypeOCLImage2dDepthWO,
+ ZigClangBuiltinTypeOCLImage2dArrayDepthWO,
+ ZigClangBuiltinTypeOCLImage2dMSAAWO,
+ ZigClangBuiltinTypeOCLImage2dArrayMSAAWO,
+ ZigClangBuiltinTypeOCLImage2dMSAADepthWO,
+ ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO,
+ ZigClangBuiltinTypeOCLImage3dWO,
+ ZigClangBuiltinTypeOCLImage1dRW,
+ ZigClangBuiltinTypeOCLImage1dArrayRW,
+ ZigClangBuiltinTypeOCLImage1dBufferRW,
+ ZigClangBuiltinTypeOCLImage2dRW,
+ ZigClangBuiltinTypeOCLImage2dArrayRW,
+ ZigClangBuiltinTypeOCLImage2dDepthRW,
+ ZigClangBuiltinTypeOCLImage2dArrayDepthRW,
+ ZigClangBuiltinTypeOCLImage2dMSAARW,
+ ZigClangBuiltinTypeOCLImage2dArrayMSAARW,
+ ZigClangBuiltinTypeOCLImage2dMSAADepthRW,
+ ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW,
+ ZigClangBuiltinTypeOCLImage3dRW,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin,
+ ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin,
+ ZigClangBuiltinTypeVoid,
+ ZigClangBuiltinTypeBool,
+ ZigClangBuiltinTypeChar_U,
+ ZigClangBuiltinTypeUChar,
+ ZigClangBuiltinTypeWChar_U,
+ ZigClangBuiltinTypeChar8,
+ ZigClangBuiltinTypeChar16,
+ ZigClangBuiltinTypeChar32,
+ ZigClangBuiltinTypeUShort,
+ ZigClangBuiltinTypeUInt,
+ ZigClangBuiltinTypeULong,
+ ZigClangBuiltinTypeULongLong,
+ ZigClangBuiltinTypeUInt128,
+ ZigClangBuiltinTypeChar_S,
+ ZigClangBuiltinTypeSChar,
+ ZigClangBuiltinTypeWChar_S,
+ ZigClangBuiltinTypeShort,
+ ZigClangBuiltinTypeInt,
+ ZigClangBuiltinTypeLong,
+ ZigClangBuiltinTypeLongLong,
+ ZigClangBuiltinTypeInt128,
+ ZigClangBuiltinTypeShortAccum,
+ ZigClangBuiltinTypeAccum,
+ ZigClangBuiltinTypeLongAccum,
+ ZigClangBuiltinTypeUShortAccum,
+ ZigClangBuiltinTypeUAccum,
+ ZigClangBuiltinTypeULongAccum,
+ ZigClangBuiltinTypeShortFract,
+ ZigClangBuiltinTypeFract,
+ ZigClangBuiltinTypeLongFract,
+ ZigClangBuiltinTypeUShortFract,
+ ZigClangBuiltinTypeUFract,
+ ZigClangBuiltinTypeULongFract,
+ ZigClangBuiltinTypeSatShortAccum,
+ ZigClangBuiltinTypeSatAccum,
+ ZigClangBuiltinTypeSatLongAccum,
+ ZigClangBuiltinTypeSatUShortAccum,
+ ZigClangBuiltinTypeSatUAccum,
+ ZigClangBuiltinTypeSatULongAccum,
+ ZigClangBuiltinTypeSatShortFract,
+ ZigClangBuiltinTypeSatFract,
+ ZigClangBuiltinTypeSatLongFract,
+ ZigClangBuiltinTypeSatUShortFract,
+ ZigClangBuiltinTypeSatUFract,
+ ZigClangBuiltinTypeSatULongFract,
+ ZigClangBuiltinTypeHalf,
+ ZigClangBuiltinTypeFloat,
+ ZigClangBuiltinTypeDouble,
+ ZigClangBuiltinTypeLongDouble,
+ ZigClangBuiltinTypeFloat16,
+ ZigClangBuiltinTypeFloat128,
+ ZigClangBuiltinTypeNullPtr,
+ ZigClangBuiltinTypeObjCId,
+ ZigClangBuiltinTypeObjCClass,
+ ZigClangBuiltinTypeObjCSel,
+ ZigClangBuiltinTypeOCLSampler,
+ ZigClangBuiltinTypeOCLEvent,
+ ZigClangBuiltinTypeOCLClkEvent,
+ ZigClangBuiltinTypeOCLQueue,
+ ZigClangBuiltinTypeOCLReserveID,
+ ZigClangBuiltinTypeDependent,
+ ZigClangBuiltinTypeOverload,
+ ZigClangBuiltinTypeBoundMember,
+ ZigClangBuiltinTypePseudoObject,
+ ZigClangBuiltinTypeUnknownAny,
+ ZigClangBuiltinTypeBuiltinFn,
+ ZigClangBuiltinTypeARCUnbridgedCast,
+ ZigClangBuiltinTypeOMPArraySection,
+};
+
+enum ZigClangCallingConv {
+ ZigClangCallingConv_C, // __attribute__((cdecl))
+ ZigClangCallingConv_X86StdCall, // __attribute__((stdcall))
+ ZigClangCallingConv_X86FastCall, // __attribute__((fastcall))
+ ZigClangCallingConv_X86ThisCall, // __attribute__((thiscall))
+ ZigClangCallingConv_X86VectorCall, // __attribute__((vectorcall))
+ ZigClangCallingConv_X86Pascal, // __attribute__((pascal))
+ ZigClangCallingConv_Win64, // __attribute__((ms_abi))
+ ZigClangCallingConv_X86_64SysV, // __attribute__((sysv_abi))
+ ZigClangCallingConv_X86RegCall, // __attribute__((regcall))
+ ZigClangCallingConv_AAPCS, // __attribute__((pcs("aapcs")))
+ ZigClangCallingConv_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
+ ZigClangCallingConv_IntelOclBicc, // __attribute__((intel_ocl_bicc))
+ ZigClangCallingConv_SpirFunction, // default for OpenCL functions on SPIR target
+ ZigClangCallingConv_OpenCLKernel, // inferred for OpenCL kernels
+ ZigClangCallingConv_Swift, // __attribute__((swiftcall))
+ ZigClangCallingConv_PreserveMost, // __attribute__((preserve_most))
+ ZigClangCallingConv_PreserveAll, // __attribute__((preserve_all))
+ ZigClangCallingConv_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
+};
+
+enum ZigClangStorageClass {
+ // These are legal on both functions and variables.
+ ZigClangStorageClass_None,
+ ZigClangStorageClass_Extern,
+ ZigClangStorageClass_Static,
+ ZigClangStorageClass_PrivateExtern,
+
+ // These are only legal on variables.
+ ZigClangStorageClass_Auto,
+ ZigClangStorageClass_Register,
+};
+
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *,
+ struct ZigClangSourceLocation Loc);
+ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *,
+ struct ZigClangSourceLocation SpellingLoc);
+ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const struct ZigClangSourceManager *,
+ struct ZigClangSourceLocation Loc);
+ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const struct ZigClangSourceManager *,
+ struct ZigClangSourceLocation Loc);
+ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const struct ZigClangSourceManager *,
+ struct ZigClangSourceLocation SL);
+
+ZIG_EXTERN_C struct ZigClangQualType ZigClangASTContext_getPointerType(const struct ZigClangASTContext*, struct ZigClangQualType T);
+
+
+// Can return null.
+ZIG_EXTERN_C struct ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end,
+ struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path);
+ZIG_EXTERN_C void ZigClangASTUnit_delete(struct ZigClangASTUnit *);
+ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len);
+
+ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *);
+ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *);
+ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,
+ bool (*Fn)(void *context, const struct ZigClangDecl *decl));
+
+ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordType_getDecl(const struct ZigClangRecordType *record_ty);
+ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumType_getDecl(const struct ZigClangEnumType *record_ty);
+
+ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const struct ZigClangRecordDecl *record_decl);
+ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const struct ZigClangEnumDecl *);
+ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCanonicalDecl(const struct ZigClangTypedefNameDecl *);
+
+ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *);
+ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *);
+
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangRecordDecl_getLocation(const struct ZigClangRecordDecl *);
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangEnumDecl_getLocation(const struct ZigClangEnumDecl *);
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangTypedefNameDecl_getLocation(const struct ZigClangTypedefNameDecl *);
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDecl_getLocation(const struct ZigClangDecl *);
+
+ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *);
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *);
+ZIG_EXTERN_C bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *);
+ZIG_EXTERN_C enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *);
+ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *, unsigned i);
+ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *);
+
+ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl);
+ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const struct ZigClangRecordDecl *record_decl);
+ZIG_EXTERN_C bool ZigClangRecordDecl_isAnonymousStructOrUnion(const struct ZigClangRecordDecl *record_decl);
+
+ZIG_EXTERN_C struct ZigClangQualType ZigClangEnumDecl_getIntegerType(const struct ZigClangEnumDecl *);
+
+ZIG_EXTERN_C const char *ZigClangDecl_getName_bytes_begin(const struct ZigClangDecl *decl);
+ZIG_EXTERN_C enum ZigClangDeclKind ZigClangDecl_getKind(const struct ZigClangDecl *decl);
+ZIG_EXTERN_C const char *ZigClangDecl_getDeclKindName(const struct ZigClangDecl *decl);
+
+ZIG_EXTERN_C bool ZigClangSourceLocation_eq(struct ZigClangSourceLocation a, struct ZigClangSourceLocation b);
+
+ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const struct ZigClangTypedefType *);
+ZIG_EXTERN_C struct ZigClangQualType ZigClangTypedefNameDecl_getUnderlyingType(const struct ZigClangTypedefNameDecl *);
+
+ZIG_EXTERN_C struct ZigClangQualType ZigClangQualType_getCanonicalType(struct ZigClangQualType);
+ZIG_EXTERN_C const struct ZigClangType *ZigClangQualType_getTypePtr(struct ZigClangQualType);
+ZIG_EXTERN_C void ZigClangQualType_addConst(struct ZigClangQualType *);
+ZIG_EXTERN_C bool ZigClangQualType_eq(struct ZigClangQualType, struct ZigClangQualType);
+ZIG_EXTERN_C bool ZigClangQualType_isConstQualified(struct ZigClangQualType);
+ZIG_EXTERN_C bool ZigClangQualType_isVolatileQualified(struct ZigClangQualType);
+ZIG_EXTERN_C bool ZigClangQualType_isRestrictQualified(struct ZigClangQualType);
+
+ZIG_EXTERN_C enum ZigClangTypeClass ZigClangType_getTypeClass(const struct ZigClangType *self);
+ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct ZigClangType *self);
+ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
+ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);
+
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangStmt_getBeginLoc(const struct ZigClangStmt *self);
+ZIG_EXTERN_C enum ZigClangStmtClass ZigClangStmt_getStmtClass(const struct ZigClangStmt *self);
+ZIG_EXTERN_C bool ZigClangStmt_classof_Expr(const struct ZigClangStmt *self);
+
+ZIG_EXTERN_C enum ZigClangStmtClass ZigClangExpr_getStmtClass(const struct ZigClangExpr *self);
+ZIG_EXTERN_C struct ZigClangQualType ZigClangExpr_getType(const struct ZigClangExpr *self);
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangExpr_getBeginLoc(const struct ZigClangExpr *self);
+
+ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self);
+ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPValue_getInt(const struct ZigClangAPValue *self);
+ZIG_EXTERN_C unsigned ZigClangAPValue_getArrayInitializedElts(const struct ZigClangAPValue *self);
+ZIG_EXTERN_C const struct ZigClangAPValue *ZigClangAPValue_getArrayInitializedElt(const struct ZigClangAPValue *self, unsigned i);
+ZIG_EXTERN_C const struct ZigClangAPValue *ZigClangAPValue_getArrayFiller(const struct ZigClangAPValue *self);
+ZIG_EXTERN_C unsigned ZigClangAPValue_getArraySize(const struct ZigClangAPValue *self);
+ZIG_EXTERN_C struct ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const struct ZigClangAPValue *self);
+
+ZIG_EXTERN_C bool ZigClangAPSInt_isSigned(const struct ZigClangAPSInt *self);
+ZIG_EXTERN_C bool ZigClangAPSInt_isNegative(const struct ZigClangAPSInt *self);
+ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPSInt_negate(const struct ZigClangAPSInt *self);
+ZIG_EXTERN_C void ZigClangAPSInt_free(const struct ZigClangAPSInt *self);
+ZIG_EXTERN_C const uint64_t *ZigClangAPSInt_getRawData(const struct ZigClangAPSInt *self);
+ZIG_EXTERN_C unsigned ZigClangAPSInt_getNumWords(const struct ZigClangAPSInt *self);
+
+ZIG_EXTERN_C const struct ZigClangExpr *ZigClangAPValueLValueBase_dyn_cast_Expr(struct ZigClangAPValueLValueBase self);
+
+ZIG_EXTERN_C enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self);
+
+ZIG_EXTERN_C bool ZigClangFunctionType_getNoReturnAttr(const struct ZigClangFunctionType *self);
+ZIG_EXTERN_C enum ZigClangCallingConv ZigClangFunctionType_getCallConv(const struct ZigClangFunctionType *self);
+ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClangFunctionType *self);
+
+ZIG_EXTERN_C bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self);
+ZIG_EXTERN_C unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self);
+ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self, unsigned i);
+
+
+ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self);
+ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self);
+
#endif
diff --git a/std/array_list.zig b/std/array_list.zig
index b173dab747..ca7d5f911e 100644
--- a/std/array_list.zig
+++ b/std/array_list.zig
@@ -111,6 +111,17 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
new_item_ptr.* = item;
}
+ pub fn orderedRemove(self: *Self, i: usize) T {
+ const newlen = self.len - 1;
+ if (newlen == i) return self.pop();
+
+ const old_item = self.at(i);
+ for (self.items[i..newlen]) |*b, j| b.* = self.items[i + 1 + j];
+ self.items[newlen] = undefined;
+ self.len = newlen;
+ return old_item;
+ }
+
/// Removes the element at the specified index and returns it.
/// The empty slot is filled from the end of the list.
pub fn swapRemove(self: *Self, i: usize) T {
@@ -279,6 +290,33 @@ test "std.ArrayList.basic" {
testing.expect(list.pop() == 33);
}
+test "std.ArrayList.orderedRemove" {
+ var list = ArrayList(i32).init(debug.global_allocator);
+ defer list.deinit();
+
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
+ try list.append(4);
+ try list.append(5);
+ try list.append(6);
+ try list.append(7);
+
+ //remove from middle
+ testing.expectEqual(i32(4), list.orderedRemove(3));
+ testing.expectEqual(i32(5), list.at(3));
+ testing.expectEqual(usize(6), list.len);
+
+ //remove from end
+ testing.expectEqual(i32(7), list.orderedRemove(5));
+ testing.expectEqual(usize(5), list.len);
+
+ //remove from front
+ testing.expectEqual(i32(1), list.orderedRemove(0));
+ testing.expectEqual(i32(2), list.at(0));
+ testing.expectEqual(usize(4), list.len);
+}
+
test "std.ArrayList.swapRemove" {
var list = ArrayList(i32).init(debug.global_allocator);
defer list.deinit();
diff --git a/std/build.zig b/std/build.zig
index 2bd4a9b08f..b5ec97ab5f 100644
--- a/std/build.zig
+++ b/std/build.zig
@@ -50,6 +50,8 @@ pub const Builder = struct {
build_root: []const u8,
cache_root: []const u8,
release_mode: ?builtin.Mode,
+ override_std_dir: ?[]const u8,
+ override_lib_dir: ?[]const u8,
pub const CStd = enum {
C89,
@@ -133,6 +135,8 @@ pub const Builder = struct {
},
.have_install_step = false,
.release_mode = null,
+ .override_std_dir = null,
+ .override_lib_dir = null,
};
self.detectNativeSystemPaths();
self.default_step = self.step("default", "Build the project");
@@ -937,8 +941,11 @@ pub const LibExeObjStep = struct {
verbose_link: bool,
verbose_cc: bool,
disable_gen_h: bool,
+ bundle_compiler_rt: bool,
+ disable_stack_probing: bool,
c_std: Builder.CStd,
override_std_dir: ?[]const u8,
+ override_lib_dir: ?[]const u8,
main_pkg_path: ?[]const u8,
exec_cmd_args: ?[]const ?[]const u8,
name_prefix: []const u8,
@@ -1039,11 +1046,14 @@ pub const LibExeObjStep = struct {
.c_std = Builder.CStd.C99,
.system_linker_hack = false,
.override_std_dir = null,
+ .override_lib_dir = null,
.main_pkg_path = null,
.exec_cmd_args = null,
.name_prefix = "",
.filter = null,
.disable_gen_h = false,
+ .bundle_compiler_rt = false,
+ .disable_stack_probing = false,
.output_dir = null,
.need_system_paths = false,
.single_threaded = false,
@@ -1446,6 +1456,12 @@ pub const LibExeObjStep = struct {
if (self.disable_gen_h) {
try zig_args.append("--disable-gen-h");
}
+ if (self.bundle_compiler_rt) {
+ try zig_args.append("--bundle-compiler-rt");
+ }
+ if (self.disable_stack_probing) {
+ try zig_args.append("--disable-stack-probing");
+ }
switch (self.target) {
Target.Native => {},
@@ -1528,6 +1544,17 @@ pub const LibExeObjStep = struct {
if (self.override_std_dir) |dir| {
try zig_args.append("--override-std-dir");
try zig_args.append(builder.pathFromRoot(dir));
+ } else if (self.builder.override_std_dir) |dir| {
+ try zig_args.append("--override-std-dir");
+ try zig_args.append(builder.pathFromRoot(dir));
+ }
+
+ if (self.override_lib_dir) |dir| {
+ try zig_args.append("--override-lib-dir");
+ try zig_args.append(builder.pathFromRoot(dir));
+ } else if (self.builder.override_lib_dir) |dir| {
+ try zig_args.append("--override-lib-dir");
+ try zig_args.append(builder.pathFromRoot(dir));
}
if (self.main_pkg_path) |dir| {
diff --git a/std/c.zig b/std/c.zig
index acff9229d1..db28105eec 100644
--- a/std/c.zig
+++ b/std/c.zig
@@ -12,6 +12,12 @@ pub use switch (builtin.os) {
// TODO https://github.com/ziglang/zig/issues/265 on this whole file
+pub const FILE = @OpaqueType();
+pub extern "c" fn fopen(filename: [*]const u8, modes: [*]const u8) ?*FILE;
+pub extern "c" fn fclose(stream: *FILE) c_int;
+pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
+pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
+
pub extern "c" fn abort() noreturn;
pub extern "c" fn exit(code: c_int) noreturn;
pub extern "c" fn isatty(fd: c_int) c_int;
diff --git a/std/c/freebsd.zig b/std/c/freebsd.zig
index 2f2f4c0a1b..b6cf15bf31 100644
--- a/std/c/freebsd.zig
+++ b/std/c/freebsd.zig
@@ -42,14 +42,36 @@ pub const pthread_attr_t = extern struct {
};
pub const msghdr = extern struct {
- msg_name: *u8,
+ /// optional address
+ msg_name: ?*sockaddr,
+ /// size of address
msg_namelen: socklen_t,
- msg_iov: *iovec,
+ /// scatter/gather array
+ msg_iov: [*]iovec,
+ /// # elements in msg_iov
msg_iovlen: i32,
- __pad1: i32,
- msg_control: *u8,
+ /// ancillary data
+ msg_control: ?*c_void,
+ /// ancillary data buffer len
msg_controllen: socklen_t,
- __pad2: socklen_t,
+ /// flags on received message
+ msg_flags: i32,
+};
+
+pub const msghdr_const = extern struct {
+ /// optional address
+ msg_name: ?*const sockaddr,
+ /// size of address
+ msg_namelen: socklen_t,
+ /// scatter/gather array
+ msg_iov: [*]iovec_const,
+ /// # elements in msg_iov
+ msg_iovlen: i32,
+ /// ancillary data
+ msg_control: ?*c_void,
+ /// ancillary data buffer len
+ msg_controllen: socklen_t,
+ /// flags on received message
msg_flags: i32,
};
diff --git a/std/c/linux.zig b/std/c/linux.zig
index b0dadf071d..48e359f361 100644
--- a/std/c/linux.zig
+++ b/std/c/linux.zig
@@ -1,3 +1,4 @@
+const linux = @import("../os/linux.zig");
pub use @import("../os/linux/errno.zig");
pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;
@@ -11,3 +12,6 @@ pub const pthread_attr_t = extern struct {
/// See std.elf for constants for this
pub extern fn getauxval(__type: c_ulong) c_ulong;
+
+pub const dl_iterate_phdr_callback = extern fn (info: *linux.dl_phdr_info, size: usize, data: ?*c_void) c_int;
+pub extern fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
diff --git a/std/c/netbsd.zig b/std/c/netbsd.zig
index 796d45dafc..2c07ee296b 100644
--- a/std/c/netbsd.zig
+++ b/std/c/netbsd.zig
@@ -42,14 +42,36 @@ pub const pthread_attr_t = extern struct {
};
pub const msghdr = extern struct {
- msg_name: *u8,
+ /// optional address
+ msg_name: ?*sockaddr,
+ /// size of address
msg_namelen: socklen_t,
- msg_iov: *iovec,
+ /// scatter/gather array
+ msg_iov: [*]iovec,
+ /// # elements in msg_iov
msg_iovlen: i32,
- __pad1: i32,
- msg_control: *u8,
+ /// ancillary data
+ msg_control: ?*c_void,
+ /// ancillary data buffer len
msg_controllen: socklen_t,
- __pad2: socklen_t,
+ /// flags on received message
+ msg_flags: i32,
+};
+
+pub const msghdr_const = extern struct {
+ /// optional address
+ msg_name: ?*const sockaddr,
+ /// size of address
+ msg_namelen: socklen_t,
+ /// scatter/gather array
+ msg_iov: [*]iovec_const,
+ /// # elements in msg_iov
+ msg_iovlen: i32,
+ /// ancillary data
+ msg_control: ?*c_void,
+ /// ancillary data buffer len
+ msg_controllen: socklen_t,
+ /// flags on received message
msg_flags: i32,
};
diff --git a/std/crypto/chacha20.zig b/std/crypto/chacha20.zig
index 78ef700bdf..796b5c6e4f 100644
--- a/std/crypto/chacha20.zig
+++ b/std/crypto/chacha20.zig
@@ -142,7 +142,7 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
assert(in.len >= out.len);
assert(counter +% (in.len >> 6) >= counter);
- var cursor: u64 = 0;
+ var cursor: usize = 0;
var k: [8]u32 = undefined;
var c: [4]u32 = undefined;
@@ -161,7 +161,8 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
const block_size = (1 << 6);
- const big_block = (block_size << 32);
+ // The full block size is greater than the address space on a 32bit machine
+ const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize);
// first partial big block
if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) {
diff --git a/std/debug.zig b/std/debug.zig
index c85a982059..d017f96144 100644
--- a/std/debug.zig
+++ b/std/debug.zig
@@ -13,6 +13,8 @@ const ArrayList = std.ArrayList;
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
+const leb = @import("debug/leb128.zig");
+
pub const FailingAllocator = @import("debug/failing_allocator.zig").FailingAllocator;
pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator;
@@ -214,14 +216,14 @@ pub fn writeStackTrace(
tty_color: bool,
) !void {
var frame_index: usize = 0;
- var frames_left: usize = stack_trace.index;
+ var frames_left: usize = std.math.min(stack_trace.index, stack_trace.instruction_addresses.len);
while (frames_left != 0) : ({
frames_left -= 1;
frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
}) {
const return_address = stack_trace.instruction_addresses[frame_index];
- try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);
+ try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color);
}
}
@@ -263,7 +265,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color
}
var it = StackIterator.init(start_addr);
while (it.next()) |return_address| {
- try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);
+ try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color);
}
}
@@ -376,7 +378,6 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
// There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records)
// from now on. We will iterate through them, and eventually find a LineInfo that we're interested in,
// breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection.
-
const subsection_end_index = sect_offset + subsect_hdr.Length;
while (line_index < subsection_end_index) {
@@ -690,9 +691,9 @@ pub fn printSourceAtAddressDwarf(
return;
};
const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
- if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| {
+ if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address)) |line_info| {
defer line_info.deinit();
- const symbol_name = "???";
+ const symbol_name = getSymbolNameDwarf(debug_info, address) orelse "???";
try printLineInfo(
out_stream,
line_info,
@@ -969,6 +970,8 @@ fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Sec
pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void {
di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator);
di.compile_unit_list = ArrayList(CompileUnit).init(allocator);
+ di.func_list = ArrayList(Func).init(allocator);
+ try scanAllFunctions(di);
try scanAllCompileUnits(di);
}
@@ -992,6 +995,7 @@ pub fn openElfDebugInfo(
.debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")),
.abbrev_table_list = undefined,
.compile_unit_list = undefined,
+ .func_list = undefined,
};
try openDwarfDebugInfo(&di, allocator);
return di;
@@ -1162,6 +1166,7 @@ pub const DwarfInfo = struct {
debug_ranges: ?Section,
abbrev_table_list: ArrayList(AbbrevTableHeader),
compile_unit_list: ArrayList(CompileUnit),
+ func_list: ArrayList(Func),
pub const Section = struct {
offset: usize,
@@ -1178,7 +1183,7 @@ pub const DwarfInfo = struct {
};
pub const DebugInfo = switch (builtin.os) {
- builtin.Os.macosx => struct {
+ builtin.Os.macosx, builtin.Os.ios => struct {
symbols: []const MachoSymbol,
strings: []const u8,
ofiles: OFileTable,
@@ -1213,7 +1218,6 @@ const CompileUnit = struct {
version: u16,
is_64: bool,
die: *Die,
- index: usize,
pc_range: ?PcRange,
};
@@ -1244,21 +1248,19 @@ const FormValue = union(enum) {
ExprLoc: []u8,
Flag: bool,
SecOffset: u64,
- Ref: []u8,
+ Ref: u64,
RefAddr: u64,
- RefSig8: u64,
String: []u8,
StrPtr: u64,
};
const Constant = struct {
- payload: []u8,
+ payload: u64,
signed: bool,
fn asUnsignedLe(self: *const Constant) !u64 {
- if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
if (self.signed) return error.InvalidDebugInfo;
- return mem.readVarInt(u64, self.payload, builtin.Endian.Little);
+ return self.payload;
}
};
@@ -1304,6 +1306,14 @@ const Die = struct {
};
}
+ fn getAttrRef(self: *const Die, id: u64) !u64 {
+ const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
+ return switch (form_value.*) {
+ FormValue.Ref => |value| value,
+ else => error.InvalidDebugInfo,
+ };
+ }
+
fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 {
const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
return switch (form_value.*) {
@@ -1443,11 +1453,18 @@ fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !
return parseFormValueBlockLen(allocator, in_stream, block_len);
}
-fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue {
+fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, comptime size: i32) !FormValue {
return FormValue{
.Const = Constant{
.signed = signed,
- .payload = try readAllocBytes(allocator, in_stream, size),
+ .payload = switch (size) {
+ 1 => try in_stream.readIntLittle(u8),
+ 2 => try in_stream.readIntLittle(u16),
+ 4 => try in_stream.readIntLittle(u32),
+ 8 => try in_stream.readIntLittle(u64),
+ -1 => if (signed) @bitCast(u64, try leb.readILEB128(i64, in_stream)) else try leb.readULEB128(u64, in_stream),
+ else => @compileError("Invalid size"),
+ },
},
};
}
@@ -1460,14 +1477,17 @@ fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable;
}
-fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
- const buf = try readAllocBytes(allocator, in_stream, size);
- return FormValue{ .Ref = buf };
-}
-
-fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
- const block_len = try in_stream.readIntLittle(T);
- return parseFormValueRefLen(allocator, in_stream, block_len);
+fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue {
+ return FormValue{
+ .Ref = switch (size) {
+ 1 => try in_stream.readIntLittle(u8),
+ 2 => try in_stream.readIntLittle(u16),
+ 4 => try in_stream.readIntLittle(u32),
+ 8 => try in_stream.readIntLittle(u64),
+ -1 => try leb.readULEB128(u64, in_stream),
+ else => unreachable,
+ },
+ };
}
fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {
@@ -1477,7 +1497,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
DW.FORM_block => x: {
- const block_len = try readULeb128(in_stream);
+ const block_len = try leb.readULEB128(usize, in_stream);
return parseFormValueBlockLen(allocator, in_stream, block_len);
},
DW.FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1),
@@ -1485,12 +1505,11 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),
DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),
DW.FORM_udata, DW.FORM_sdata => {
- const block_len = try readULeb128(in_stream);
const signed = form_id == DW.FORM_sdata;
- return parseFormValueConstant(allocator, in_stream, signed, block_len);
+ return parseFormValueConstant(allocator, in_stream, signed, -1);
},
DW.FORM_exprloc => {
- const size = try readULeb128(in_stream);
+ const size = try leb.readULEB128(usize, in_stream);
const buf = try readAllocBytes(allocator, in_stream, size);
return FormValue{ .ExprLoc = buf };
},
@@ -1498,22 +1517,19 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
DW.FORM_flag_present => FormValue{ .Flag = true },
DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
- DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),
- DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),
- DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, u32),
- DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, u64),
- DW.FORM_ref_udata => {
- const ref_len = try readULeb128(in_stream);
- return parseFormValueRefLen(allocator, in_stream, ref_len);
- },
+ DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, 1),
+ DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, 2),
+ DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, 4),
+ DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, 8),
+ DW.FORM_ref_udata => parseFormValueRef(allocator, in_stream, -1),
DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
- DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) },
+ DW.FORM_ref_sig8 => FormValue{ .Ref = try in_stream.readIntLittle(u64) },
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_indirect => {
- const child_form_id = try readULeb128(in_stream);
+ const child_form_id = try leb.readULEB128(u64, in_stream);
return parseFormValue(allocator, in_stream, child_form_id, is_64);
},
else => error.InvalidDebugInfo,
@@ -1523,19 +1539,19 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {
var result = AbbrevTable.init(di.allocator());
while (true) {
- const abbrev_code = try readULeb128(di.dwarf_in_stream);
+ const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
if (abbrev_code == 0) return result;
try result.append(AbbrevTableEntry{
.abbrev_code = abbrev_code,
- .tag_id = try readULeb128(di.dwarf_in_stream),
+ .tag_id = try leb.readULEB128(u64, di.dwarf_in_stream),
.has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes,
.attrs = ArrayList(AbbrevAttr).init(di.allocator()),
});
const attrs = &result.items[result.len - 1].attrs;
while (true) {
- const attr_id = try readULeb128(di.dwarf_in_stream);
- const form_id = try readULeb128(di.dwarf_in_stream);
+ const attr_id = try leb.readULEB128(u64, di.dwarf_in_stream);
+ const form_id = try leb.readULEB128(u64, di.dwarf_in_stream);
if (attr_id == 0 and form_id == 0) break;
try attrs.append(AbbrevAttr{
.attr_id = attr_id,
@@ -1568,8 +1584,28 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
return null;
}
+fn parseDie1(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Die {
+ const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
+ if (abbrev_code == 0) return null;
+ const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
+
+ var result = Die{
+ .tag_id = table_entry.tag_id,
+ .has_children = table_entry.has_children,
+ .attrs = ArrayList(Die.Attr).init(di.allocator()),
+ };
+ try result.attrs.resize(table_entry.attrs.len);
+ for (table_entry.attrs.toSliceConst()) |attr, i| {
+ result.attrs.items[i] = Die.Attr{
+ .id = attr.attr_id,
+ .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64),
+ };
+ }
+ return result;
+}
+
fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
- const abbrev_code = try readULeb128(di.dwarf_in_stream);
+ const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
var result = Die{
@@ -1682,9 +1718,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
while (true) {
const file_name = readStringMem(&ptr);
if (file_name.len == 0) break;
- const dir_index = try readULeb128Mem(&ptr);
- const mtime = try readULeb128Mem(&ptr);
- const len_bytes = try readULeb128Mem(&ptr);
+ const dir_index = try leb.readULEB128Mem(usize, &ptr);
+ const mtime = try leb.readULEB128Mem(usize, &ptr);
+ const len_bytes = try leb.readULEB128Mem(usize, &ptr);
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
@@ -1698,7 +1734,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
const opcode = readByteMem(&ptr);
if (opcode == DW.LNS_extended_op) {
- const op_size = try readULeb128Mem(&ptr);
+ const op_size = try leb.readULEB128Mem(u64, &ptr);
if (op_size < 1) return error.InvalidDebugInfo;
var sub_op = readByteMem(&ptr);
switch (sub_op) {
@@ -1713,9 +1749,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
},
DW.LNE_define_file => {
const file_name = readStringMem(&ptr);
- const dir_index = try readULeb128Mem(&ptr);
- const mtime = try readULeb128Mem(&ptr);
- const len_bytes = try readULeb128Mem(&ptr);
+ const dir_index = try leb.readULEB128Mem(usize, &ptr);
+ const mtime = try leb.readULEB128Mem(usize, &ptr);
+ const len_bytes = try leb.readULEB128Mem(usize, &ptr);
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
@@ -1743,19 +1779,19 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
prog.basic_block = false;
},
DW.LNS_advance_pc => {
- const arg = try readULeb128Mem(&ptr);
+ const arg = try leb.readULEB128Mem(u64, &ptr);
prog.address += arg * minimum_instruction_length;
},
DW.LNS_advance_line => {
- const arg = try readILeb128Mem(&ptr);
+ const arg = try leb.readILEB128Mem(i64, &ptr);
prog.line += arg;
},
DW.LNS_set_file => {
- const arg = try readULeb128Mem(&ptr);
+ const arg = try leb.readULEB128Mem(u64, &ptr);
prog.file = arg;
},
DW.LNS_set_column => {
- const arg = try readULeb128Mem(&ptr);
+ const arg = try leb.readULEB128Mem(u64, &ptr);
prog.column = arg;
},
DW.LNS_negate_stmt => {
@@ -1787,182 +1823,292 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);
+ const line_info_offset = try compile_unit.die.getAttrSecOffset(DW.AT_stmt_list);
- const debug_line_end = di.debug_line.offset + di.debug_line.size;
- var this_offset = di.debug_line.offset;
- var this_index: usize = 0;
+ assert(line_info_offset < di.debug_line.size);
- while (this_offset < debug_line_end) : (this_index += 1) {
- try di.dwarf_seekable_stream.seekTo(this_offset);
+ try di.dwarf_seekable_stream.seekTo(di.debug_line.offset + line_info_offset);
- var is_64: bool = undefined;
- const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
- if (unit_length == 0) return error.MissingDebugInfo;
- const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
+ var is_64: bool = undefined;
+ const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
+ if (unit_length == 0) {
+ return error.MissingDebugInfo;
+ }
+ const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
- if (compile_unit.index != this_index) {
- this_offset += next_offset;
- continue;
- }
+ const version = try di.dwarf_in_stream.readInt(u16, di.endian);
+ // TODO support 3 and 5
+ if (version != 2 and version != 4) return error.InvalidDebugInfo;
- const version = try di.dwarf_in_stream.readInt(u16, di.endian);
- // TODO support 3 and 5
- if (version != 2 and version != 4) return error.InvalidDebugInfo;
+ const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
+ const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
+
+ const minimum_instruction_length = try di.dwarf_in_stream.readByte();
+ if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
+
+ if (version >= 4) {
+ // maximum_operations_per_instruction
+ _ = try di.dwarf_in_stream.readByte();
+ }
+
+ const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0;
+ const line_base = try di.dwarf_in_stream.readByteSigned();
+
+ const line_range = try di.dwarf_in_stream.readByte();
+ if (line_range == 0) return error.InvalidDebugInfo;
- const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
- const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
+ const opcode_base = try di.dwarf_in_stream.readByte();
- const minimum_instruction_length = try di.dwarf_in_stream.readByte();
- if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
+ const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);
- if (version >= 4) {
- // maximum_operations_per_instruction
- _ = try di.dwarf_in_stream.readByte();
+ {
+ var i: usize = 0;
+ while (i < opcode_base - 1) : (i += 1) {
+ standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte();
}
+ }
- const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0;
- const line_base = try di.dwarf_in_stream.readByteSigned();
+ var include_directories = ArrayList([]u8).init(di.allocator());
+ try include_directories.append(compile_unit_cwd);
+ while (true) {
+ const dir = try di.readString();
+ if (dir.len == 0) break;
+ try include_directories.append(dir);
+ }
+
+ var file_entries = ArrayList(FileEntry).init(di.allocator());
+ var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address);
- const line_range = try di.dwarf_in_stream.readByte();
- if (line_range == 0) return error.InvalidDebugInfo;
+ while (true) {
+ const file_name = try di.readString();
+ if (file_name.len == 0) break;
+ const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream);
+ const mtime = try leb.readULEB128(usize, di.dwarf_in_stream);
+ const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream);
+ try file_entries.append(FileEntry{
+ .file_name = file_name,
+ .dir_index = dir_index,
+ .mtime = mtime,
+ .len_bytes = len_bytes,
+ });
+ }
- const opcode_base = try di.dwarf_in_stream.readByte();
+ try di.dwarf_seekable_stream.seekTo(prog_start_offset);
- const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);
+ while (true) {
+ const opcode = try di.dwarf_in_stream.readByte();
- {
- var i: usize = 0;
- while (i < opcode_base - 1) : (i += 1) {
- standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte();
+ if (opcode == DW.LNS_extended_op) {
+ const op_size = try leb.readULEB128(u64, di.dwarf_in_stream);
+ if (op_size < 1) return error.InvalidDebugInfo;
+ var sub_op = try di.dwarf_in_stream.readByte();
+ switch (sub_op) {
+ DW.LNE_end_sequence => {
+ prog.end_sequence = true;
+ if (try prog.checkLineMatch()) |info| return info;
+ return error.MissingDebugInfo;
+ },
+ DW.LNE_set_address => {
+ const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
+ prog.address = addr;
+ },
+ DW.LNE_define_file => {
+ const file_name = try di.readString();
+ const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream);
+ const mtime = try leb.readULEB128(usize, di.dwarf_in_stream);
+ const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream);
+ try file_entries.append(FileEntry{
+ .file_name = file_name,
+ .dir_index = dir_index,
+ .mtime = mtime,
+ .len_bytes = len_bytes,
+ });
+ },
+ else => {
+ const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
+ try di.dwarf_seekable_stream.seekForward(fwd_amt);
+ },
+ }
+ } else if (opcode >= opcode_base) {
+ // special opcodes
+ const adjusted_opcode = opcode - opcode_base;
+ const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range);
+ const inc_line = i32(line_base) + i32(adjusted_opcode % line_range);
+ prog.line += inc_line;
+ prog.address += inc_addr;
+ if (try prog.checkLineMatch()) |info| return info;
+ prog.basic_block = false;
+ } else {
+ switch (opcode) {
+ DW.LNS_copy => {
+ if (try prog.checkLineMatch()) |info| return info;
+ prog.basic_block = false;
+ },
+ DW.LNS_advance_pc => {
+ const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
+ prog.address += arg * minimum_instruction_length;
+ },
+ DW.LNS_advance_line => {
+ const arg = try leb.readILEB128(i64, di.dwarf_in_stream);
+ prog.line += arg;
+ },
+ DW.LNS_set_file => {
+ const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
+ prog.file = arg;
+ },
+ DW.LNS_set_column => {
+ const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
+ prog.column = arg;
+ },
+ DW.LNS_negate_stmt => {
+ prog.is_stmt = !prog.is_stmt;
+ },
+ DW.LNS_set_basic_block => {
+ prog.basic_block = true;
+ },
+ DW.LNS_const_add_pc => {
+ const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range);
+ prog.address += inc_addr;
+ },
+ DW.LNS_fixed_advance_pc => {
+ const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
+ prog.address += arg;
+ },
+ DW.LNS_set_prologue_end => {},
+ else => {
+ if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
+ const len_bytes = standard_opcode_lengths[opcode - 1];
+ try di.dwarf_seekable_stream.seekForward(len_bytes);
+ },
}
}
+ }
- var include_directories = ArrayList([]u8).init(di.allocator());
- try include_directories.append(compile_unit_cwd);
- while (true) {
- const dir = try di.readString();
- if (dir.len == 0) break;
- try include_directories.append(dir);
- }
+ return error.MissingDebugInfo;
+}
- var file_entries = ArrayList(FileEntry).init(di.allocator());
- var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address);
+const Func = struct {
+ pc_range: ?PcRange,
+ name: ?[]u8,
+};
- while (true) {
- const file_name = try di.readString();
- if (file_name.len == 0) break;
- const dir_index = try readULeb128(di.dwarf_in_stream);
- const mtime = try readULeb128(di.dwarf_in_stream);
- const len_bytes = try readULeb128(di.dwarf_in_stream);
- try file_entries.append(FileEntry{
- .file_name = file_name,
- .dir_index = dir_index,
- .mtime = mtime,
- .len_bytes = len_bytes,
- });
+fn getSymbolNameDwarf(di: *DwarfInfo, address: u64) ?[]const u8 {
+ for (di.func_list.toSliceConst()) |*func| {
+ if (func.pc_range) |range| {
+ if (address >= range.start and address < range.end) {
+ return func.name;
+ }
}
+ }
+
+ return null;
+}
- try di.dwarf_seekable_stream.seekTo(prog_start_offset);
+fn scanAllFunctions(di: *DwarfInfo) !void {
+ const debug_info_end = di.debug_info.offset + di.debug_info.size;
+ var this_unit_offset = di.debug_info.offset;
- while (true) {
- const opcode = try di.dwarf_in_stream.readByte();
-
- if (opcode == DW.LNS_extended_op) {
- const op_size = try readULeb128(di.dwarf_in_stream);
- if (op_size < 1) return error.InvalidDebugInfo;
- var sub_op = try di.dwarf_in_stream.readByte();
- switch (sub_op) {
- DW.LNE_end_sequence => {
- prog.end_sequence = true;
- if (try prog.checkLineMatch()) |info| return info;
- return error.MissingDebugInfo;
- },
- DW.LNE_set_address => {
- const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
- prog.address = addr;
- },
- DW.LNE_define_file => {
- const file_name = try di.readString();
- const dir_index = try readULeb128(di.dwarf_in_stream);
- const mtime = try readULeb128(di.dwarf_in_stream);
- const len_bytes = try readULeb128(di.dwarf_in_stream);
- try file_entries.append(FileEntry{
- .file_name = file_name,
- .dir_index = dir_index,
- .mtime = mtime,
- .len_bytes = len_bytes,
- });
- },
- else => {
- const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
- try di.dwarf_seekable_stream.seekForward(fwd_amt);
- },
- }
- } else if (opcode >= opcode_base) {
- // special opcodes
- const adjusted_opcode = opcode - opcode_base;
- const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range);
- const inc_line = i32(line_base) + i32(adjusted_opcode % line_range);
- prog.line += inc_line;
- prog.address += inc_addr;
- if (try prog.checkLineMatch()) |info| return info;
- prog.basic_block = false;
- } else {
- switch (opcode) {
- DW.LNS_copy => {
- if (try prog.checkLineMatch()) |info| return info;
- prog.basic_block = false;
- },
- DW.LNS_advance_pc => {
- const arg = try readULeb128(di.dwarf_in_stream);
- prog.address += arg * minimum_instruction_length;
- },
- DW.LNS_advance_line => {
- const arg = try readILeb128(di.dwarf_in_stream);
- prog.line += arg;
- },
- DW.LNS_set_file => {
- const arg = try readULeb128(di.dwarf_in_stream);
- prog.file = arg;
- },
- DW.LNS_set_column => {
- const arg = try readULeb128(di.dwarf_in_stream);
- prog.column = arg;
- },
- DW.LNS_negate_stmt => {
- prog.is_stmt = !prog.is_stmt;
- },
- DW.LNS_set_basic_block => {
- prog.basic_block = true;
- },
- DW.LNS_const_add_pc => {
- const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range);
- prog.address += inc_addr;
- },
- DW.LNS_fixed_advance_pc => {
- const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
- prog.address += arg;
- },
- DW.LNS_set_prologue_end => {},
- else => {
- if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
- const len_bytes = standard_opcode_lengths[opcode - 1];
- try di.dwarf_seekable_stream.seekForward(len_bytes);
- },
- }
+ while (this_unit_offset < debug_info_end) {
+ try di.dwarf_seekable_stream.seekTo(this_unit_offset);
+
+ var is_64: bool = undefined;
+ const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
+ if (unit_length == 0) return;
+ const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
+
+ const version = try di.dwarf_in_stream.readInt(u16, di.endian);
+ if (version < 2 or version > 5) return error.InvalidDebugInfo;
+
+ const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
+
+ const address_size = try di.dwarf_in_stream.readByte();
+ if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
+
+ const compile_unit_pos = try di.dwarf_seekable_stream.getPos();
+ const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset);
+
+ try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
+
+ const next_unit_pos = this_unit_offset + next_offset;
+
+ while ((try di.dwarf_seekable_stream.getPos()) < next_unit_pos) {
+ const die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse continue;
+ const after_die_offset = try di.dwarf_seekable_stream.getPos();
+
+ switch (die_obj.tag_id) {
+ DW.TAG_subprogram, DW.TAG_inlined_subroutine, DW.TAG_subroutine, DW.TAG_entry_point => {
+ const fn_name = x: {
+ var depth: i32 = 3;
+ var this_die_obj = die_obj;
+ // Prenvent endless loops
+ while (depth > 0) : (depth -= 1) {
+ if (this_die_obj.getAttr(DW.AT_name)) |_| {
+ const name = try this_die_obj.getAttrString(di, DW.AT_name);
+ break :x name;
+ } else if (this_die_obj.getAttr(DW.AT_abstract_origin)) |ref| {
+ // Follow the DIE it points to and repeat
+ const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin);
+ if (ref_offset > next_offset) return error.InvalidDebugInfo;
+ try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset);
+ this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
+ } else if (this_die_obj.getAttr(DW.AT_specification)) |ref| {
+ // Follow the DIE it points to and repeat
+ const ref_offset = try this_die_obj.getAttrRef(DW.AT_specification);
+ if (ref_offset > next_offset) return error.InvalidDebugInfo;
+ try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset);
+ this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
+ } else {
+ break :x null;
+ }
+ }
+
+ break :x null;
+ };
+
+ const pc_range = x: {
+ if (die_obj.getAttrAddr(DW.AT_low_pc)) |low_pc| {
+ if (die_obj.getAttr(DW.AT_high_pc)) |high_pc_value| {
+ const pc_end = switch (high_pc_value.*) {
+ FormValue.Address => |value| value,
+ FormValue.Const => |value| b: {
+ const offset = try value.asUnsignedLe();
+ break :b (low_pc + offset);
+ },
+ else => return error.InvalidDebugInfo,
+ };
+ break :x PcRange{
+ .start = low_pc,
+ .end = pc_end,
+ };
+ } else {
+ break :x null;
+ }
+ } else |err| {
+ if (err != error.MissingDebugInfo) return err;
+ break :x null;
+ }
+ };
+
+ try di.func_list.append(Func{
+ .name = fn_name,
+ .pc_range = pc_range,
+ });
+ },
+ else => {
+ continue;
+ },
}
+
+ try di.dwarf_seekable_stream.seekTo(after_die_offset);
}
- this_offset += next_offset;
+ this_unit_offset += next_offset;
}
-
- return error.MissingDebugInfo;
}
fn scanAllCompileUnits(di: *DwarfInfo) !void {
const debug_info_end = di.debug_info.offset + di.debug_info.size;
var this_unit_offset = di.debug_info.offset;
- var cu_index: usize = 0;
while (this_unit_offset < debug_info_end) {
try di.dwarf_seekable_stream.seekTo(this_unit_offset);
@@ -2019,11 +2165,9 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
.is_64 = is_64,
.pc_range = pc_range,
.die = compile_unit_die,
- .index = cu_index,
});
this_unit_offset += next_offset;
- cu_index += 1;
}
}
@@ -2098,52 +2242,6 @@ fn readStringMem(ptr: *[*]const u8) []const u8 {
return result;
}
-fn readULeb128Mem(ptr: *[*]const u8) !u64 {
- var result: u64 = 0;
- var shift: usize = 0;
- var i: usize = 0;
-
- while (true) {
- const byte = ptr.*[i];
- i += 1;
-
- var operand: u64 = undefined;
-
- if (@shlWithOverflow(u64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
-
- result |= operand;
-
- if ((byte & 0b10000000) == 0) {
- ptr.* += i;
- return result;
- }
-
- shift += 7;
- }
-}
-fn readILeb128Mem(ptr: *[*]const u8) !i64 {
- var result: i64 = 0;
- var shift: usize = 0;
- var i: usize = 0;
-
- while (true) {
- const byte = ptr.*[i];
- i += 1;
-
- var operand: i64 = undefined;
- if (@shlWithOverflow(i64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
-
- result |= operand;
- shift += 7;
-
- if ((byte & 0b10000000) == 0) {
- if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) result |= -(i64(1) << @intCast(u6, shift));
- ptr.* += i;
- return result;
- }
- }
-}
-
fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
const first_32_bits = try in_stream.readIntLittle(u32);
is_64.* = (first_32_bits == 0xffffffff);
@@ -2155,46 +2253,6 @@ fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool)
}
}
-fn readULeb128(in_stream: var) !u64 {
- var result: u64 = 0;
- var shift: usize = 0;
-
- while (true) {
- const byte = try in_stream.readByte();
-
- var operand: u64 = undefined;
-
- if (@shlWithOverflow(u64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
-
- result |= operand;
-
- if ((byte & 0b10000000) == 0) return result;
-
- shift += 7;
- }
-}
-
-fn readILeb128(in_stream: var) !i64 {
- var result: i64 = 0;
- var shift: usize = 0;
-
- while (true) {
- const byte = try in_stream.readByte();
-
- var operand: i64 = undefined;
-
- if (@shlWithOverflow(i64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
-
- result |= operand;
- shift += 7;
-
- if ((byte & 0b10000000) == 0) {
- if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) result |= -(i64(1) << @intCast(u6, shift));
- return result;
- }
- }
-}
-
/// This should only be used in temporary test programs.
pub const global_allocator = &global_fixed_allocator.allocator;
var global_fixed_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(global_allocator_mem[0..]);
diff --git a/std/debug/failing_allocator.zig b/std/debug/failing_allocator.zig
index 7a89460513..5776d23194 100644
--- a/std/debug/failing_allocator.zig
+++ b/std/debug/failing_allocator.zig
@@ -10,6 +10,7 @@ pub const FailingAllocator = struct {
internal_allocator: *mem.Allocator,
allocated_bytes: usize,
freed_bytes: usize,
+ allocations: usize,
deallocations: usize,
pub fn init(allocator: *mem.Allocator, fail_index: usize) FailingAllocator {
@@ -19,6 +20,7 @@ pub const FailingAllocator = struct {
.index = 0,
.allocated_bytes = 0,
.freed_bytes = 0,
+ .allocations = 0,
.deallocations = 0,
.allocator = mem.Allocator{
.reallocFn = realloc,
@@ -39,19 +41,25 @@ pub const FailingAllocator = struct {
new_size,
new_align,
);
- if (new_size <= old_mem.len) {
+ if (new_size < old_mem.len) {
self.freed_bytes += old_mem.len - new_size;
- } else {
+ if (new_size == 0)
+ self.deallocations += 1;
+ } else if (new_size > old_mem.len) {
self.allocated_bytes += new_size - old_mem.len;
+ if (old_mem.len == 0)
+ self.allocations += 1;
}
- self.deallocations += 1;
self.index += 1;
return result;
}
fn shrink(allocator: *mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
- self.freed_bytes += old_mem.len - new_size;
- return self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align);
+ const r = self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align);
+ self.freed_bytes += old_mem.len - r.len;
+ if (new_size == 0)
+ self.deallocations += 1;
+ return r;
}
};
diff --git a/std/debug/leb128.zig b/std/debug/leb128.zig
new file mode 100644
index 0000000000..2801877839
--- /dev/null
+++ b/std/debug/leb128.zig
@@ -0,0 +1,228 @@
+const std = @import("std");
+const testing = std.testing;
+
+pub fn readULEB128(comptime T: type, in_stream: var) !T {
+ const ShiftT = @IntType(false, std.math.log2(T.bit_count));
+
+ var result: T = 0;
+ var shift: usize = 0;
+
+ while (true) {
+ const byte = try in_stream.readByte();
+
+ if (shift > T.bit_count)
+ return error.Overflow;
+
+ var operand: T = undefined;
+ if (@shlWithOverflow(T, byte & 0x7f, @intCast(ShiftT, shift), &operand))
+ return error.Overflow;
+
+ result |= operand;
+
+ if ((byte & 0x80) == 0)
+ return result;
+
+ shift += 7;
+ }
+}
+
+pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
+ const ShiftT = @IntType(false, std.math.log2(T.bit_count));
+
+ var result: T = 0;
+ var shift: usize = 0;
+ var i: usize = 0;
+
+ while (true) : (i += 1) {
+ const byte = ptr.*[i];
+
+ if (shift > T.bit_count)
+ return error.Overflow;
+
+ var operand: T = undefined;
+ if (@shlWithOverflow(T, byte & 0x7f, @intCast(ShiftT, shift), &operand))
+ return error.Overflow;
+
+ result |= operand;
+
+ if ((byte & 0x80) == 0) {
+ ptr.* += i;
+ return result;
+ }
+
+ shift += 7;
+ }
+}
+
+pub fn readILEB128(comptime T: type, in_stream: var) !T {
+ const UT = @IntType(false, T.bit_count);
+ const ShiftT = @IntType(false, std.math.log2(T.bit_count));
+
+ var result: UT = 0;
+ var shift: usize = 0;
+
+ while (true) {
+ const byte = u8(try in_stream.readByte());
+
+ if (shift > T.bit_count)
+ return error.Overflow;
+
+ var operand: UT = undefined;
+ if (@shlWithOverflow(UT, UT(byte & 0x7f), @intCast(ShiftT, shift), &operand)) {
+ if (byte != 0x7f)
+ return error.Overflow;
+ }
+
+ result |= operand;
+
+ shift += 7;
+
+ if ((byte & 0x80) == 0) {
+ if (shift < T.bit_count and (byte & 0x40) != 0) {
+ result |= @bitCast(UT, @intCast(T, -1)) << @intCast(ShiftT, shift);
+ }
+ return @bitCast(T, result);
+ }
+ }
+}
+
+pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
+ const UT = @IntType(false, T.bit_count);
+ const ShiftT = @IntType(false, std.math.log2(T.bit_count));
+
+ var result: UT = 0;
+ var shift: usize = 0;
+ var i: usize = 0;
+
+ while (true) : (i += 1) {
+ const byte = ptr.*[i];
+
+ if (shift > T.bit_count)
+ return error.Overflow;
+
+ var operand: UT = undefined;
+ if (@shlWithOverflow(UT, UT(byte & 0x7f), @intCast(ShiftT, shift), &operand)) {
+ if (byte != 0x7f)
+ return error.Overflow;
+ }
+
+ result |= operand;
+
+ shift += 7;
+
+ if ((byte & 0x80) == 0) {
+ if (shift < T.bit_count and (byte & 0x40) != 0) {
+ result |= @bitCast(UT, @intCast(T, -1)) << @intCast(ShiftT, shift);
+ }
+ ptr.* += i;
+ return @bitCast(T, result);
+ }
+ }
+}
+
+fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T {
+ var in_stream = std.io.SliceInStream.init(encoded);
+ return try readILEB128(T, &in_stream.stream);
+}
+
+fn test_read_stream_uleb128(comptime T: type, encoded: []const u8) !T {
+ var in_stream = std.io.SliceInStream.init(encoded);
+ return try readULEB128(T, &in_stream.stream);
+}
+
+fn test_read_ileb128(comptime T: type, encoded: []const u8) !T {
+ var in_stream = std.io.SliceInStream.init(encoded);
+ const v1 = readILEB128(T, &in_stream.stream);
+ var in_ptr = encoded.ptr;
+ const v2 = readILEB128Mem(T, &in_ptr);
+ testing.expectEqual(v1, v2);
+ return v1;
+}
+
+fn test_read_uleb128(comptime T: type, encoded: []const u8) !T {
+ var in_stream = std.io.SliceInStream.init(encoded);
+ const v1 = readULEB128(T, &in_stream.stream);
+ var in_ptr = encoded.ptr;
+ const v2 = readULEB128Mem(T, &in_ptr);
+ testing.expectEqual(v1, v2);
+ return v1;
+}
+
+test "deserialize signed LEB128" {
+ // Truncated
+ testing.expectError(error.EndOfStream, test_read_stream_ileb128(i64, "\x80"));
+
+ // Overflow
+ testing.expectError(error.Overflow, test_read_ileb128(i8, "\x80\x80\x40"));
+ testing.expectError(error.Overflow, test_read_ileb128(i16, "\x80\x80\x80\x40"));
+ testing.expectError(error.Overflow, test_read_ileb128(i32, "\x80\x80\x80\x80\x40"));
+ testing.expectError(error.Overflow, test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40"));
+ testing.expectError(error.Overflow, test_read_ileb128(i8, "\xff\x7e"));
+
+ // Decode SLEB128
+ testing.expect((try test_read_ileb128(i64, "\x00")) == 0);
+ testing.expect((try test_read_ileb128(i64, "\x01")) == 1);
+ testing.expect((try test_read_ileb128(i64, "\x3f")) == 63);
+ testing.expect((try test_read_ileb128(i64, "\x40")) == -64);
+ testing.expect((try test_read_ileb128(i64, "\x41")) == -63);
+ testing.expect((try test_read_ileb128(i64, "\x7f")) == -1);
+ testing.expect((try test_read_ileb128(i64, "\x80\x01")) == 128);
+ testing.expect((try test_read_ileb128(i64, "\x81\x01")) == 129);
+ testing.expect((try test_read_ileb128(i64, "\xff\x7e")) == -129);
+ testing.expect((try test_read_ileb128(i64, "\x80\x7f")) == -128);
+ testing.expect((try test_read_ileb128(i64, "\x81\x7f")) == -127);
+ testing.expect((try test_read_ileb128(i64, "\xc0\x00")) == 64);
+ testing.expect((try test_read_ileb128(i64, "\xc7\x9f\x7f")) == -12345);
+ testing.expect((try test_read_ileb128(i8, "\xff\x7f")) == -1);
+ testing.expect((try test_read_ileb128(i16, "\xff\xff\x7f")) == -1);
+ testing.expect((try test_read_ileb128(i32, "\xff\xff\xff\xff\x7f")) == -1);
+ testing.expect((try test_read_ileb128(i32, "\x80\x80\x80\x80\x08")) == -0x80000000);
+ testing.expect((try test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01")) == @bitCast(i64, @intCast(u64, 0x8000000000000000)));
+ testing.expect((try test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x40")) == -0x4000000000000000);
+ testing.expect((try test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x7f")) == -0x8000000000000000);
+
+ // Decode unnormalized SLEB128 with extra padding bytes.
+ testing.expect((try test_read_ileb128(i64, "\x80\x00")) == 0);
+ testing.expect((try test_read_ileb128(i64, "\x80\x80\x00")) == 0);
+ testing.expect((try test_read_ileb128(i64, "\xff\x00")) == 0x7f);
+ testing.expect((try test_read_ileb128(i64, "\xff\x80\x00")) == 0x7f);
+ testing.expect((try test_read_ileb128(i64, "\x80\x81\x00")) == 0x80);
+ testing.expect((try test_read_ileb128(i64, "\x80\x81\x80\x00")) == 0x80);
+}
+
+test "deserialize unsigned LEB128" {
+ // Truncated
+ testing.expectError(error.EndOfStream, test_read_stream_uleb128(u64, "\x80"));
+
+ // Overflow
+ testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x02"));
+ testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x80\x40"));
+ testing.expectError(error.Overflow, test_read_uleb128(u16, "\x80\x80\x84"));
+ testing.expectError(error.Overflow, test_read_uleb128(u16, "\x80\x80\x80\x40"));
+ testing.expectError(error.Overflow, test_read_uleb128(u32, "\x80\x80\x80\x80\x90"));
+ testing.expectError(error.Overflow, test_read_uleb128(u32, "\x80\x80\x80\x80\x40"));
+ testing.expectError(error.Overflow, test_read_uleb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40"));
+
+ // Decode ULEB128
+ testing.expect((try test_read_uleb128(u64, "\x00")) == 0);
+ testing.expect((try test_read_uleb128(u64, "\x01")) == 1);
+ testing.expect((try test_read_uleb128(u64, "\x3f")) == 63);
+ testing.expect((try test_read_uleb128(u64, "\x40")) == 64);
+ testing.expect((try test_read_uleb128(u64, "\x7f")) == 0x7f);
+ testing.expect((try test_read_uleb128(u64, "\x80\x01")) == 0x80);
+ testing.expect((try test_read_uleb128(u64, "\x81\x01")) == 0x81);
+ testing.expect((try test_read_uleb128(u64, "\x90\x01")) == 0x90);
+ testing.expect((try test_read_uleb128(u64, "\xff\x01")) == 0xff);
+ testing.expect((try test_read_uleb128(u64, "\x80\x02")) == 0x100);
+ testing.expect((try test_read_uleb128(u64, "\x81\x02")) == 0x101);
+ testing.expect((try test_read_uleb128(u64, "\x80\xc1\x80\x80\x10")) == 4294975616);
+ testing.expect((try test_read_uleb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01")) == 0x8000000000000000);
+
+ // Decode ULEB128 with extra padding bytes
+ testing.expect((try test_read_uleb128(u64, "\x80\x00")) == 0);
+ testing.expect((try test_read_uleb128(u64, "\x80\x80\x00")) == 0);
+ testing.expect((try test_read_uleb128(u64, "\xff\x00")) == 0x7f);
+ testing.expect((try test_read_uleb128(u64, "\xff\x80\x00")) == 0x7f);
+ testing.expect((try test_read_uleb128(u64, "\x80\x81\x00")) == 0x80);
+ testing.expect((try test_read_uleb128(u64, "\x80\x81\x80\x00")) == 0x80);
+}
diff --git a/std/dwarf.zig b/std/dwarf.zig
index 2cf8ed953e..2f3b29302d 100644
--- a/std/dwarf.zig
+++ b/std/dwarf.zig
@@ -13,6 +13,7 @@ pub const TAG_reference_type = 0x10;
pub const TAG_compile_unit = 0x11;
pub const TAG_string_type = 0x12;
pub const TAG_structure_type = 0x13;
+pub const TAG_subroutine = 0x14;
pub const TAG_subroutine_type = 0x15;
pub const TAG_typedef = 0x16;
pub const TAG_union_type = 0x17;
@@ -241,6 +242,9 @@ pub const AT_const_expr = 0x6c;
pub const AT_enum_class = 0x6d;
pub const AT_linkage_name = 0x6e;
+// DWARF 5
+pub const AT_alignment = 0x88;
+
pub const AT_lo_user = 0x2000; // Implementation-defined range start.
pub const AT_hi_user = 0x3fff; // Implementation-defined range end.
diff --git a/std/dynamic_library.zig b/std/dynamic_library.zig
index 698b0eb216..b2064311db 100644
--- a/std/dynamic_library.zig
+++ b/std/dynamic_library.zig
@@ -19,6 +19,89 @@ pub const DynLib = switch (builtin.os) {
else => void,
};
+// The link_map structure is not completely specified beside the fields
+// reported below, any libc is free to store additional data in the remaining
+// space.
+// An iterator is provided in order to traverse the linked list in a idiomatic
+// fashion.
+const LinkMap = extern struct {
+ l_addr: usize,
+ l_name: [*]const u8,
+ l_ld: ?*elf.Dyn,
+ l_next: ?*LinkMap,
+ l_prev: ?*LinkMap,
+
+ pub const Iterator = struct {
+ current: ?*LinkMap,
+
+ fn end(self: *Iterator) bool {
+ return self.current == null;
+ }
+
+ fn next(self: *Iterator) ?*LinkMap {
+ if (self.current) |it| {
+ self.current = it.l_next;
+ return it;
+ }
+ return null;
+ }
+ };
+};
+
+const RDebug = extern struct {
+ r_version: i32,
+ r_map: ?*LinkMap,
+ r_brk: usize,
+ r_ldbase: usize,
+};
+
+fn elf_get_va_offset(phdrs: []elf.Phdr) !usize {
+ for (phdrs) |*phdr| {
+ if (phdr.p_type == elf.PT_LOAD) {
+ return @ptrToInt(phdr) - phdr.p_vaddr;
+ }
+ }
+ return error.InvalidExe;
+}
+
+pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
+ const va_offset = try elf_get_va_offset(phdrs);
+
+ const dyn_table = init: {
+ for (phdrs) |*phdr| {
+ if (phdr.p_type == elf.PT_DYNAMIC) {
+ const ptr = @intToPtr([*]elf.Dyn, va_offset + phdr.p_vaddr);
+ break :init ptr[0..phdr.p_memsz / @sizeOf(elf.Dyn)];
+ }
+ }
+ // No PT_DYNAMIC means this is either a statically-linked program or a
+ // badly corrupted one
+ return LinkMap.Iterator{.current = null};
+ };
+
+ const link_map_ptr = init: {
+ for (dyn_table) |*dyn| {
+ switch (dyn.d_tag) {
+ elf.DT_DEBUG => {
+ const r_debug = @intToPtr(*RDebug, dyn.d_un.d_ptr);
+ if (r_debug.r_version != 1) return error.InvalidExe;
+ break :init r_debug.r_map;
+ },
+ elf.DT_PLTGOT => {
+ const got_table = @intToPtr([*]usize, dyn.d_un.d_ptr);
+ // The address to the link_map structure is stored in the
+ // second slot
+ break :init @intToPtr(?*LinkMap, got_table[1]);
+ },
+ else => { }
+ }
+ }
+ return error.InvalidExe;
+ };
+
+ return LinkMap.Iterator{.current = link_map_ptr};
+}
+
pub const LinuxDynLib = struct {
elf_lib: ElfLib,
fd: i32,
diff --git a/std/elf.zig b/std/elf.zig
index d0ec5fb2ae..49f2f7d137 100644
--- a/std/elf.zig
+++ b/std/elf.zig
@@ -877,6 +877,11 @@ pub const Phdr = switch (@sizeOf(usize)) {
8 => Elf64_Phdr,
else => @compileError("expected pointer size of 32 or 64"),
};
+pub const Dyn = switch (@sizeOf(usize)) {
+ 4 => Elf32_Dyn,
+ 8 => Elf64_Dyn,
+ else => @compileError("expected pointer size of 32 or 64"),
+};
pub const Shdr = switch (@sizeOf(usize)) {
4 => Elf32_Shdr,
8 => Elf64_Shdr,
diff --git a/std/fmt.zig b/std/fmt.zig
index 6402271563..e4738d430d 100644
--- a/std/fmt.zig
+++ b/std/fmt.zig
@@ -8,6 +8,8 @@ const builtin = @import("builtin");
const errol = @import("fmt/errol.zig");
const lossyCast = std.math.lossyCast;
+pub const default_max_depth = 3;
+
/// Renders fmt string with args, calling output with slices of bytes.
/// If `output` returns an error, the error is returned from `format` and
/// `output` is not called again.
@@ -49,7 +51,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
start_index = i;
},
'}' => {
- try formatType(args[next_arg], fmt[0..0], context, Errors, output);
+ try formatType(args[next_arg], fmt[0..0], context, Errors, output, default_max_depth);
next_arg += 1;
state = State.Start;
start_index = i + 1;
@@ -69,7 +71,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
State.FormatString => switch (c) {
'}' => {
const s = start_index + 1;
- try formatType(args[next_arg], fmt[s..i], context, Errors, output);
+ try formatType(args[next_arg], fmt[s..i], context, Errors, output, default_max_depth);
next_arg += 1;
state = State.Start;
start_index = i + 1;
@@ -108,6 +110,7 @@ pub fn formatType(
context: var,
comptime Errors: type,
output: fn (@typeOf(context), []const u8) Errors!void,
+ max_depth: usize,
) Errors!void {
const T = @typeOf(value);
switch (@typeInfo(T)) {
@@ -122,16 +125,16 @@ pub fn formatType(
},
builtin.TypeId.Optional => {
if (value) |payload| {
- return formatType(payload, fmt, context, Errors, output);
+ return formatType(payload, fmt, context, Errors, output, max_depth);
} else {
return output(context, "null");
}
},
builtin.TypeId.ErrorUnion => {
if (value) |payload| {
- return formatType(payload, fmt, context, Errors, output);
+ return formatType(payload, fmt, context, Errors, output, max_depth);
} else |err| {
- return formatType(err, fmt, context, Errors, output);
+ return formatType(err, fmt, context, Errors, output, max_depth);
}
},
builtin.TypeId.ErrorSet => {
@@ -164,10 +167,13 @@ pub fn formatType(
switch (comptime @typeId(T)) {
builtin.TypeId.Enum => {
try output(context, ".");
- try formatType(@tagName(value), "", context, Errors, output);
+ try formatType(@tagName(value), "", context, Errors, output, max_depth);
return;
},
builtin.TypeId.Struct => {
+ if (max_depth == 0) {
+ return output(context, "{ ... }");
+ }
comptime var field_i = 0;
inline while (field_i < @memberCount(T)) : (field_i += 1) {
if (field_i == 0) {
@@ -177,11 +183,14 @@ pub fn formatType(
}
try output(context, @memberName(T, field_i));
try output(context, " = ");
- try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output);
+ try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output, max_depth-1);
}
try output(context, " }");
},
builtin.TypeId.Union => {
+ if (max_depth == 0) {
+ return output(context, "{ ... }");
+ }
const info = @typeInfo(T).Union;
if (info.tag_type) |UnionTagType| {
try output(context, "{ .");
@@ -189,7 +198,7 @@ pub fn formatType(
try output(context, " = ");
inline for (info.fields) |u_field| {
if (@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) {
- try formatType(@field(value, u_field.name), "", context, Errors, output);
+ try formatType(@field(value, u_field.name), "", context, Errors, output, max_depth-1);
}
}
try output(context, " }");
@@ -210,7 +219,7 @@ pub fn formatType(
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
},
builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
- return formatType(value.*, fmt, context, Errors, output);
+ return formatType(value.*, fmt, context, Errors, output, max_depth);
},
else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),
},
@@ -986,17 +995,17 @@ test "fmt.format" {
{
var buf1: [32]u8 = undefined;
var context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite);
+ try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
var res = buf1[0 .. buf1.len - context.remaining.len];
testing.expect(mem.eql(u8, res, "1234"));
context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);
+ try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
res = buf1[0 .. buf1.len - context.remaining.len];
testing.expect(mem.eql(u8, res, "a"));
context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);
+ try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
res = buf1[0 .. buf1.len - context.remaining.len];
testing.expect(mem.eql(u8, res, "1100"));
}
@@ -1364,6 +1373,20 @@ test "fmt.format" {
try testFmt("E.Two", "{}", inst);
}
+ //self-referential struct format
+ {
+ const S = struct {
+ const SelfType = @This();
+ a: ?*SelfType,
+ };
+
+ var inst = S{
+ .a = null,
+ };
+ inst.a = &inst;
+
+ try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst);
+ }
//print bytes as hex
{
const some_bytes = "\xCA\xFE\xBA\xBE";
@@ -1449,3 +1472,64 @@ test "fmt.formatIntValue with comptime_int" {
try formatIntValue(value, "", &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);
assert(mem.eql(u8, buf.toSlice(), "123456789123456789"));
}
+
+test "fmt.formatType max_depth" {
+ const Vec2 = struct {
+ const SelfType = @This();
+ x: f32,
+ y: f32,
+
+ pub fn format(
+ self: SelfType,
+ comptime fmt: []const u8,
+ context: var,
+ comptime Errors: type,
+ output: fn (@typeOf(context), []const u8) Errors!void,
+ ) Errors!void {
+ return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y);
+ }
+ };
+ const E = enum {
+ One,
+ Two,
+ Three,
+ };
+ const TU = union(enum) {
+ const SelfType = @This();
+ float: f32,
+ int: u32,
+ ptr: ?*SelfType,
+ };
+ const S = struct {
+ const SelfType = @This();
+ a: ?*SelfType,
+ tu: TU,
+ e: E,
+ vec: Vec2,
+ };
+
+ var inst = S{
+ .a = null,
+ .tu = TU{ .ptr = null },
+ .e = E.Two,
+ .vec = Vec2{ .x = 10.2, .y = 2.22 },
+ };
+ inst.a = &inst;
+ inst.tu.ptr = &inst.tu;
+
+ var buf0 = try std.Buffer.init(std.debug.global_allocator, "");
+ try formatType(inst, "", &buf0, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0);
+ assert(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
+
+ var buf1 = try std.Buffer.init(std.debug.global_allocator, "");
+ try formatType(inst, "", &buf1, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1);
+ assert(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
+
+ var buf2 = try std.Buffer.init(std.debug.global_allocator, "");
+ try formatType(inst, "", &buf2, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2);
+ assert(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
+
+ var buf3 = try std.Buffer.init(std.debug.global_allocator, "");
+ try formatType(inst, "", &buf3, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3);
+ assert(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
+}
diff --git a/std/hash_map.zig b/std/hash_map.zig
index f4c0b87167..9cd1ea052c 100644
--- a/std/hash_map.zig
+++ b/std/hash_map.zig
@@ -118,7 +118,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
};
}
self.incrementModificationCount();
- try self.ensureCapacity();
+ try self.autoCapacity();
const put_result = self.internalPut(key);
assert(put_result.old_kv == null);
return GetOrPutResult{
@@ -135,15 +135,37 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
return res.kv;
}
- fn ensureCapacity(self: *Self) !void {
- if (self.entries.len == 0) {
- return self.initCapacity(16);
+ fn optimizedCapacity(expected_count: usize) usize {
+ // ensure that the hash map will be at most 60% full if
+ // expected_count items are put into it
+ var optimized_capacity = expected_count * 5 / 3;
+ // round capacity to the next power of two
+ const pow = math.log2_int_ceil(usize, optimized_capacity);
+ return math.pow(usize, 2, pow);
+ }
+
+ /// Increases capacity so that the hash map will be at most
+ /// 60% full when expected_count items are put into it
+ pub fn ensureCapacity(self: *Self, expected_count: usize) !void {
+ const optimized_capacity = optimizedCapacity(expected_count);
+ return self.ensureCapacityExact(optimized_capacity);
+ }
+
+ /// Sets the capacity to the new capacity if the new
+ /// capacity is greater than the current capacity.
+ /// New capacity must be a power of two.
+ fn ensureCapacityExact(self: *Self, new_capacity: usize) !void {
+ const is_power_of_two = new_capacity & (new_capacity-1) == 0;
+ assert(is_power_of_two);
+
+ if (new_capacity <= self.entries.len) {
+ return;
}
- // if we get too full (60%), double the capacity
- if (self.size * 5 >= self.entries.len * 3) {
- const old_entries = self.entries;
- try self.initCapacity(self.entries.len * 2);
+ const old_entries = self.entries;
+ try self.initCapacity(new_capacity);
+ self.incrementModificationCount();
+ if (old_entries.len > 0) {
// dump all of the old elements into the new table
for (old_entries) |*old_entry| {
if (old_entry.used) {
@@ -156,8 +178,13 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
/// Returns the kv pair that was already there.
pub fn put(self: *Self, key: K, value: V) !?KV {
+ try self.autoCapacity();
+ return putAssumeCapacity(self, key, value);
+ }
+
+ pub fn putAssumeCapacity(self: *Self, key: K, value: V) ?KV {
+ assert(self.count() < self.entries.len);
self.incrementModificationCount();
- try self.ensureCapacity();
const put_result = self.internalPut(key);
put_result.new_entry.kv.value = value;
@@ -175,7 +202,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
return hm.get(key) != null;
}
- pub fn remove(hm: *Self, key: K) ?*KV {
+ pub fn remove(hm: *Self, key: K) ?KV {
if (hm.entries.len == 0) return null;
hm.incrementModificationCount();
const start_index = hm.keyToIndex(key);
@@ -189,13 +216,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
if (!eql(entry.kv.key, key)) continue;
+ const removed_kv = entry.kv;
while (roll_over < hm.entries.len) : (roll_over += 1) {
const next_index = (start_index + roll_over + 1) % hm.entries.len;
const next_entry = &hm.entries[next_index];
if (!next_entry.used or next_entry.distance_from_start_index == 0) {
entry.used = false;
hm.size -= 1;
- return &entry.kv;
+ return removed_kv;
}
entry.* = next_entry.*;
entry.distance_from_start_index -= 1;
@@ -226,6 +254,16 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
return other;
}
+ fn autoCapacity(self: *Self) !void {
+ if (self.entries.len == 0) {
+ return self.ensureCapacityExact(16);
+ }
+ // if we get too full (60%), double the capacity
+ if (self.size * 5 >= self.entries.len * 3) {
+ return self.ensureCapacityExact(self.entries.len * 2);
+ }
+ }
+
fn initCapacity(hm: *Self, capacity: usize) !void {
hm.entries = try hm.allocator.alloc(Entry, capacity);
hm.size = 0;
@@ -371,7 +409,10 @@ test "basic hash map usage" {
testing.expect(map.contains(2));
testing.expect(map.get(2).?.value == 22);
- _ = map.remove(2);
+
+ const rmv1 = map.remove(2);
+ testing.expect(rmv1.?.key == 2);
+ testing.expect(rmv1.?.value == 22);
testing.expect(map.remove(2) == null);
testing.expect(map.get(2) == null);
}
@@ -423,6 +464,24 @@ test "iterator hash map" {
testing.expect(entry.value == values[0]);
}
+test "ensure capacity" {
+ var direct_allocator = std.heap.DirectAllocator.init();
+ defer direct_allocator.deinit();
+
+ var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
+ defer map.deinit();
+
+ try map.ensureCapacity(20);
+ const initialCapacity = map.entries.len;
+ testing.expect(initialCapacity >= 20);
+ var i : i32 = 0;
+ while (i < 20) : (i += 1) {
+ testing.expect(map.putAssumeCapacity(i, i+10) == null);
+ }
+ // shouldn't resize from putAssumeCapacity
+ testing.expect(initialCapacity == map.entries.len);
+}
+
pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) {
return struct {
fn hash(key: K) u32 {
diff --git a/std/heap.zig b/std/heap.zig
index dd5cfa4cd7..8e3cccc365 100644
--- a/std/heap.zig
+++ b/std/heap.zig
@@ -34,9 +34,6 @@ fn cShrink(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new
/// Thread-safe and lock-free.
pub const DirectAllocator = struct {
allocator: Allocator,
- heap_handle: ?HeapHandle,
-
- const HeapHandle = if (builtin.os == Os.windows) os.windows.HANDLE else void;
pub fn init() DirectAllocator {
return DirectAllocator{
@@ -44,21 +41,15 @@ pub const DirectAllocator = struct {
.reallocFn = realloc,
.shrinkFn = shrink,
},
- .heap_handle = if (builtin.os == Os.windows) null else {},
};
}
- pub fn deinit(self: *DirectAllocator) void {
- switch (builtin.os) {
- Os.windows => if (self.heap_handle) |heap_handle| {
- _ = os.windows.HeapDestroy(heap_handle);
- },
- else => {},
- }
- }
+ pub fn deinit(self: *DirectAllocator) void {}
fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
+ if (n == 0)
+ return (([*]u8)(undefined))[0..0];
switch (builtin.os) {
Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
@@ -68,39 +59,76 @@ pub const DirectAllocator = struct {
if (addr == p.MAP_FAILED) return error.OutOfMemory;
if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];
- const aligned_addr = (addr & ~usize(alignment - 1)) + alignment;
-
- // We can unmap the unused portions of our mmap, but we must only
- // pass munmap bytes that exist outside our allocated pages or it
- // will happily eat us too.
-
- // Since alignment > page_size, we are by definition on a page boundary.
- const unused_start = addr;
- const unused_len = aligned_addr - 1 - unused_start;
-
- const err = p.munmap(unused_start, unused_len);
- assert(p.getErrno(err) == 0);
+ const aligned_addr = mem.alignForward(addr, alignment);
- // It is impossible that there is an unoccupied page at the top of our
- // mmap.
+ // Unmap the extra bytes that were only requested in order to guarantee
+ // that the range of memory we were provided had a proper alignment in
+ // it somewhere. The extra bytes could be at the beginning, or end, or both.
+ const unused_start_len = aligned_addr - addr;
+ if (unused_start_len != 0) {
+ const err = p.munmap(addr, unused_start_len);
+ assert(p.getErrno(err) == 0);
+ }
+ const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size);
+ const unused_end_len = addr + alloc_size - aligned_end_addr;
+ if (unused_end_len != 0) {
+ const err = p.munmap(aligned_end_addr, unused_end_len);
+ assert(p.getErrno(err) == 0);
+ }
return @intToPtr([*]u8, aligned_addr)[0..n];
},
- Os.windows => {
- const amt = n + alignment + @sizeOf(usize);
- const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, builtin.AtomicOrder.SeqCst);
- const heap_handle = optional_heap_handle orelse blk: {
- const hh = os.windows.HeapCreate(0, amt, 0) orelse return error.OutOfMemory;
- const other_hh = @cmpxchgStrong(?HeapHandle, &self.heap_handle, null, hh, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse break :blk hh;
- _ = os.windows.HeapDestroy(hh);
- break :blk other_hh.?; // can't be null because of the cmpxchg
- };
- const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory;
- const root_addr = @ptrToInt(ptr);
- const adjusted_addr = mem.alignForward(root_addr, alignment);
- const record_addr = adjusted_addr + n;
- @intToPtr(*align(1) usize, record_addr).* = root_addr;
- return @intToPtr([*]u8, adjusted_addr)[0..n];
+ .windows => {
+ const w = os.windows;
+
+ // Although officially it's at least aligned to page boundary,
+ // Windows is known to reserve pages on a 64K boundary. It's
+ // even more likely that the requested alignment is <= 64K than
+ // 4K, so we're just allocating blindly and hoping for the best.
+ // see https://devblogs.microsoft.com/oldnewthing/?p=42223
+ const addr = w.VirtualAlloc(
+ null,
+ n,
+ w.MEM_COMMIT | w.MEM_RESERVE,
+ w.PAGE_READWRITE,
+ ) orelse return error.OutOfMemory;
+
+ // If the allocation is sufficiently aligned, use it.
+ if (@ptrToInt(addr) & (alignment - 1) == 0) {
+ return @ptrCast([*]u8, addr)[0..n];
+ }
+
+ // If it wasn't, actually do an explicitely aligned allocation.
+ if (w.VirtualFree(addr, 0, w.MEM_RELEASE) == 0) unreachable;
+ const alloc_size = n + alignment;
+
+ const final_addr = while (true) {
+ // Reserve a range of memory large enough to find a sufficiently
+ // aligned address.
+ const reserved_addr = w.VirtualAlloc(
+ null,
+ alloc_size,
+ w.MEM_RESERVE,
+ w.PAGE_NOACCESS,
+ ) orelse return error.OutOfMemory;
+ const aligned_addr = mem.alignForward(@ptrToInt(reserved_addr), alignment);
+
+ // Release the reserved pages (not actually used).
+ if (w.VirtualFree(reserved_addr, 0, w.MEM_RELEASE) == 0) unreachable;
+
+ // At this point, it is possible that another thread has
+ // obtained some memory space that will cause the next
+ // VirtualAlloc call to fail. To handle this, we will retry
+ // until it succeeds.
+ if (w.VirtualAlloc(
+ @intToPtr(*c_void, aligned_addr),
+ n,
+ w.MEM_COMMIT | w.MEM_RESERVE,
+ w.PAGE_READWRITE,
+ )) |ptr| break ptr;
+ } else unreachable; // TODO else unreachable should not be necessary
+
+ return @ptrCast([*]u8, final_addr)[0..n];
},
else => @compileError("Unsupported OS"),
}
@@ -118,13 +146,31 @@ pub const DirectAllocator = struct {
}
return old_mem[0..new_size];
},
- Os.windows => return realloc(allocator, old_mem, old_align, new_size, new_align) catch {
- const old_adjusted_addr = @ptrToInt(old_mem.ptr);
- const old_record_addr = old_adjusted_addr + old_mem.len;
- const root_addr = @intToPtr(*align(1) usize, old_record_addr).*;
- const old_ptr = @intToPtr(*c_void, root_addr);
- const new_record_addr = old_record_addr - new_size + old_mem.len;
- @intToPtr(*align(1) usize, new_record_addr).* = root_addr;
+ .windows => {
+ const w = os.windows;
+ if (new_size == 0) {
+ // From the docs:
+ // "If the dwFreeType parameter is MEM_RELEASE, this parameter
+ // must be 0 (zero). The function frees the entire region that
+ // is reserved in the initial allocation call to VirtualAlloc."
+ // So we can only use MEM_RELEASE when actually releasing the
+ // whole allocation.
+ if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
+ } else {
+ const base_addr = @ptrToInt(old_mem.ptr);
+ const old_addr_end = base_addr + old_mem.len;
+ const new_addr_end = base_addr + new_size;
+ const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
+ if (old_addr_end > new_addr_end_rounded) {
+ // For shrinking that is not releasing, we will only
+ // decommit the pages not needed anymore.
+ if (w.VirtualFree(
+ @intToPtr(*c_void, new_addr_end_rounded),
+ old_addr_end - new_addr_end_rounded,
+ w.MEM_DECOMMIT,
+ ) == 0) unreachable;
+ }
+ }
return old_mem[0..new_size];
},
else => @compileError("Unsupported OS"),
@@ -138,36 +184,168 @@ pub const DirectAllocator = struct {
return shrink(allocator, old_mem, old_align, new_size, new_align);
}
const result = try alloc(allocator, new_size, new_align);
- mem.copy(u8, result, old_mem);
- _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
+ if (old_mem.len != 0) {
+ @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
+ _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
+ }
return result;
},
- Os.windows => {
- if (old_mem.len == 0) return alloc(allocator, new_size, new_align);
+ .windows => {
+ if (old_mem.len == 0) {
+ return alloc(allocator, new_size, new_align);
+ }
+
+ if (new_size <= old_mem.len and new_align <= old_align) {
+ return shrink(allocator, old_mem, old_align, new_size, new_align);
+ }
+
+ const w = os.windows;
+ const base_addr = @ptrToInt(old_mem.ptr);
+
+ if (new_align > old_align and base_addr & (new_align - 1) != 0) {
+ // Current allocation doesn't satisfy the new alignment.
+ // For now we'll do a new one no matter what, but maybe
+ // there is something smarter to do instead.
+ const result = try alloc(allocator, new_size, new_align);
+ assert(old_mem.len != 0);
+ @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
+ if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
- const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
+ return result;
+ }
+
+ const old_addr_end = base_addr + old_mem.len;
+ const old_addr_end_rounded = mem.alignForward(old_addr_end, os.page_size);
+ const new_addr_end = base_addr + new_size;
+ const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
+ if (new_addr_end_rounded == old_addr_end_rounded) {
+ // The reallocation fits in the already allocated pages.
+ return @ptrCast([*]u8, old_mem.ptr)[0..new_size];
+ }
+ assert(new_addr_end_rounded > old_addr_end_rounded);
+
+ // We need to commit new pages.
+ const additional_size = new_addr_end - old_addr_end_rounded;
+ const realloc_addr = w.VirtualAlloc(
+ @intToPtr(*c_void, old_addr_end_rounded),
+ additional_size,
+ w.MEM_COMMIT | w.MEM_RESERVE,
+ w.PAGE_READWRITE,
+ ) orelse {
+ // Committing new pages at the end of the existing allocation
+ // failed, we need to try a new one.
+ const new_alloc_mem = try alloc(allocator, new_size, new_align);
+ @memcpy(new_alloc_mem.ptr, old_mem.ptr, old_mem.len);
+ if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
+
+ return new_alloc_mem;
+ };
+
+ assert(@ptrToInt(realloc_addr) == old_addr_end_rounded);
+ return @ptrCast([*]u8, old_mem.ptr)[0..new_size];
+ },
+ else => @compileError("Unsupported OS"),
+ }
+ }
+};
+
+pub const HeapAllocator = switch (builtin.os) {
+ .windows => struct {
+ allocator: Allocator,
+ heap_handle: ?HeapHandle,
+
+ const HeapHandle = os.windows.HANDLE;
+
+ pub fn init() HeapAllocator {
+ return HeapAllocator{
+ .allocator = Allocator{
+ .reallocFn = realloc,
+ .shrinkFn = shrink,
+ },
+ .heap_handle = null,
+ };
+ }
+
+ pub fn deinit(self: *HeapAllocator) void {
+ if (self.heap_handle) |heap_handle| {
+ _ = os.windows.HeapDestroy(heap_handle);
+ }
+ }
+
+ fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
+ const self = @fieldParentPtr(HeapAllocator, "allocator", allocator);
+ if (n == 0)
+ return (([*]u8)(undefined))[0..0];
+
+ const amt = n + alignment + @sizeOf(usize);
+ const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, builtin.AtomicOrder.SeqCst);
+ const heap_handle = optional_heap_handle orelse blk: {
+ const options = if (builtin.single_threaded) os.windows.HEAP_NO_SERIALIZE else 0;
+ const hh = os.windows.HeapCreate(options, amt, 0) orelse return error.OutOfMemory;
+ const other_hh = @cmpxchgStrong(?HeapHandle, &self.heap_handle, null, hh, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse break :blk hh;
+ _ = os.windows.HeapDestroy(hh);
+ break :blk other_hh.?; // can't be null because of the cmpxchg
+ };
+ const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory;
+ const root_addr = @ptrToInt(ptr);
+ const adjusted_addr = mem.alignForward(root_addr, alignment);
+ const record_addr = adjusted_addr + n;
+ @intToPtr(*align(1) usize, record_addr).* = root_addr;
+ return @intToPtr([*]u8, adjusted_addr)[0..n];
+ }
+
+ fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
+ return realloc(allocator, old_mem, old_align, new_size, new_align) catch {
const old_adjusted_addr = @ptrToInt(old_mem.ptr);
const old_record_addr = old_adjusted_addr + old_mem.len;
const root_addr = @intToPtr(*align(1) usize, old_record_addr).*;
const old_ptr = @intToPtr(*c_void, root_addr);
- const amt = new_size + new_align + @sizeOf(usize);
- const new_ptr = os.windows.HeapReAlloc(
- self.heap_handle.?,
- 0,
- old_ptr,
- amt,
- ) orelse return error.OutOfMemory;
- const offset = old_adjusted_addr - root_addr;
- const new_root_addr = @ptrToInt(new_ptr);
- const new_adjusted_addr = new_root_addr + offset;
- assert(new_adjusted_addr % new_align == 0);
- const new_record_addr = new_adjusted_addr + new_size;
- @intToPtr(*align(1) usize, new_record_addr).* = new_root_addr;
- return @intToPtr([*]u8, new_adjusted_addr)[0..new_size];
- },
- else => @compileError("Unsupported OS"),
+ const new_record_addr = old_record_addr - new_size + old_mem.len;
+ @intToPtr(*align(1) usize, new_record_addr).* = root_addr;
+ return old_mem[0..new_size];
+ };
}
- }
+
+ fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
+ if (old_mem.len == 0) return alloc(allocator, new_size, new_align);
+
+ const self = @fieldParentPtr(HeapAllocator, "allocator", allocator);
+ const old_adjusted_addr = @ptrToInt(old_mem.ptr);
+ const old_record_addr = old_adjusted_addr + old_mem.len;
+ const root_addr = @intToPtr(*align(1) usize, old_record_addr).*;
+ const old_ptr = @intToPtr(*c_void, root_addr);
+
+ if (new_size == 0) {
+ if (os.windows.HeapFree(self.heap_handle.?, 0, old_ptr) == 0) unreachable;
+ return old_mem[0..0];
+ }
+
+ const amt = new_size + new_align + @sizeOf(usize);
+ const new_ptr = os.windows.HeapReAlloc(
+ self.heap_handle.?,
+ 0,
+ old_ptr,
+ amt,
+ ) orelse return error.OutOfMemory;
+ const offset = old_adjusted_addr - root_addr;
+ const new_root_addr = @ptrToInt(new_ptr);
+ var new_adjusted_addr = new_root_addr + offset;
+ const offset_is_valid = new_adjusted_addr + new_size + @sizeOf(usize) <= new_root_addr + amt;
+ const offset_is_aligned = new_adjusted_addr % new_align == 0;
+ if (!offset_is_valid or !offset_is_aligned) {
+ // If HeapReAlloc didn't happen to move the memory to the new alignment,
+ // or the memory starting at the old offset would be outside of the new allocation,
+ // then we need to copy the memory to a valid aligned address and use that
+ const new_aligned_addr = mem.alignForward(new_root_addr, new_align);
+ @memcpy(@intToPtr([*]u8, new_aligned_addr), @intToPtr([*]u8, new_adjusted_addr), std.math.min(old_mem.len, new_size));
+ new_adjusted_addr = new_aligned_addr;
+ }
+ const new_record_addr = new_adjusted_addr + new_size;
+ @intToPtr(*align(1) usize, new_record_addr).* = new_root_addr;
+ return @intToPtr([*]u8, new_adjusted_addr)[0..new_size];
+ }
+ },
+ else => @compileError("Unsupported OS"),
};
/// This allocator takes an existing allocator, wraps it, and provides an interface
@@ -250,7 +428,7 @@ pub const ArenaAllocator = struct {
return error.OutOfMemory;
} else {
const result = try alloc(allocator, new_size, new_align);
- mem.copy(u8, result, old_mem);
+ @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
return result;
}
}
@@ -308,6 +486,103 @@ pub const FixedBufferAllocator = struct {
return error.OutOfMemory;
} else {
const result = try alloc(allocator, new_size, new_align);
+ @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
+ return result;
+ }
+ }
+
+ fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
+ return old_mem[0..new_size];
+ }
+};
+
+// FIXME: Exposed LLVM intrinsics is a bug
+// See: https://github.com/ziglang/zig/issues/2291
+extern fn @"llvm.wasm.memory.size.i32"(u32) u32;
+extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32;
+
+pub const wasm_allocator = &wasm_allocator_state.allocator;
+var wasm_allocator_state = WasmAllocator{
+ .allocator = Allocator{
+ .reallocFn = WasmAllocator.realloc,
+ .shrinkFn = WasmAllocator.shrink,
+ },
+ .start_ptr = undefined,
+ .num_pages = 0,
+ .end_index = 0,
+};
+
+const WasmAllocator = struct {
+ allocator: Allocator,
+ start_ptr: [*]u8,
+ num_pages: usize,
+ end_index: usize,
+
+ comptime {
+ if (builtin.arch != .wasm32) {
+ @compileError("WasmAllocator is only available for wasm32 arch");
+ }
+ }
+
+ fn alloc(allocator: *Allocator, size: usize, alignment: u29) ![]u8 {
+ const self = @fieldParentPtr(WasmAllocator, "allocator", allocator);
+
+ const addr = @ptrToInt(self.start_ptr) + self.end_index;
+ const adjusted_addr = mem.alignForward(addr, alignment);
+ const adjusted_index = self.end_index + (adjusted_addr - addr);
+ const new_end_index = adjusted_index + size;
+
+ if (new_end_index > self.num_pages * os.page_size) {
+ const required_memory = new_end_index - (self.num_pages * os.page_size);
+
+ var num_pages: usize = required_memory / os.page_size;
+ if (required_memory % os.page_size != 0) {
+ num_pages += 1;
+ }
+
+ const prev_page = @"llvm.wasm.memory.grow.i32"(0, @intCast(u32, num_pages));
+ if (prev_page == -1) {
+ return error.OutOfMemory;
+ }
+
+ self.num_pages += num_pages;
+ }
+
+ const result = self.start_ptr[adjusted_index..new_end_index];
+ self.end_index = new_end_index;
+
+ return result;
+ }
+
+ // Check if memory is the last "item" and is aligned correctly
+ fn is_last_item(allocator: *Allocator, memory: []u8, alignment: u29) bool {
+ const self = @fieldParentPtr(WasmAllocator, "allocator", allocator);
+ return memory.ptr == self.start_ptr + self.end_index - memory.len and mem.alignForward(@ptrToInt(memory.ptr), alignment) == @ptrToInt(memory.ptr);
+ }
+
+ fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
+ const self = @fieldParentPtr(WasmAllocator, "allocator", allocator);
+
+ // Initialize start_ptr at the first realloc
+ if (self.num_pages == 0) {
+ self.start_ptr = @intToPtr([*]u8, @intCast(usize, @"llvm.wasm.memory.size.i32"(0)) * os.page_size);
+ }
+
+ if (is_last_item(allocator, old_mem, new_align)) {
+ const start_index = self.end_index - old_mem.len;
+ const new_end_index = start_index + new_size;
+
+ if (new_end_index > self.num_pages * os.page_size) {
+ _ = try alloc(allocator, new_end_index - self.end_index, new_align);
+ }
+ const result = self.start_ptr[start_index..new_end_index];
+
+ self.end_index = new_end_index;
+ return result;
+ } else if (new_size <= old_mem.len and new_align <= old_align) {
+ return error.OutOfMemory;
+ } else {
+ const result = try alloc(allocator, new_size, new_align);
mem.copy(u8, result, old_mem);
return result;
}
@@ -360,7 +635,7 @@ pub const ThreadSafeFixedBufferAllocator = blk: {
return error.OutOfMemory;
} else {
const result = try alloc(allocator, new_size, new_align);
- mem.copy(u8, result, old_mem);
+ @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
return result;
}
}
@@ -470,6 +745,31 @@ test "DirectAllocator" {
try testAllocator(allocator);
try testAllocatorAligned(allocator, 16);
try testAllocatorLargeAlignment(allocator);
+ try testAllocatorAlignedShrink(allocator);
+
+ if (builtin.os == .windows) {
+ // Trying really large alignment. As mentionned in the implementation,
+ // VirtualAlloc returns 64K aligned addresses. We want to make sure
+ // DirectAllocator works beyond that, as it's not tested by
+ // `testAllocatorLargeAlignment`.
+ const slice = try allocator.alignedAlloc(u8, 1 << 20, 128);
+ slice[0] = 0x12;
+ slice[127] = 0x34;
+ allocator.free(slice);
+ }
+}
+
+test "HeapAllocator" {
+ if (builtin.os == .windows) {
+ var heap_allocator = HeapAllocator.init();
+ defer heap_allocator.deinit();
+
+ const allocator = &heap_allocator.allocator;
+ try testAllocator(allocator);
+ try testAllocatorAligned(allocator, 16);
+ try testAllocatorLargeAlignment(allocator);
+ try testAllocatorAlignedShrink(allocator);
+ }
}
test "ArenaAllocator" {
@@ -482,15 +782,17 @@ test "ArenaAllocator" {
try testAllocator(&arena_allocator.allocator);
try testAllocatorAligned(&arena_allocator.allocator, 16);
try testAllocatorLargeAlignment(&arena_allocator.allocator);
+ try testAllocatorAlignedShrink(&arena_allocator.allocator);
}
-var test_fixed_buffer_allocator_memory: [30000 * @sizeOf(usize)]u8 = undefined;
+var test_fixed_buffer_allocator_memory: [80000 * @sizeOf(u64)]u8 = undefined;
test "FixedBufferAllocator" {
var fixed_buffer_allocator = FixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]);
try testAllocator(&fixed_buffer_allocator.allocator);
try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);
try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
+ try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator);
}
test "FixedBufferAllocator Reuse memory on realloc" {
@@ -528,6 +830,7 @@ test "ThreadSafeFixedBufferAllocator" {
try testAllocator(&fixed_buffer_allocator.allocator);
try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);
try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
+ try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator);
}
fn testAllocator(allocator: *mem.Allocator) !void {
@@ -610,3 +913,32 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo
allocator.free(slice);
}
+
+fn testAllocatorAlignedShrink(allocator: *mem.Allocator) mem.Allocator.Error!void {
+ var debug_buffer: [1000]u8 = undefined;
+ const debug_allocator = &FixedBufferAllocator.init(&debug_buffer).allocator;
+
+ const alloc_size = os.page_size * 2 + 50;
+ var slice = try allocator.alignedAlloc(u8, 16, alloc_size);
+ defer allocator.free(slice);
+
+ var stuff_to_free = std.ArrayList([]align(16) u8).init(debug_allocator);
+ // On Windows, VirtualAlloc returns addresses aligned to a 64K boundary,
+ // which is 16 pages, hence the 32. This test may require to increase
+ // the size of the allocations feeding the `allocator` parameter if they
+ // fail, because of this high over-alignment we want to have.
+ while (@ptrToInt(slice.ptr) == mem.alignForward(@ptrToInt(slice.ptr), os.page_size * 32)) {
+ try stuff_to_free.append(slice);
+ slice = try allocator.alignedAlloc(u8, 16, alloc_size);
+ }
+ while (stuff_to_free.popOrNull()) |item| {
+ allocator.free(item);
+ }
+ slice[0] = 0x12;
+ slice[60] = 0x34;
+
+ // realloc to a smaller size but with a larger alignment
+ slice = try allocator.alignedRealloc(slice, os.page_size * 32, alloc_size / 2);
+ testing.expect(slice[0] == 0x12);
+ testing.expect(slice[60] == 0x34);
+}
diff --git a/std/io.zig b/std/io.zig
index afbd8198fd..1f363b47b1 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -36,6 +36,7 @@ pub fn getStdIn() GetStdIoErrs!File {
}
pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
+pub const COutStream = @import("io/c_out_stream.zig").COutStream;
pub fn InStream(comptime ReadError: type) type {
return struct {
@@ -194,8 +195,8 @@ pub fn InStream(comptime ReadError: type) type {
return mem.readVarInt(ReturnType, bytes, endian);
}
- pub fn skipBytes(self: *Self, num_bytes: usize) !void {
- var i: usize = 0;
+ pub fn skipBytes(self: *Self, num_bytes: u64) !void {
+ var i: u64 = 0;
while (i < num_bytes) : (i += 1) {
_ = try self.readByte();
}
@@ -289,7 +290,7 @@ pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptim
var file = try File.openRead(path);
defer file.close();
- const size = try file.getEndPos();
+ const size = try math.cast(usize, try file.getEndPos());
const buf = try allocator.alignedAlloc(u8, A, size);
errdefer allocator.free(buf);
@@ -742,7 +743,7 @@ pub fn CountingOutStream(comptime OutStreamError: type) type {
pub const Error = OutStreamError;
pub stream: Stream,
- pub bytes_written: usize,
+ pub bytes_written: u64,
child_stream: *Stream,
pub fn init(child_stream: *Stream) Self {
@@ -1089,8 +1090,11 @@ test "io.readLineSliceFrom" {
}
pub const Packing = enum {
- Byte, /// Pack data to byte alignment
- Bit, /// Pack data to bit alignment
+ /// Pack data to byte alignment
+ Byte,
+
+ /// Pack data to bit alignment
+ Bit,
};
/// Creates a deserializer that deserializes types from any stream.
@@ -1111,10 +1115,12 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
pub const Stream = InStream(Error);
pub fn init(in_stream: *Stream) Self {
- return Self{ .in_stream = switch (packing) {
- .Bit => BitInStream(endian, Stream.Error).init(in_stream),
- .Byte => in_stream,
- } };
+ return Self{
+ .in_stream = switch (packing) {
+ .Bit => BitInStream(endian, Stream.Error).init(in_stream),
+ .Byte => in_stream,
+ },
+ };
}
pub fn alignToByte(self: *Self) void {
@@ -1281,7 +1287,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
ptr.* = null;
return;
}
-
+
ptr.* = OC(undefined); //make it non-null so the following .? is guaranteed safe
const val_ptr = &ptr.*.?;
try self.deserializeInto(val_ptr);
@@ -1320,10 +1326,12 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
pub const Stream = OutStream(Error);
pub fn init(out_stream: *Stream) Self {
- return Self{ .out_stream = switch (packing) {
- .Bit => BitOutStream(endian, Stream.Error).init(out_stream),
- .Byte => out_stream,
- } };
+ return Self{
+ .out_stream = switch (packing) {
+ .Bit => BitOutStream(endian, Stream.Error).init(out_stream),
+ .Byte => out_stream,
+ },
+ };
}
/// Flushes any unwritten bits to the stream
@@ -1447,7 +1455,6 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
test "import io tests" {
comptime {
- _ = @import("io_test.zig");
+ _ = @import("io/test.zig");
}
}
-
diff --git a/std/io/c_out_stream.zig b/std/io/c_out_stream.zig
new file mode 100644
index 0000000000..c66b342f1e
--- /dev/null
+++ b/std/io/c_out_stream.zig
@@ -0,0 +1,48 @@
+const std = @import("../std.zig");
+const OutStream = std.io.OutStream;
+const builtin = @import("builtin");
+const posix = std.os.posix;
+
+/// TODO make std.os.FILE use *FILE when linking libc and this just becomes
+/// std.io.FileOutStream because std.os.File.write would do this when linking
+/// libc.
+pub const COutStream = struct {
+ pub const Error = std.os.File.WriteError;
+ pub const Stream = OutStream(Error);
+
+ stream: Stream,
+ c_file: *std.c.FILE,
+
+ pub fn init(c_file: *std.c.FILE) COutStream {
+ return COutStream{
+ .c_file = c_file,
+ .stream = Stream{ .writeFn = writeFn },
+ };
+ }
+
+ fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void {
+ const self = @fieldParentPtr(COutStream, "stream", out_stream);
+ const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);
+ if (amt_written == bytes.len) return;
+ // TODO errno on windows. should we have a posix layer for windows?
+ if (builtin.os == .windows) {
+ return error.InputOutput;
+ }
+ const errno = std.c._errno().*;
+ switch (errno) {
+ 0 => unreachable,
+ posix.EINVAL => unreachable,
+ posix.EFAULT => unreachable,
+ posix.EAGAIN => unreachable, // this is a blocking API
+ posix.EBADF => unreachable, // always a race condition
+ posix.EDESTADDRREQ => unreachable, // connect was never called
+ posix.EDQUOT => return error.DiskQuota,
+ posix.EFBIG => return error.FileTooBig,
+ posix.EIO => return error.InputOutput,
+ posix.ENOSPC => return error.NoSpaceLeft,
+ posix.EPERM => return error.AccessDenied,
+ posix.EPIPE => return error.BrokenPipe,
+ else => return std.os.unexpectedErrorPosix(@intCast(usize, errno)),
+ }
+ }
+};
diff --git a/std/io/seekable_stream.zig b/std/io/seekable_stream.zig
index 5529e42ff1..baf479891c 100644
--- a/std/io/seekable_stream.zig
+++ b/std/io/seekable_stream.zig
@@ -7,25 +7,25 @@ pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType
pub const SeekError = SeekErrorType;
pub const GetSeekPosError = GetSeekPosErrorType;
- seekToFn: fn (self: *Self, pos: usize) SeekError!void,
- seekForwardFn: fn (self: *Self, pos: isize) SeekError!void,
+ seekToFn: fn (self: *Self, pos: u64) SeekError!void,
+ seekForwardFn: fn (self: *Self, pos: i64) SeekError!void,
- getPosFn: fn (self: *Self) GetSeekPosError!usize,
- getEndPosFn: fn (self: *Self) GetSeekPosError!usize,
+ getPosFn: fn (self: *Self) GetSeekPosError!u64,
+ getEndPosFn: fn (self: *Self) GetSeekPosError!u64,
- pub fn seekTo(self: *Self, pos: usize) SeekError!void {
+ pub fn seekTo(self: *Self, pos: u64) SeekError!void {
return self.seekToFn(self, pos);
}
- pub fn seekForward(self: *Self, amt: isize) SeekError!void {
+ pub fn seekForward(self: *Self, amt: i64) SeekError!void {
return self.seekForwardFn(self, amt);
}
- pub fn getEndPos(self: *Self) GetSeekPosError!usize {
+ pub fn getEndPos(self: *Self) GetSeekPosError!u64 {
return self.getEndPosFn(self);
}
- pub fn getPos(self: *Self) GetSeekPosError!usize {
+ pub fn getPos(self: *Self) GetSeekPosError!u64 {
return self.getPosFn(self);
}
};
diff --git a/std/io_test.zig b/std/io/test.zig
index d6f2264a56..07a3c0e8dd 100644
--- a/std/io_test.zig
+++ b/std/io/test.zig
@@ -1,4 +1,4 @@
-const std = @import("std.zig");
+const std = @import("../std.zig");
const io = std.io;
const meta = std.meta;
const trait = std.trait;
@@ -589,3 +589,14 @@ test "Deserializer bad data" {
try testBadData(.Big, .Bit);
try testBadData(.Little, .Bit);
}
+
+test "c out stream" {
+ if (!builtin.link_libc) return error.SkipZigTest;
+
+ const filename = c"tmp_io_test_file.txt";
+ const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;
+ defer std.os.deleteFileC(filename) catch {};
+
+ const out_stream = &io.COutStream.init(out_file).stream;
+ try out_stream.print("hi: {}\n", i32(123));
+}
diff --git a/std/json.zig b/std/json.zig
index 551c3a8da7..8d42d1bcf0 100644
--- a/std/json.zig
+++ b/std/json.zig
@@ -1400,3 +1400,7 @@ test "json.parser.dynamic" {
const double = image.Object.get("double").?.value;
testing.expect(double.Float == 1.3412);
}
+
+test "import more json tests" {
+ _ = @import("json/test.zig");
+}
diff --git a/std/json/test.zig b/std/json/test.zig
new file mode 100644
index 0000000000..7c89dcd123
--- /dev/null
+++ b/std/json/test.zig
@@ -0,0 +1,1904 @@
+// RFC 8529 conformance tests.
+//
+// Tests are taken from https://github.com/nst/JSONTestSuite
+// Read also http://seriot.ch/parsing_json.php for a good overview.
+
+const std = @import("../std.zig");
+
+fn ok(comptime s: []const u8) void {
+ std.testing.expect(std.json.validate(s));
+}
+
+fn err(comptime s: []const u8) void {
+ std.testing.expect(!std.json.validate(s));
+}
+
+fn any(comptime s: []const u8) void {
+ std.testing.expect(true);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Additional tests not part of test JSONTestSuite.
+
+test "y_trailing_comma_after_empty" {
+ ok(
+ \\{"1":[],"2":{},"3":"4"}
+ );
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+test "y_array_arraysWithSpaces" {
+ ok(
+ \\[[] ]
+ );
+}
+
+test "y_array_empty" {
+ ok(
+ \\[]
+ );
+}
+
+test "y_array_empty-string" {
+ ok(
+ \\[""]
+ );
+}
+
+test "y_array_ending_with_newline" {
+ ok(
+ \\["a"]
+ );
+}
+
+test "y_array_false" {
+ ok(
+ \\[false]
+ );
+}
+
+test "y_array_heterogeneous" {
+ ok(
+ \\[null, 1, "1", {}]
+ );
+}
+
+test "y_array_null" {
+ ok(
+ \\[null]
+ );
+}
+
+test "y_array_with_1_and_newline" {
+ ok(
+ \\[1
+ \\]
+ );
+}
+
+test "y_array_with_leading_space" {
+ ok(
+ \\ [1]
+ );
+}
+
+test "y_array_with_several_null" {
+ ok(
+ \\[1,null,null,null,2]
+ );
+}
+
+test "y_array_with_trailing_space" {
+ ok("[2] ");
+}
+
+test "y_number_0e+1" {
+ ok(
+ \\[0e+1]
+ );
+}
+
+test "y_number_0e1" {
+ ok(
+ \\[0e1]
+ );
+}
+
+test "y_number_after_space" {
+ ok(
+ \\[ 4]
+ );
+}
+
+test "y_number_double_close_to_zero" {
+ ok(
+ \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]
+ );
+}
+
+test "y_number_int_with_exp" {
+ ok(
+ \\[20e1]
+ );
+}
+
+test "y_number" {
+ ok(
+ \\[123e65]
+ );
+}
+
+test "y_number_minus_zero" {
+ ok(
+ \\[-0]
+ );
+}
+
+test "y_number_negative_int" {
+ ok(
+ \\[-123]
+ );
+}
+
+test "y_number_negative_one" {
+ ok(
+ \\[-1]
+ );
+}
+
+test "y_number_negative_zero" {
+ ok(
+ \\[-0]
+ );
+}
+
+test "y_number_real_capital_e" {
+ ok(
+ \\[1E22]
+ );
+}
+
+test "y_number_real_capital_e_neg_exp" {
+ ok(
+ \\[1E-2]
+ );
+}
+
+test "y_number_real_capital_e_pos_exp" {
+ ok(
+ \\[1E+2]
+ );
+}
+
+test "y_number_real_exponent" {
+ ok(
+ \\[123e45]
+ );
+}
+
+test "y_number_real_fraction_exponent" {
+ ok(
+ \\[123.456e78]
+ );
+}
+
+test "y_number_real_neg_exp" {
+ ok(
+ \\[1e-2]
+ );
+}
+
+test "y_number_real_pos_exponent" {
+ ok(
+ \\[1e+2]
+ );
+}
+
+test "y_number_simple_int" {
+ ok(
+ \\[123]
+ );
+}
+
+test "y_number_simple_real" {
+ ok(
+ \\[123.456789]
+ );
+}
+
+test "y_object_basic" {
+ ok(
+ \\{"asd":"sdf"}
+ );
+}
+
+test "y_object_duplicated_key_and_value" {
+ ok(
+ \\{"a":"b","a":"b"}
+ );
+}
+
+test "y_object_duplicated_key" {
+ ok(
+ \\{"a":"b","a":"c"}
+ );
+}
+
+test "y_object_empty" {
+ ok(
+ \\{}
+ );
+}
+
+test "y_object_empty_key" {
+ ok(
+ \\{"":0}
+ );
+}
+
+test "y_object_escaped_null_in_key" {
+ ok(
+ \\{"foo\u0000bar": 42}
+ );
+}
+
+test "y_object_extreme_numbers" {
+ ok(
+ \\{ "min": -1.0e+28, "max": 1.0e+28 }
+ );
+}
+
+test "y_object" {
+ ok(
+ \\{"asd":"sdf", "dfg":"fgh"}
+ );
+}
+
+test "y_object_long_strings" {
+ ok(
+ \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
+ );
+}
+
+test "y_object_simple" {
+ ok(
+ \\{"a":[]}
+ );
+}
+
+test "y_object_string_unicode" {
+ ok(
+ \\{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" }
+ );
+}
+
+test "y_object_with_newlines" {
+ ok(
+ \\{
+ \\"a": "b"
+ \\}
+ );
+}
+
+test "y_string_1_2_3_bytes_UTF-8_sequences" {
+ ok(
+ \\["\u0060\u012a\u12AB"]
+ );
+}
+
+test "y_string_accepted_surrogate_pair" {
+ ok(
+ \\["\uD801\udc37"]
+ );
+}
+
+test "y_string_accepted_surrogate_pairs" {
+ ok(
+ \\["\ud83d\ude39\ud83d\udc8d"]
+ );
+}
+
+test "y_string_allowed_escapes" {
+ ok(
+ \\["\"\\\/\b\f\n\r\t"]
+ );
+}
+
+test "y_string_backslash_and_u_escaped_zero" {
+ ok(
+ \\["\\u0000"]
+ );
+}
+
+test "y_string_backslash_doublequotes" {
+ ok(
+ \\["\""]
+ );
+}
+
+test "y_string_comments" {
+ ok(
+ \\["a/*b*/c/*d//e"]
+ );
+}
+
+test "y_string_double_escape_a" {
+ ok(
+ \\["\\a"]
+ );
+}
+
+test "y_string_double_escape_n" {
+ ok(
+ \\["\\n"]
+ );
+}
+
+test "y_string_escaped_control_character" {
+ ok(
+ \\["\u0012"]
+ );
+}
+
+test "y_string_escaped_noncharacter" {
+ ok(
+ \\["\uFFFF"]
+ );
+}
+
+test "y_string_in_array" {
+ ok(
+ \\["asd"]
+ );
+}
+
+test "y_string_in_array_with_leading_space" {
+ ok(
+ \\[ "asd"]
+ );
+}
+
+test "y_string_last_surrogates_1_and_2" {
+ ok(
+ \\["\uDBFF\uDFFF"]
+ );
+}
+
+test "y_string_nbsp_uescaped" {
+ ok(
+ \\["new\u00A0line"]
+ );
+}
+
+test "y_string_nonCharacterInUTF-8_U+10FFFF" {
+ ok(
+ \\["􏿿"]
+ );
+}
+
+test "y_string_nonCharacterInUTF-8_U+FFFF" {
+ ok(
+ \\["￿"]
+ );
+}
+
+test "y_string_null_escape" {
+ ok(
+ \\["\u0000"]
+ );
+}
+
+test "y_string_one-byte-utf-8" {
+ ok(
+ \\["\u002c"]
+ );
+}
+
+test "y_string_pi" {
+ ok(
+ \\["π"]
+ );
+}
+
+test "y_string_reservedCharacterInUTF-8_U+1BFFF" {
+ ok(
+ \\["𛿿"]
+ );
+}
+
+test "y_string_simple_ascii" {
+ ok(
+ \\["asd "]
+ );
+}
+
+test "y_string_space" {
+ ok(
+ \\" "
+ );
+}
+
+test "y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" {
+ ok(
+ \\["\uD834\uDd1e"]
+ );
+}
+
+test "y_string_three-byte-utf-8" {
+ ok(
+ \\["\u0821"]
+ );
+}
+
+test "y_string_two-byte-utf-8" {
+ ok(
+ \\["\u0123"]
+ );
+}
+
+test "y_string_u+2028_line_sep" {
+ ok("[\"\xe2\x80\xa8\"]");
+}
+
+test "y_string_u+2029_par_sep" {
+ ok("[\"\xe2\x80\xa9\"]");
+}
+
+test "y_string_uescaped_newline" {
+ ok(
+ \\["new\u000Aline"]
+ );
+}
+
+test "y_string_uEscape" {
+ ok(
+ \\["\u0061\u30af\u30EA\u30b9"]
+ );
+}
+
+test "y_string_unescaped_char_delete" {
+ ok("[\"\x7f\"]");
+}
+
+test "y_string_unicode_2" {
+ ok(
+ \\["⍂㈴⍂"]
+ );
+}
+
+test "y_string_unicodeEscapedBackslash" {
+ ok(
+ \\["\u005C"]
+ );
+}
+
+test "y_string_unicode_escaped_double_quote" {
+ ok(
+ \\["\u0022"]
+ );
+}
+
+test "y_string_unicode" {
+ ok(
+ \\["\uA66D"]
+ );
+}
+
+test "y_string_unicode_U+10FFFE_nonchar" {
+ ok(
+ \\["\uDBFF\uDFFE"]
+ );
+}
+
+test "y_string_unicode_U+1FFFE_nonchar" {
+ ok(
+ \\["\uD83F\uDFFE"]
+ );
+}
+
+test "y_string_unicode_U+200B_ZERO_WIDTH_SPACE" {
+ ok(
+ \\["\u200B"]
+ );
+}
+
+test "y_string_unicode_U+2064_invisible_plus" {
+ ok(
+ \\["\u2064"]
+ );
+}
+
+test "y_string_unicode_U+FDD0_nonchar" {
+ ok(
+ \\["\uFDD0"]
+ );
+}
+
+test "y_string_unicode_U+FFFE_nonchar" {
+ ok(
+ \\["\uFFFE"]
+ );
+}
+
+test "y_string_utf8" {
+ ok(
+ \\["€𝄞"]
+ );
+}
+
+test "y_string_with_del_character" {
+ ok("[\"a\x7fa\"]");
+}
+
+test "y_structure_lonely_false" {
+ ok(
+ \\false
+ );
+}
+
+test "y_structure_lonely_int" {
+ ok(
+ \\42
+ );
+}
+
+test "y_structure_lonely_negative_real" {
+ ok(
+ \\-0.1
+ );
+}
+
+test "y_structure_lonely_null" {
+ ok(
+ \\null
+ );
+}
+
+test "y_structure_lonely_string" {
+ ok(
+ \\"asd"
+ );
+}
+
+test "y_structure_lonely_true" {
+ ok(
+ \\true
+ );
+}
+
+test "y_structure_string_empty" {
+ ok(
+ \\""
+ );
+}
+
+test "y_structure_trailing_newline" {
+ ok(
+ \\["a"]
+ );
+}
+
+test "y_structure_true_in_array" {
+ ok(
+ \\[true]
+ );
+}
+
+test "y_structure_whitespace_array" {
+ ok(" [] ");
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+test "n_array_1_true_without_comma" {
+ err(
+ \\[1 true]
+ );
+}
+
+test "n_array_a_invalid_utf8" {
+ err(
+ \\[aå]
+ );
+}
+
+test "n_array_colon_instead_of_comma" {
+ err(
+ \\["": 1]
+ );
+}
+
+test "n_array_comma_after_close" {
+ //err(
+ // \\[""],
+ //);
+}
+
+test "n_array_comma_and_number" {
+ err(
+ \\[,1]
+ );
+}
+
+test "n_array_double_comma" {
+ err(
+ \\[1,,2]
+ );
+}
+
+test "n_array_double_extra_comma" {
+ err(
+ \\["x",,]
+ );
+}
+
+test "n_array_extra_close" {
+ err(
+ \\["x"]]
+ );
+}
+
+test "n_array_extra_comma" {
+ //err(
+ // \\["",]
+ //);
+}
+
+test "n_array_incomplete_invalid_value" {
+ err(
+ \\[x
+ );
+}
+
+test "n_array_incomplete" {
+ err(
+ \\["x"
+ );
+}
+
+test "n_array_inner_array_no_comma" {
+ err(
+ \\[3[4]]
+ );
+}
+
+test "n_array_invalid_utf8" {
+ err(
+ \\[ÿ]
+ );
+}
+
+test "n_array_items_separated_by_semicolon" {
+ err(
+ \\[1:2]
+ );
+}
+
+test "n_array_just_comma" {
+ err(
+ \\[,]
+ );
+}
+
+test "n_array_just_minus" {
+ err(
+ \\[-]
+ );
+}
+
+test "n_array_missing_value" {
+ err(
+ \\[ , ""]
+ );
+}
+
+test "n_array_newlines_unclosed" {
+ err(
+ \\["a",
+ \\4
+ \\,1,
+ );
+}
+
+test "n_array_number_and_comma" {
+ err(
+ \\[1,]
+ );
+}
+
+test "n_array_number_and_several_commas" {
+ err(
+ \\[1,,]
+ );
+}
+
+test "n_array_spaces_vertical_tab_formfeed" {
+ err("[\"\x0aa\"\\f]");
+}
+
+test "n_array_star_inside" {
+ err(
+ \\[*]
+ );
+}
+
+test "n_array_unclosed" {
+ err(
+ \\[""
+ );
+}
+
+test "n_array_unclosed_trailing_comma" {
+ err(
+ \\[1,
+ );
+}
+
+test "n_array_unclosed_with_new_lines" {
+ err(
+ \\[1,
+ \\1
+ \\,1
+ );
+}
+
+test "n_array_unclosed_with_object_inside" {
+ err(
+ \\[{}
+ );
+}
+
+test "n_incomplete_false" {
+ err(
+ \\[fals]
+ );
+}
+
+test "n_incomplete_null" {
+ err(
+ \\[nul]
+ );
+}
+
+test "n_incomplete_true" {
+ err(
+ \\[tru]
+ );
+}
+
+test "n_multidigit_number_then_00" {
+ err("123\x00");
+}
+
+test "n_number_0.1.2" {
+ err(
+ \\[0.1.2]
+ );
+}
+
+test "n_number_-01" {
+ err(
+ \\[-01]
+ );
+}
+
+test "n_number_0.3e" {
+ err(
+ \\[0.3e]
+ );
+}
+
+test "n_number_0.3e+" {
+ err(
+ \\[0.3e+]
+ );
+}
+
+test "n_number_0_capital_E" {
+ err(
+ \\[0E]
+ );
+}
+
+test "n_number_0_capital_E+" {
+ err(
+ \\[0E+]
+ );
+}
+
+test "n_number_0.e1" {
+ err(
+ \\[0.e1]
+ );
+}
+
+test "n_number_0e" {
+ err(
+ \\[0e]
+ );
+}
+
+test "n_number_0e+" {
+ err(
+ \\[0e+]
+ );
+}
+
+test "n_number_1_000" {
+ err(
+ \\[1 000.0]
+ );
+}
+
+test "n_number_1.0e-" {
+ err(
+ \\[1.0e-]
+ );
+}
+
+test "n_number_1.0e" {
+ err(
+ \\[1.0e]
+ );
+}
+
+test "n_number_1.0e+" {
+ err(
+ \\[1.0e+]
+ );
+}
+
+test "n_number_-1.0." {
+ err(
+ \\[-1.0.]
+ );
+}
+
+test "n_number_1eE2" {
+ err(
+ \\[1eE2]
+ );
+}
+
+test "n_number_.-1" {
+ err(
+ \\[.-1]
+ );
+}
+
+test "n_number_+1" {
+ err(
+ \\[+1]
+ );
+}
+
+test "n_number_.2e-3" {
+ err(
+ \\[.2e-3]
+ );
+}
+
+test "n_number_2.e-3" {
+ err(
+ \\[2.e-3]
+ );
+}
+
+test "n_number_2.e+3" {
+ err(
+ \\[2.e+3]
+ );
+}
+
+test "n_number_2.e3" {
+ err(
+ \\[2.e3]
+ );
+}
+
+test "n_number_-2." {
+ err(
+ \\[-2.]
+ );
+}
+
+test "n_number_9.e+" {
+ err(
+ \\[9.e+]
+ );
+}
+
+test "n_number_expression" {
+ err(
+ \\[1+2]
+ );
+}
+
+test "n_number_hex_1_digit" {
+ err(
+ \\[0x1]
+ );
+}
+
+test "n_number_hex_2_digits" {
+ err(
+ \\[0x42]
+ );
+}
+
+test "n_number_infinity" {
+ err(
+ \\[Infinity]
+ );
+}
+
+test "n_number_+Inf" {
+ err(
+ \\[+Inf]
+ );
+}
+
+test "n_number_Inf" {
+ err(
+ \\[Inf]
+ );
+}
+
+test "n_number_invalid+-" {
+ err(
+ \\[0e+-1]
+ );
+}
+
+test "n_number_invalid-negative-real" {
+ err(
+ \\[-123.123foo]
+ );
+}
+
+test "n_number_invalid-utf-8-in-bigger-int" {
+ err(
+ \\[123å]
+ );
+}
+
+test "n_number_invalid-utf-8-in-exponent" {
+ err(
+ \\[1e1å]
+ );
+}
+
+test "n_number_invalid-utf-8-in-int" {
+ err(
+ \\[0å]
+ );
+}
+
+test "n_number_++" {
+ err(
+ \\[++1234]
+ );
+}
+
+test "n_number_minus_infinity" {
+ err(
+ \\[-Infinity]
+ );
+}
+
+test "n_number_minus_sign_with_trailing_garbage" {
+ err(
+ \\[-foo]
+ );
+}
+
+test "n_number_minus_space_1" {
+ err(
+ \\[- 1]
+ );
+}
+
+test "n_number_-NaN" {
+ err(
+ \\[-NaN]
+ );
+}
+
+test "n_number_NaN" {
+ err(
+ \\[NaN]
+ );
+}
+
+test "n_number_neg_int_starting_with_zero" {
+ err(
+ \\[-012]
+ );
+}
+
+test "n_number_neg_real_without_int_part" {
+ err(
+ \\[-.123]
+ );
+}
+
+test "n_number_neg_with_garbage_at_end" {
+ err(
+ \\[-1x]
+ );
+}
+
+test "n_number_real_garbage_after_e" {
+ err(
+ \\[1ea]
+ );
+}
+
+test "n_number_real_with_invalid_utf8_after_e" {
+ err(
+ \\[1eå]
+ );
+}
+
+test "n_number_real_without_fractional_part" {
+ err(
+ \\[1.]
+ );
+}
+
+test "n_number_starting_with_dot" {
+ err(
+ \\[.123]
+ );
+}
+
+test "n_number_U+FF11_fullwidth_digit_one" {
+ err(
+ \\[1]
+ );
+}
+
+test "n_number_with_alpha_char" {
+ err(
+ \\[1.8011670033376514H-308]
+ );
+}
+
+test "n_number_with_alpha" {
+ err(
+ \\[1.2a-3]
+ );
+}
+
+test "n_number_with_leading_zero" {
+ err(
+ \\[012]
+ );
+}
+
+test "n_object_bad_value" {
+ err(
+ \\["x", truth]
+ );
+}
+
+test "n_object_bracket_key" {
+ err(
+ \\{[: "x"}
+ );
+}
+
+test "n_object_comma_instead_of_colon" {
+ err(
+ \\{"x", null}
+ );
+}
+
+test "n_object_double_colon" {
+ err(
+ \\{"x"::"b"}
+ );
+}
+
+test "n_object_emoji" {
+ err(
+ \\{🇨🇭}
+ );
+}
+
+test "n_object_garbage_at_end" {
+ err(
+ \\{"a":"a" 123}
+ );
+}
+
+test "n_object_key_with_single_quotes" {
+ err(
+ \\{key: 'value'}
+ );
+}
+
+test "n_object_lone_continuation_byte_in_key_and_trailing_comma" {
+ err(
+ \\{"¹":"0",}
+ );
+}
+
+test "n_object_missing_colon" {
+ err(
+ \\{"a" b}
+ );
+}
+
+test "n_object_missing_key" {
+ err(
+ \\{:"b"}
+ );
+}
+
+test "n_object_missing_semicolon" {
+ err(
+ \\{"a" "b"}
+ );
+}
+
+test "n_object_missing_value" {
+ err(
+ \\{"a":
+ );
+}
+
+test "n_object_no-colon" {
+ err(
+ \\{"a"
+ );
+}
+
+test "n_object_non_string_key_but_huge_number_instead" {
+ err(
+ \\{9999E9999:1}
+ );
+}
+
+test "n_object_non_string_key" {
+ err(
+ \\{1:1}
+ );
+}
+
+test "n_object_repeated_null_null" {
+ err(
+ \\{null:null,null:null}
+ );
+}
+
+test "n_object_several_trailing_commas" {
+ err(
+ \\{"id":0,,,,,}
+ );
+}
+
+test "n_object_single_quote" {
+ err(
+ \\{'a':0}
+ );
+}
+
+test "n_object_trailing_comma" {
+ err(
+ \\{"id":0,}
+ );
+}
+
+test "n_object_trailing_comment" {
+ err(
+ \\{"a":"b"}/**/
+ );
+}
+
+test "n_object_trailing_comment_open" {
+ err(
+ \\{"a":"b"}/**//
+ );
+}
+
+test "n_object_trailing_comment_slash_open_incomplete" {
+ err(
+ \\{"a":"b"}/
+ );
+}
+
+test "n_object_trailing_comment_slash_open" {
+ err(
+ \\{"a":"b"}//
+ );
+}
+
+test "n_object_two_commas_in_a_row" {
+ err(
+ \\{"a":"b",,"c":"d"}
+ );
+}
+
+test "n_object_unquoted_key" {
+ err(
+ \\{a: "b"}
+ );
+}
+
+test "n_object_unterminated-value" {
+ err(
+ \\{"a":"a
+ );
+}
+
+test "n_object_with_single_string" {
+ err(
+ \\{ "foo" : "bar", "a" }
+ );
+}
+
+test "n_object_with_trailing_garbage" {
+ err(
+ \\{"a":"b"}#
+ );
+}
+
+test "n_single_space" {
+ err(" ");
+}
+
+test "n_string_1_surrogate_then_escape" {
+ err(
+ \\["\uD800\"]
+ );
+}
+
+test "n_string_1_surrogate_then_escape_u1" {
+ err(
+ \\["\uD800\u1"]
+ );
+}
+
+test "n_string_1_surrogate_then_escape_u1x" {
+ err(
+ \\["\uD800\u1x"]
+ );
+}
+
+test "n_string_1_surrogate_then_escape_u" {
+ err(
+ \\["\uD800\u"]
+ );
+}
+
+test "n_string_accentuated_char_no_quotes" {
+ err(
+ \\[é]
+ );
+}
+
+test "n_string_backslash_00" {
+ err("[\"\x00\"]");
+}
+
+test "n_string_escaped_backslash_bad" {
+ err(
+ \\["\\\"]
+ );
+}
+
+test "n_string_escaped_ctrl_char_tab" {
+ err("\x5b\x22\x5c\x09\x22\x5d");
+}
+
+test "n_string_escaped_emoji" {
+ err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]");
+}
+
+test "n_string_escape_x" {
+ err(
+ \\["\x00"]
+ );
+}
+
+test "n_string_incomplete_escaped_character" {
+ err(
+ \\["\u00A"]
+ );
+}
+
+test "n_string_incomplete_escape" {
+ err(
+ \\["\"]
+ );
+}
+
+test "n_string_incomplete_surrogate_escape_invalid" {
+ err(
+ \\["\uD800\uD800\x"]
+ );
+}
+
+test "n_string_incomplete_surrogate" {
+ err(
+ \\["\uD834\uDd"]
+ );
+}
+
+test "n_string_invalid_backslash_esc" {
+ err(
+ \\["\a"]
+ );
+}
+
+test "n_string_invalid_unicode_escape" {
+ err(
+ \\["\uqqqq"]
+ );
+}
+
+test "n_string_invalid_utf8_after_escape" {
+ err("[\"\\\x75\xc3\xa5\"]");
+}
+
+test "n_string_invalid-utf-8-in-escape" {
+ err(
+ \\["\uå"]
+ );
+}
+
+test "n_string_leading_uescaped_thinspace" {
+ err(
+ \\[\u0020"asd"]
+ );
+}
+
+test "n_string_no_quotes_with_bad_escape" {
+ err(
+ \\[\n]
+ );
+}
+
+test "n_string_single_doublequote" {
+ err(
+ \\"
+ );
+}
+
+test "n_string_single_quote" {
+ err(
+ \\['single quote']
+ );
+}
+
+test "n_string_single_string_no_double_quotes" {
+ err(
+ \\abc
+ );
+}
+
+test "n_string_start_escape_unclosed" {
+ err(
+ \\["\
+ );
+}
+
+test "n_string_unescaped_crtl_char" {
+ err("[\"a\x00a\"]");
+}
+
+test "n_string_unescaped_newline" {
+ err(
+ \\["new
+ \\line"]
+ );
+}
+
+test "n_string_unescaped_tab" {
+ err("[\"\t\"]");
+}
+
+test "n_string_unicode_CapitalU" {
+ err(
+ \\"\UA66D"
+ );
+}
+
+test "n_string_with_trailing_garbage" {
+ err(
+ \\""x
+ );
+}
+
+test "n_structure_100000_opening_arrays" {
+ err("[" ** 100000);
+}
+
+test "n_structure_angle_bracket_." {
+ err(
+ \\<.>
+ );
+}
+
+test "n_structure_angle_bracket_null" {
+ err(
+ \\[<null>]
+ );
+}
+
+test "n_structure_array_trailing_garbage" {
+ err(
+ \\[1]x
+ );
+}
+
+test "n_structure_array_with_extra_array_close" {
+ err(
+ \\[1]]
+ );
+}
+
+test "n_structure_array_with_unclosed_string" {
+ err(
+ \\["asd]
+ );
+}
+
+test "n_structure_ascii-unicode-identifier" {
+ err(
+ \\aå
+ );
+}
+
+test "n_structure_capitalized_True" {
+ err(
+ \\[True]
+ );
+}
+
+test "n_structure_close_unopened_array" {
+ err(
+ \\1]
+ );
+}
+
+test "n_structure_comma_instead_of_closing_brace" {
+ err(
+ \\{"x": true,
+ );
+}
+
+test "n_structure_double_array" {
+ err(
+ \\[][]
+ );
+}
+
+test "n_structure_end_array" {
+ err(
+ \\]
+ );
+}
+
+test "n_structure_incomplete_UTF8_BOM" {
+ err(
+ \\ï»{}
+ );
+}
+
+test "n_structure_lone-invalid-utf-8" {
+ err(
+ \\å
+ );
+}
+
+test "n_structure_lone-open-bracket" {
+ err(
+ \\[
+ );
+}
+
+test "n_structure_no_data" {
+ err(
+ \\
+ );
+}
+
+test "n_structure_null-byte-outside-string" {
+ err("[\x00]");
+}
+
+test "n_structure_number_with_trailing_garbage" {
+ err(
+ \\2@
+ );
+}
+
+test "n_structure_object_followed_by_closing_object" {
+ err(
+ \\{}}
+ );
+}
+
+test "n_structure_object_unclosed_no_value" {
+ err(
+ \\{"":
+ );
+}
+
+test "n_structure_object_with_comment" {
+ err(
+ \\{"a":/*comment*/"b"}
+ );
+}
+
+test "n_structure_object_with_trailing_garbage" {
+ err(
+ \\{"a": true} "x"
+ );
+}
+
+test "n_structure_open_array_apostrophe" {
+ err(
+ \\['
+ );
+}
+
+test "n_structure_open_array_comma" {
+ err(
+ \\[,
+ );
+}
+
+test "n_structure_open_array_object" {
+ err("[{\"\":" ** 50000);
+}
+
+test "n_structure_open_array_open_object" {
+ err(
+ \\[{
+ );
+}
+
+test "n_structure_open_array_open_string" {
+ err(
+ \\["a
+ );
+}
+
+test "n_structure_open_array_string" {
+ err(
+ \\["a"
+ );
+}
+
+test "n_structure_open_object_close_array" {
+ err(
+ \\{]
+ );
+}
+
+test "n_structure_open_object_comma" {
+ err(
+ \\{,
+ );
+}
+
+test "n_structure_open_object" {
+ err(
+ \\{
+ );
+}
+
+test "n_structure_open_object_open_array" {
+ err(
+ \\{[
+ );
+}
+
+test "n_structure_open_object_open_string" {
+ err(
+ \\{"a
+ );
+}
+
+test "n_structure_open_object_string_with_apostrophes" {
+ err(
+ \\{'a'
+ );
+}
+
+test "n_structure_open_open" {
+ err(
+ \\["\{["\{["\{["\{
+ );
+}
+
+test "n_structure_single_eacute" {
+ err(
+ \\é
+ );
+}
+
+test "n_structure_single_star" {
+ err(
+ \\*
+ );
+}
+
+test "n_structure_trailing_#" {
+ err(
+ \\{"a":"b"}#{}
+ );
+}
+
+test "n_structure_U+2060_word_joined" {
+ err(
+ \\[⁠]
+ );
+}
+
+test "n_structure_uescaped_LF_before_string" {
+ err(
+ \\[\u000A""]
+ );
+}
+
+test "n_structure_unclosed_array" {
+ err(
+ \\[1
+ );
+}
+
+test "n_structure_unclosed_array_partial_null" {
+ err(
+ \\[ false, nul
+ );
+}
+
+test "n_structure_unclosed_array_unfinished_false" {
+ err(
+ \\[ true, fals
+ );
+}
+
+test "n_structure_unclosed_array_unfinished_true" {
+ err(
+ \\[ false, tru
+ );
+}
+
+test "n_structure_unclosed_object" {
+ err(
+ \\{"asd":"asd"
+ );
+}
+
+test "n_structure_unicode-identifier" {
+ err(
+ \\Ã¥
+ );
+}
+
+test "n_structure_UTF8_BOM_no_data" {
+ err(
+ \\
+ );
+}
+
+test "n_structure_whitespace_formfeed" {
+ err("[\x0c]");
+}
+
+test "n_structure_whitespace_U+2060_word_joiner" {
+ err(
+ \\[⁠]
+ );
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+test "i_number_double_huge_neg_exp" {
+ any(
+ \\[123.456e-789]
+ );
+}
+
+test "i_number_huge_exp" {
+ any(
+ \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]
+ );
+}
+
+test "i_number_neg_int_huge_exp" {
+ any(
+ \\[-1e+9999]
+ );
+}
+
+test "i_number_pos_double_huge_exp" {
+ any(
+ \\[1.5e+9999]
+ );
+}
+
+test "i_number_real_neg_overflow" {
+ any(
+ \\[-123123e100000]
+ );
+}
+
+test "i_number_real_pos_overflow" {
+ any(
+ \\[123123e100000]
+ );
+}
+
+test "i_number_real_underflow" {
+ any(
+ \\[123e-10000000]
+ );
+}
+
+test "i_number_too_big_neg_int" {
+ any(
+ \\[-123123123123123123123123123123]
+ );
+}
+
+test "i_number_too_big_pos_int" {
+ any(
+ \\[100000000000000000000]
+ );
+}
+
+test "i_number_very_big_negative_int" {
+ any(
+ \\[-237462374673276894279832749832423479823246327846]
+ );
+}
+
+test "i_object_key_lone_2nd_surrogate" {
+ any(
+ \\{"\uDFAA":0}
+ );
+}
+
+test "i_string_1st_surrogate_but_2nd_missing" {
+ any(
+ \\["\uDADA"]
+ );
+}
+
+test "i_string_1st_valid_surrogate_2nd_invalid" {
+ any(
+ \\["\uD888\u1234"]
+ );
+}
+
+test "i_string_incomplete_surrogate_and_escape_valid" {
+ any(
+ \\["\uD800\n"]
+ );
+}
+
+test "i_string_incomplete_surrogate_pair" {
+ any(
+ \\["\uDd1ea"]
+ );
+}
+
+test "i_string_incomplete_surrogates_escape_valid" {
+ any(
+ \\["\uD800\uD800\n"]
+ );
+}
+
+test "i_string_invalid_lonely_surrogate" {
+ any(
+ \\["\ud800"]
+ );
+}
+
+test "i_string_invalid_surrogate" {
+ any(
+ \\["\ud800abc"]
+ );
+}
+
+test "i_string_invalid_utf-8" {
+ any(
+ \\["ÿ"]
+ );
+}
+
+test "i_string_inverted_surrogates_U+1D11E" {
+ any(
+ \\["\uDd1e\uD834"]
+ );
+}
+
+test "i_string_iso_latin_1" {
+ any(
+ \\["é"]
+ );
+}
+
+test "i_string_lone_second_surrogate" {
+ any(
+ \\["\uDFAA"]
+ );
+}
+
+test "i_string_lone_utf8_continuation_byte" {
+ any(
+ \\[""]
+ );
+}
+
+test "i_string_not_in_unicode_range" {
+ any(
+ \\["ô¿¿¿"]
+ );
+}
+
+test "i_string_overlong_sequence_2_bytes" {
+ any(
+ \\["À¯"]
+ );
+}
+
+test "i_string_overlong_sequence_6_bytes" {
+ any(
+ \\["üƒ¿¿¿¿"]
+ );
+}
+
+test "i_string_overlong_sequence_6_bytes_null" {
+ any(
+ \\["ü€€€€€"]
+ );
+}
+
+test "i_string_truncated-utf-8" {
+ any(
+ \\["àÿ"]
+ );
+}
+
+test "i_string_utf16BE_no_BOM" {
+ any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d");
+}
+
+test "i_string_utf16LE_no_BOM" {
+ any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
+}
+
+test "i_string_UTF-16LE_with_BOM" {
+ any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
+}
+
+test "i_string_UTF-8_invalid_sequence" {
+ any(
+ \\["日шú"]
+ );
+}
+
+test "i_string_UTF8_surrogate_U+D800" {
+ any(
+ \\["í €"]
+ );
+}
+
+test "i_structure_500_nested_arrays" {
+ any(("[" ** 500) ++ ("]" ** 500));
+}
+
+test "i_structure_UTF-8_BOM_empty_object" {
+ any(
+ \\{}
+ );
+}
diff --git a/std/json_test.zig b/std/json_test.zig
deleted file mode 100644
index a323e6e979..0000000000
--- a/std/json_test.zig
+++ /dev/null
@@ -1,1904 +0,0 @@
-// RFC 8529 conformance tests.
-//
-// Tests are taken from https://github.com/nst/JSONTestSuite
-// Read also http://seriot.ch/parsing_json.php for a good overview.
-
-const std = @import("std.zig");
-
-fn ok(comptime s: []const u8) void {
- std.testing.expect(std.json.validate(s));
-}
-
-fn err(comptime s: []const u8) void {
- std.testing.expect(!std.json.validate(s));
-}
-
-fn any(comptime s: []const u8) void {
- std.testing.expect(true);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Additional tests not part of test JSONTestSuite.
-
-test "json.test.y_trailing_comma_after_empty" {
- ok(
- \\{"1":[],"2":{},"3":"4"}
- );
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-test "json.test.y_array_arraysWithSpaces" {
- ok(
- \\[[] ]
- );
-}
-
-test "json.test.y_array_empty" {
- ok(
- \\[]
- );
-}
-
-test "json.test.y_array_empty-string" {
- ok(
- \\[""]
- );
-}
-
-test "json.test.y_array_ending_with_newline" {
- ok(
- \\["a"]
- );
-}
-
-test "json.test.y_array_false" {
- ok(
- \\[false]
- );
-}
-
-test "json.test.y_array_heterogeneous" {
- ok(
- \\[null, 1, "1", {}]
- );
-}
-
-test "json.test.y_array_null" {
- ok(
- \\[null]
- );
-}
-
-test "json.test.y_array_with_1_and_newline" {
- ok(
- \\[1
- \\]
- );
-}
-
-test "json.test.y_array_with_leading_space" {
- ok(
- \\ [1]
- );
-}
-
-test "json.test.y_array_with_several_null" {
- ok(
- \\[1,null,null,null,2]
- );
-}
-
-test "json.test.y_array_with_trailing_space" {
- ok("[2] ");
-}
-
-test "json.test.y_number_0e+1" {
- ok(
- \\[0e+1]
- );
-}
-
-test "json.test.y_number_0e1" {
- ok(
- \\[0e1]
- );
-}
-
-test "json.test.y_number_after_space" {
- ok(
- \\[ 4]
- );
-}
-
-test "json.test.y_number_double_close_to_zero" {
- ok(
- \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]
- );
-}
-
-test "json.test.y_number_int_with_exp" {
- ok(
- \\[20e1]
- );
-}
-
-test "json.test.y_number" {
- ok(
- \\[123e65]
- );
-}
-
-test "json.test.y_number_minus_zero" {
- ok(
- \\[-0]
- );
-}
-
-test "json.test.y_number_negative_int" {
- ok(
- \\[-123]
- );
-}
-
-test "json.test.y_number_negative_one" {
- ok(
- \\[-1]
- );
-}
-
-test "json.test.y_number_negative_zero" {
- ok(
- \\[-0]
- );
-}
-
-test "json.test.y_number_real_capital_e" {
- ok(
- \\[1E22]
- );
-}
-
-test "json.test.y_number_real_capital_e_neg_exp" {
- ok(
- \\[1E-2]
- );
-}
-
-test "json.test.y_number_real_capital_e_pos_exp" {
- ok(
- \\[1E+2]
- );
-}
-
-test "json.test.y_number_real_exponent" {
- ok(
- \\[123e45]
- );
-}
-
-test "json.test.y_number_real_fraction_exponent" {
- ok(
- \\[123.456e78]
- );
-}
-
-test "json.test.y_number_real_neg_exp" {
- ok(
- \\[1e-2]
- );
-}
-
-test "json.test.y_number_real_pos_exponent" {
- ok(
- \\[1e+2]
- );
-}
-
-test "json.test.y_number_simple_int" {
- ok(
- \\[123]
- );
-}
-
-test "json.test.y_number_simple_real" {
- ok(
- \\[123.456789]
- );
-}
-
-test "json.test.y_object_basic" {
- ok(
- \\{"asd":"sdf"}
- );
-}
-
-test "json.test.y_object_duplicated_key_and_value" {
- ok(
- \\{"a":"b","a":"b"}
- );
-}
-
-test "json.test.y_object_duplicated_key" {
- ok(
- \\{"a":"b","a":"c"}
- );
-}
-
-test "json.test.y_object_empty" {
- ok(
- \\{}
- );
-}
-
-test "json.test.y_object_empty_key" {
- ok(
- \\{"":0}
- );
-}
-
-test "json.test.y_object_escaped_null_in_key" {
- ok(
- \\{"foo\u0000bar": 42}
- );
-}
-
-test "json.test.y_object_extreme_numbers" {
- ok(
- \\{ "min": -1.0e+28, "max": 1.0e+28 }
- );
-}
-
-test "json.test.y_object" {
- ok(
- \\{"asd":"sdf", "dfg":"fgh"}
- );
-}
-
-test "json.test.y_object_long_strings" {
- ok(
- \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
- );
-}
-
-test "json.test.y_object_simple" {
- ok(
- \\{"a":[]}
- );
-}
-
-test "json.test.y_object_string_unicode" {
- ok(
- \\{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" }
- );
-}
-
-test "json.test.y_object_with_newlines" {
- ok(
- \\{
- \\"a": "b"
- \\}
- );
-}
-
-test "json.test.y_string_1_2_3_bytes_UTF-8_sequences" {
- ok(
- \\["\u0060\u012a\u12AB"]
- );
-}
-
-test "json.test.y_string_accepted_surrogate_pair" {
- ok(
- \\["\uD801\udc37"]
- );
-}
-
-test "json.test.y_string_accepted_surrogate_pairs" {
- ok(
- \\["\ud83d\ude39\ud83d\udc8d"]
- );
-}
-
-test "json.test.y_string_allowed_escapes" {
- ok(
- \\["\"\\\/\b\f\n\r\t"]
- );
-}
-
-test "json.test.y_string_backslash_and_u_escaped_zero" {
- ok(
- \\["\\u0000"]
- );
-}
-
-test "json.test.y_string_backslash_doublequotes" {
- ok(
- \\["\""]
- );
-}
-
-test "json.test.y_string_comments" {
- ok(
- \\["a/*b*/c/*d//e"]
- );
-}
-
-test "json.test.y_string_double_escape_a" {
- ok(
- \\["\\a"]
- );
-}
-
-test "json.test.y_string_double_escape_n" {
- ok(
- \\["\\n"]
- );
-}
-
-test "json.test.y_string_escaped_control_character" {
- ok(
- \\["\u0012"]
- );
-}
-
-test "json.test.y_string_escaped_noncharacter" {
- ok(
- \\["\uFFFF"]
- );
-}
-
-test "json.test.y_string_in_array" {
- ok(
- \\["asd"]
- );
-}
-
-test "json.test.y_string_in_array_with_leading_space" {
- ok(
- \\[ "asd"]
- );
-}
-
-test "json.test.y_string_last_surrogates_1_and_2" {
- ok(
- \\["\uDBFF\uDFFF"]
- );
-}
-
-test "json.test.y_string_nbsp_uescaped" {
- ok(
- \\["new\u00A0line"]
- );
-}
-
-test "json.test.y_string_nonCharacterInUTF-8_U+10FFFF" {
- ok(
- \\["􏿿"]
- );
-}
-
-test "json.test.y_string_nonCharacterInUTF-8_U+FFFF" {
- ok(
- \\["￿"]
- );
-}
-
-test "json.test.y_string_null_escape" {
- ok(
- \\["\u0000"]
- );
-}
-
-test "json.test.y_string_one-byte-utf-8" {
- ok(
- \\["\u002c"]
- );
-}
-
-test "json.test.y_string_pi" {
- ok(
- \\["π"]
- );
-}
-
-test "json.test.y_string_reservedCharacterInUTF-8_U+1BFFF" {
- ok(
- \\["𛿿"]
- );
-}
-
-test "json.test.y_string_simple_ascii" {
- ok(
- \\["asd "]
- );
-}
-
-test "json.test.y_string_space" {
- ok(
- \\" "
- );
-}
-
-test "json.test.y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" {
- ok(
- \\["\uD834\uDd1e"]
- );
-}
-
-test "json.test.y_string_three-byte-utf-8" {
- ok(
- \\["\u0821"]
- );
-}
-
-test "json.test.y_string_two-byte-utf-8" {
- ok(
- \\["\u0123"]
- );
-}
-
-test "json.test.y_string_u+2028_line_sep" {
- ok("[\"\xe2\x80\xa8\"]");
-}
-
-test "json.test.y_string_u+2029_par_sep" {
- ok("[\"\xe2\x80\xa9\"]");
-}
-
-test "json.test.y_string_uescaped_newline" {
- ok(
- \\["new\u000Aline"]
- );
-}
-
-test "json.test.y_string_uEscape" {
- ok(
- \\["\u0061\u30af\u30EA\u30b9"]
- );
-}
-
-test "json.test.y_string_unescaped_char_delete" {
- ok("[\"\x7f\"]");
-}
-
-test "json.test.y_string_unicode_2" {
- ok(
- \\["⍂㈴⍂"]
- );
-}
-
-test "json.test.y_string_unicodeEscapedBackslash" {
- ok(
- \\["\u005C"]
- );
-}
-
-test "json.test.y_string_unicode_escaped_double_quote" {
- ok(
- \\["\u0022"]
- );
-}
-
-test "json.test.y_string_unicode" {
- ok(
- \\["\uA66D"]
- );
-}
-
-test "json.test.y_string_unicode_U+10FFFE_nonchar" {
- ok(
- \\["\uDBFF\uDFFE"]
- );
-}
-
-test "json.test.y_string_unicode_U+1FFFE_nonchar" {
- ok(
- \\["\uD83F\uDFFE"]
- );
-}
-
-test "json.test.y_string_unicode_U+200B_ZERO_WIDTH_SPACE" {
- ok(
- \\["\u200B"]
- );
-}
-
-test "json.test.y_string_unicode_U+2064_invisible_plus" {
- ok(
- \\["\u2064"]
- );
-}
-
-test "json.test.y_string_unicode_U+FDD0_nonchar" {
- ok(
- \\["\uFDD0"]
- );
-}
-
-test "json.test.y_string_unicode_U+FFFE_nonchar" {
- ok(
- \\["\uFFFE"]
- );
-}
-
-test "json.test.y_string_utf8" {
- ok(
- \\["€𝄞"]
- );
-}
-
-test "json.test.y_string_with_del_character" {
- ok("[\"a\x7fa\"]");
-}
-
-test "json.test.y_structure_lonely_false" {
- ok(
- \\false
- );
-}
-
-test "json.test.y_structure_lonely_int" {
- ok(
- \\42
- );
-}
-
-test "json.test.y_structure_lonely_negative_real" {
- ok(
- \\-0.1
- );
-}
-
-test "json.test.y_structure_lonely_null" {
- ok(
- \\null
- );
-}
-
-test "json.test.y_structure_lonely_string" {
- ok(
- \\"asd"
- );
-}
-
-test "json.test.y_structure_lonely_true" {
- ok(
- \\true
- );
-}
-
-test "json.test.y_structure_string_empty" {
- ok(
- \\""
- );
-}
-
-test "json.test.y_structure_trailing_newline" {
- ok(
- \\["a"]
- );
-}
-
-test "json.test.y_structure_true_in_array" {
- ok(
- \\[true]
- );
-}
-
-test "json.test.y_structure_whitespace_array" {
- ok(" [] ");
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-test "json.test.n_array_1_true_without_comma" {
- err(
- \\[1 true]
- );
-}
-
-test "json.test.n_array_a_invalid_utf8" {
- err(
- \\[aå]
- );
-}
-
-test "json.test.n_array_colon_instead_of_comma" {
- err(
- \\["": 1]
- );
-}
-
-test "json.test.n_array_comma_after_close" {
- //err(
- // \\[""],
- //);
-}
-
-test "json.test.n_array_comma_and_number" {
- err(
- \\[,1]
- );
-}
-
-test "json.test.n_array_double_comma" {
- err(
- \\[1,,2]
- );
-}
-
-test "json.test.n_array_double_extra_comma" {
- err(
- \\["x",,]
- );
-}
-
-test "json.test.n_array_extra_close" {
- err(
- \\["x"]]
- );
-}
-
-test "json.test.n_array_extra_comma" {
- //err(
- // \\["",]
- //);
-}
-
-test "json.test.n_array_incomplete_invalid_value" {
- err(
- \\[x
- );
-}
-
-test "json.test.n_array_incomplete" {
- err(
- \\["x"
- );
-}
-
-test "json.test.n_array_inner_array_no_comma" {
- err(
- \\[3[4]]
- );
-}
-
-test "json.test.n_array_invalid_utf8" {
- err(
- \\[ÿ]
- );
-}
-
-test "json.test.n_array_items_separated_by_semicolon" {
- err(
- \\[1:2]
- );
-}
-
-test "json.test.n_array_just_comma" {
- err(
- \\[,]
- );
-}
-
-test "json.test.n_array_just_minus" {
- err(
- \\[-]
- );
-}
-
-test "json.test.n_array_missing_value" {
- err(
- \\[ , ""]
- );
-}
-
-test "json.test.n_array_newlines_unclosed" {
- err(
- \\["a",
- \\4
- \\,1,
- );
-}
-
-test "json.test.n_array_number_and_comma" {
- err(
- \\[1,]
- );
-}
-
-test "json.test.n_array_number_and_several_commas" {
- err(
- \\[1,,]
- );
-}
-
-test "json.test.n_array_spaces_vertical_tab_formfeed" {
- err("[\"\x0aa\"\\f]");
-}
-
-test "json.test.n_array_star_inside" {
- err(
- \\[*]
- );
-}
-
-test "json.test.n_array_unclosed" {
- err(
- \\[""
- );
-}
-
-test "json.test.n_array_unclosed_trailing_comma" {
- err(
- \\[1,
- );
-}
-
-test "json.test.n_array_unclosed_with_new_lines" {
- err(
- \\[1,
- \\1
- \\,1
- );
-}
-
-test "json.test.n_array_unclosed_with_object_inside" {
- err(
- \\[{}
- );
-}
-
-test "json.test.n_incomplete_false" {
- err(
- \\[fals]
- );
-}
-
-test "json.test.n_incomplete_null" {
- err(
- \\[nul]
- );
-}
-
-test "json.test.n_incomplete_true" {
- err(
- \\[tru]
- );
-}
-
-test "json.test.n_multidigit_number_then_00" {
- err("123\x00");
-}
-
-test "json.test.n_number_0.1.2" {
- err(
- \\[0.1.2]
- );
-}
-
-test "json.test.n_number_-01" {
- err(
- \\[-01]
- );
-}
-
-test "json.test.n_number_0.3e" {
- err(
- \\[0.3e]
- );
-}
-
-test "json.test.n_number_0.3e+" {
- err(
- \\[0.3e+]
- );
-}
-
-test "json.test.n_number_0_capital_E" {
- err(
- \\[0E]
- );
-}
-
-test "json.test.n_number_0_capital_E+" {
- err(
- \\[0E+]
- );
-}
-
-test "json.test.n_number_0.e1" {
- err(
- \\[0.e1]
- );
-}
-
-test "json.test.n_number_0e" {
- err(
- \\[0e]
- );
-}
-
-test "json.test.n_number_0e+" {
- err(
- \\[0e+]
- );
-}
-
-test "json.test.n_number_1_000" {
- err(
- \\[1 000.0]
- );
-}
-
-test "json.test.n_number_1.0e-" {
- err(
- \\[1.0e-]
- );
-}
-
-test "json.test.n_number_1.0e" {
- err(
- \\[1.0e]
- );
-}
-
-test "json.test.n_number_1.0e+" {
- err(
- \\[1.0e+]
- );
-}
-
-test "json.test.n_number_-1.0." {
- err(
- \\[-1.0.]
- );
-}
-
-test "json.test.n_number_1eE2" {
- err(
- \\[1eE2]
- );
-}
-
-test "json.test.n_number_.-1" {
- err(
- \\[.-1]
- );
-}
-
-test "json.test.n_number_+1" {
- err(
- \\[+1]
- );
-}
-
-test "json.test.n_number_.2e-3" {
- err(
- \\[.2e-3]
- );
-}
-
-test "json.test.n_number_2.e-3" {
- err(
- \\[2.e-3]
- );
-}
-
-test "json.test.n_number_2.e+3" {
- err(
- \\[2.e+3]
- );
-}
-
-test "json.test.n_number_2.e3" {
- err(
- \\[2.e3]
- );
-}
-
-test "json.test.n_number_-2." {
- err(
- \\[-2.]
- );
-}
-
-test "json.test.n_number_9.e+" {
- err(
- \\[9.e+]
- );
-}
-
-test "json.test.n_number_expression" {
- err(
- \\[1+2]
- );
-}
-
-test "json.test.n_number_hex_1_digit" {
- err(
- \\[0x1]
- );
-}
-
-test "json.test.n_number_hex_2_digits" {
- err(
- \\[0x42]
- );
-}
-
-test "json.test.n_number_infinity" {
- err(
- \\[Infinity]
- );
-}
-
-test "json.test.n_number_+Inf" {
- err(
- \\[+Inf]
- );
-}
-
-test "json.test.n_number_Inf" {
- err(
- \\[Inf]
- );
-}
-
-test "json.test.n_number_invalid+-" {
- err(
- \\[0e+-1]
- );
-}
-
-test "json.test.n_number_invalid-negative-real" {
- err(
- \\[-123.123foo]
- );
-}
-
-test "json.test.n_number_invalid-utf-8-in-bigger-int" {
- err(
- \\[123å]
- );
-}
-
-test "json.test.n_number_invalid-utf-8-in-exponent" {
- err(
- \\[1e1å]
- );
-}
-
-test "json.test.n_number_invalid-utf-8-in-int" {
- err(
- \\[0å]
- );
-}
-
-test "json.test.n_number_++" {
- err(
- \\[++1234]
- );
-}
-
-test "json.test.n_number_minus_infinity" {
- err(
- \\[-Infinity]
- );
-}
-
-test "json.test.n_number_minus_sign_with_trailing_garbage" {
- err(
- \\[-foo]
- );
-}
-
-test "json.test.n_number_minus_space_1" {
- err(
- \\[- 1]
- );
-}
-
-test "json.test.n_number_-NaN" {
- err(
- \\[-NaN]
- );
-}
-
-test "json.test.n_number_NaN" {
- err(
- \\[NaN]
- );
-}
-
-test "json.test.n_number_neg_int_starting_with_zero" {
- err(
- \\[-012]
- );
-}
-
-test "json.test.n_number_neg_real_without_int_part" {
- err(
- \\[-.123]
- );
-}
-
-test "json.test.n_number_neg_with_garbage_at_end" {
- err(
- \\[-1x]
- );
-}
-
-test "json.test.n_number_real_garbage_after_e" {
- err(
- \\[1ea]
- );
-}
-
-test "json.test.n_number_real_with_invalid_utf8_after_e" {
- err(
- \\[1eå]
- );
-}
-
-test "json.test.n_number_real_without_fractional_part" {
- err(
- \\[1.]
- );
-}
-
-test "json.test.n_number_starting_with_dot" {
- err(
- \\[.123]
- );
-}
-
-test "json.test.n_number_U+FF11_fullwidth_digit_one" {
- err(
- \\[1]
- );
-}
-
-test "json.test.n_number_with_alpha_char" {
- err(
- \\[1.8011670033376514H-308]
- );
-}
-
-test "json.test.n_number_with_alpha" {
- err(
- \\[1.2a-3]
- );
-}
-
-test "json.test.n_number_with_leading_zero" {
- err(
- \\[012]
- );
-}
-
-test "json.test.n_object_bad_value" {
- err(
- \\["x", truth]
- );
-}
-
-test "json.test.n_object_bracket_key" {
- err(
- \\{[: "x"}
- );
-}
-
-test "json.test.n_object_comma_instead_of_colon" {
- err(
- \\{"x", null}
- );
-}
-
-test "json.test.n_object_double_colon" {
- err(
- \\{"x"::"b"}
- );
-}
-
-test "json.test.n_object_emoji" {
- err(
- \\{🇨🇭}
- );
-}
-
-test "json.test.n_object_garbage_at_end" {
- err(
- \\{"a":"a" 123}
- );
-}
-
-test "json.test.n_object_key_with_single_quotes" {
- err(
- \\{key: 'value'}
- );
-}
-
-test "json.test.n_object_lone_continuation_byte_in_key_and_trailing_comma" {
- err(
- \\{"¹":"0",}
- );
-}
-
-test "json.test.n_object_missing_colon" {
- err(
- \\{"a" b}
- );
-}
-
-test "json.test.n_object_missing_key" {
- err(
- \\{:"b"}
- );
-}
-
-test "json.test.n_object_missing_semicolon" {
- err(
- \\{"a" "b"}
- );
-}
-
-test "json.test.n_object_missing_value" {
- err(
- \\{"a":
- );
-}
-
-test "json.test.n_object_no-colon" {
- err(
- \\{"a"
- );
-}
-
-test "json.test.n_object_non_string_key_but_huge_number_instead" {
- err(
- \\{9999E9999:1}
- );
-}
-
-test "json.test.n_object_non_string_key" {
- err(
- \\{1:1}
- );
-}
-
-test "json.test.n_object_repeated_null_null" {
- err(
- \\{null:null,null:null}
- );
-}
-
-test "json.test.n_object_several_trailing_commas" {
- err(
- \\{"id":0,,,,,}
- );
-}
-
-test "json.test.n_object_single_quote" {
- err(
- \\{'a':0}
- );
-}
-
-test "json.test.n_object_trailing_comma" {
- err(
- \\{"id":0,}
- );
-}
-
-test "json.test.n_object_trailing_comment" {
- err(
- \\{"a":"b"}/**/
- );
-}
-
-test "json.test.n_object_trailing_comment_open" {
- err(
- \\{"a":"b"}/**//
- );
-}
-
-test "json.test.n_object_trailing_comment_slash_open_incomplete" {
- err(
- \\{"a":"b"}/
- );
-}
-
-test "json.test.n_object_trailing_comment_slash_open" {
- err(
- \\{"a":"b"}//
- );
-}
-
-test "json.test.n_object_two_commas_in_a_row" {
- err(
- \\{"a":"b",,"c":"d"}
- );
-}
-
-test "json.test.n_object_unquoted_key" {
- err(
- \\{a: "b"}
- );
-}
-
-test "json.test.n_object_unterminated-value" {
- err(
- \\{"a":"a
- );
-}
-
-test "json.test.n_object_with_single_string" {
- err(
- \\{ "foo" : "bar", "a" }
- );
-}
-
-test "json.test.n_object_with_trailing_garbage" {
- err(
- \\{"a":"b"}#
- );
-}
-
-test "json.test.n_single_space" {
- err(" ");
-}
-
-test "json.test.n_string_1_surrogate_then_escape" {
- err(
- \\["\uD800\"]
- );
-}
-
-test "json.test.n_string_1_surrogate_then_escape_u1" {
- err(
- \\["\uD800\u1"]
- );
-}
-
-test "json.test.n_string_1_surrogate_then_escape_u1x" {
- err(
- \\["\uD800\u1x"]
- );
-}
-
-test "json.test.n_string_1_surrogate_then_escape_u" {
- err(
- \\["\uD800\u"]
- );
-}
-
-test "json.test.n_string_accentuated_char_no_quotes" {
- err(
- \\[é]
- );
-}
-
-test "json.test.n_string_backslash_00" {
- err("[\"\x00\"]");
-}
-
-test "json.test.n_string_escaped_backslash_bad" {
- err(
- \\["\\\"]
- );
-}
-
-test "json.test.n_string_escaped_ctrl_char_tab" {
- err("\x5b\x22\x5c\x09\x22\x5d");
-}
-
-test "json.test.n_string_escaped_emoji" {
- err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]");
-}
-
-test "json.test.n_string_escape_x" {
- err(
- \\["\x00"]
- );
-}
-
-test "json.test.n_string_incomplete_escaped_character" {
- err(
- \\["\u00A"]
- );
-}
-
-test "json.test.n_string_incomplete_escape" {
- err(
- \\["\"]
- );
-}
-
-test "json.test.n_string_incomplete_surrogate_escape_invalid" {
- err(
- \\["\uD800\uD800\x"]
- );
-}
-
-test "json.test.n_string_incomplete_surrogate" {
- err(
- \\["\uD834\uDd"]
- );
-}
-
-test "json.test.n_string_invalid_backslash_esc" {
- err(
- \\["\a"]
- );
-}
-
-test "json.test.n_string_invalid_unicode_escape" {
- err(
- \\["\uqqqq"]
- );
-}
-
-test "json.test.n_string_invalid_utf8_after_escape" {
- err("[\"\\\x75\xc3\xa5\"]");
-}
-
-test "json.test.n_string_invalid-utf-8-in-escape" {
- err(
- \\["\uå"]
- );
-}
-
-test "json.test.n_string_leading_uescaped_thinspace" {
- err(
- \\[\u0020"asd"]
- );
-}
-
-test "json.test.n_string_no_quotes_with_bad_escape" {
- err(
- \\[\n]
- );
-}
-
-test "json.test.n_string_single_doublequote" {
- err(
- \\"
- );
-}
-
-test "json.test.n_string_single_quote" {
- err(
- \\['single quote']
- );
-}
-
-test "json.test.n_string_single_string_no_double_quotes" {
- err(
- \\abc
- );
-}
-
-test "json.test.n_string_start_escape_unclosed" {
- err(
- \\["\
- );
-}
-
-test "json.test.n_string_unescaped_crtl_char" {
- err("[\"a\x00a\"]");
-}
-
-test "json.test.n_string_unescaped_newline" {
- err(
- \\["new
- \\line"]
- );
-}
-
-test "json.test.n_string_unescaped_tab" {
- err("[\"\t\"]");
-}
-
-test "json.test.n_string_unicode_CapitalU" {
- err(
- \\"\UA66D"
- );
-}
-
-test "json.test.n_string_with_trailing_garbage" {
- err(
- \\""x
- );
-}
-
-test "json.test.n_structure_100000_opening_arrays" {
- err("[" ** 100000);
-}
-
-test "json.test.n_structure_angle_bracket_." {
- err(
- \\<.>
- );
-}
-
-test "json.test.n_structure_angle_bracket_null" {
- err(
- \\[<null>]
- );
-}
-
-test "json.test.n_structure_array_trailing_garbage" {
- err(
- \\[1]x
- );
-}
-
-test "json.test.n_structure_array_with_extra_array_close" {
- err(
- \\[1]]
- );
-}
-
-test "json.test.n_structure_array_with_unclosed_string" {
- err(
- \\["asd]
- );
-}
-
-test "json.test.n_structure_ascii-unicode-identifier" {
- err(
- \\aå
- );
-}
-
-test "json.test.n_structure_capitalized_True" {
- err(
- \\[True]
- );
-}
-
-test "json.test.n_structure_close_unopened_array" {
- err(
- \\1]
- );
-}
-
-test "json.test.n_structure_comma_instead_of_closing_brace" {
- err(
- \\{"x": true,
- );
-}
-
-test "json.test.n_structure_double_array" {
- err(
- \\[][]
- );
-}
-
-test "json.test.n_structure_end_array" {
- err(
- \\]
- );
-}
-
-test "json.test.n_structure_incomplete_UTF8_BOM" {
- err(
- \\ï»{}
- );
-}
-
-test "json.test.n_structure_lone-invalid-utf-8" {
- err(
- \\å
- );
-}
-
-test "json.test.n_structure_lone-open-bracket" {
- err(
- \\[
- );
-}
-
-test "json.test.n_structure_no_data" {
- err(
- \\
- );
-}
-
-test "json.test.n_structure_null-byte-outside-string" {
- err("[\x00]");
-}
-
-test "json.test.n_structure_number_with_trailing_garbage" {
- err(
- \\2@
- );
-}
-
-test "json.test.n_structure_object_followed_by_closing_object" {
- err(
- \\{}}
- );
-}
-
-test "json.test.n_structure_object_unclosed_no_value" {
- err(
- \\{"":
- );
-}
-
-test "json.test.n_structure_object_with_comment" {
- err(
- \\{"a":/*comment*/"b"}
- );
-}
-
-test "json.test.n_structure_object_with_trailing_garbage" {
- err(
- \\{"a": true} "x"
- );
-}
-
-test "json.test.n_structure_open_array_apostrophe" {
- err(
- \\['
- );
-}
-
-test "json.test.n_structure_open_array_comma" {
- err(
- \\[,
- );
-}
-
-test "json.test.n_structure_open_array_object" {
- err("[{\"\":" ** 50000);
-}
-
-test "json.test.n_structure_open_array_open_object" {
- err(
- \\[{
- );
-}
-
-test "json.test.n_structure_open_array_open_string" {
- err(
- \\["a
- );
-}
-
-test "json.test.n_structure_open_array_string" {
- err(
- \\["a"
- );
-}
-
-test "json.test.n_structure_open_object_close_array" {
- err(
- \\{]
- );
-}
-
-test "json.test.n_structure_open_object_comma" {
- err(
- \\{,
- );
-}
-
-test "json.test.n_structure_open_object" {
- err(
- \\{
- );
-}
-
-test "json.test.n_structure_open_object_open_array" {
- err(
- \\{[
- );
-}
-
-test "json.test.n_structure_open_object_open_string" {
- err(
- \\{"a
- );
-}
-
-test "json.test.n_structure_open_object_string_with_apostrophes" {
- err(
- \\{'a'
- );
-}
-
-test "json.test.n_structure_open_open" {
- err(
- \\["\{["\{["\{["\{
- );
-}
-
-test "json.test.n_structure_single_eacute" {
- err(
- \\é
- );
-}
-
-test "json.test.n_structure_single_star" {
- err(
- \\*
- );
-}
-
-test "json.test.n_structure_trailing_#" {
- err(
- \\{"a":"b"}#{}
- );
-}
-
-test "json.test.n_structure_U+2060_word_joined" {
- err(
- \\[⁠]
- );
-}
-
-test "json.test.n_structure_uescaped_LF_before_string" {
- err(
- \\[\u000A""]
- );
-}
-
-test "json.test.n_structure_unclosed_array" {
- err(
- \\[1
- );
-}
-
-test "json.test.n_structure_unclosed_array_partial_null" {
- err(
- \\[ false, nul
- );
-}
-
-test "json.test.n_structure_unclosed_array_unfinished_false" {
- err(
- \\[ true, fals
- );
-}
-
-test "json.test.n_structure_unclosed_array_unfinished_true" {
- err(
- \\[ false, tru
- );
-}
-
-test "json.test.n_structure_unclosed_object" {
- err(
- \\{"asd":"asd"
- );
-}
-
-test "json.test.n_structure_unicode-identifier" {
- err(
- \\Ã¥
- );
-}
-
-test "json.test.n_structure_UTF8_BOM_no_data" {
- err(
- \\
- );
-}
-
-test "json.test.n_structure_whitespace_formfeed" {
- err("[\x0c]");
-}
-
-test "json.test.n_structure_whitespace_U+2060_word_joiner" {
- err(
- \\[⁠]
- );
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-test "json.test.i_number_double_huge_neg_exp" {
- any(
- \\[123.456e-789]
- );
-}
-
-test "json.test.i_number_huge_exp" {
- any(
- \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]
- );
-}
-
-test "json.test.i_number_neg_int_huge_exp" {
- any(
- \\[-1e+9999]
- );
-}
-
-test "json.test.i_number_pos_double_huge_exp" {
- any(
- \\[1.5e+9999]
- );
-}
-
-test "json.test.i_number_real_neg_overflow" {
- any(
- \\[-123123e100000]
- );
-}
-
-test "json.test.i_number_real_pos_overflow" {
- any(
- \\[123123e100000]
- );
-}
-
-test "json.test.i_number_real_underflow" {
- any(
- \\[123e-10000000]
- );
-}
-
-test "json.test.i_number_too_big_neg_int" {
- any(
- \\[-123123123123123123123123123123]
- );
-}
-
-test "json.test.i_number_too_big_pos_int" {
- any(
- \\[100000000000000000000]
- );
-}
-
-test "json.test.i_number_very_big_negative_int" {
- any(
- \\[-237462374673276894279832749832423479823246327846]
- );
-}
-
-test "json.test.i_object_key_lone_2nd_surrogate" {
- any(
- \\{"\uDFAA":0}
- );
-}
-
-test "json.test.i_string_1st_surrogate_but_2nd_missing" {
- any(
- \\["\uDADA"]
- );
-}
-
-test "json.test.i_string_1st_valid_surrogate_2nd_invalid" {
- any(
- \\["\uD888\u1234"]
- );
-}
-
-test "json.test.i_string_incomplete_surrogate_and_escape_valid" {
- any(
- \\["\uD800\n"]
- );
-}
-
-test "json.test.i_string_incomplete_surrogate_pair" {
- any(
- \\["\uDd1ea"]
- );
-}
-
-test "json.test.i_string_incomplete_surrogates_escape_valid" {
- any(
- \\["\uD800\uD800\n"]
- );
-}
-
-test "json.test.i_string_invalid_lonely_surrogate" {
- any(
- \\["\ud800"]
- );
-}
-
-test "json.test.i_string_invalid_surrogate" {
- any(
- \\["\ud800abc"]
- );
-}
-
-test "json.test.i_string_invalid_utf-8" {
- any(
- \\["ÿ"]
- );
-}
-
-test "json.test.i_string_inverted_surrogates_U+1D11E" {
- any(
- \\["\uDd1e\uD834"]
- );
-}
-
-test "json.test.i_string_iso_latin_1" {
- any(
- \\["é"]
- );
-}
-
-test "json.test.i_string_lone_second_surrogate" {
- any(
- \\["\uDFAA"]
- );
-}
-
-test "json.test.i_string_lone_utf8_continuation_byte" {
- any(
- \\[""]
- );
-}
-
-test "json.test.i_string_not_in_unicode_range" {
- any(
- \\["ô¿¿¿"]
- );
-}
-
-test "json.test.i_string_overlong_sequence_2_bytes" {
- any(
- \\["À¯"]
- );
-}
-
-test "json.test.i_string_overlong_sequence_6_bytes" {
- any(
- \\["üƒ¿¿¿¿"]
- );
-}
-
-test "json.test.i_string_overlong_sequence_6_bytes_null" {
- any(
- \\["ü€€€€€"]
- );
-}
-
-test "json.test.i_string_truncated-utf-8" {
- any(
- \\["àÿ"]
- );
-}
-
-test "json.test.i_string_utf16BE_no_BOM" {
- any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d");
-}
-
-test "json.test.i_string_utf16LE_no_BOM" {
- any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
-}
-
-test "json.test.i_string_UTF-16LE_with_BOM" {
- any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
-}
-
-test "json.test.i_string_UTF-8_invalid_sequence" {
- any(
- \\["日шú"]
- );
-}
-
-test "json.test.i_string_UTF8_surrogate_U+D800" {
- any(
- \\["í €"]
- );
-}
-
-test "json.test.i_structure_500_nested_arrays" {
- any(("[" ** 500) ++ ("]" ** 500));
-}
-
-test "json.test.i_structure_UTF-8_BOM_empty_object" {
- any(
- \\{}
- );
-}
diff --git a/std/math/acos.zig b/std/math/acos.zig
index 763d9d8abd..de07da8fe0 100644
--- a/std/math/acos.zig
+++ b/std/math/acos.zig
@@ -1,11 +1,17 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - acos(x) = nan if x < -1 or x > 1
+// https://git.musl-libc.org/cgit/musl/tree/src/math/acosf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/acos.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the arc-cosine of x.
+///
+/// Special cases:
+/// - acos(x) = nan if x < -1 or x > 1
pub fn acos(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/acosh.zig b/std/math/acosh.zig
index a2a9926863..503c0433fc 100644
--- a/std/math/acosh.zig
+++ b/std/math/acosh.zig
@@ -1,13 +1,19 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - acosh(x) = snan if x < 1
-// - acosh(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/acoshf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/acosh.c
const builtin = @import("builtin");
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the hyperbolic arc-cosine of x.
+///
+/// Special cases:
+/// - acosh(x) = snan if x < 1
+/// - acosh(nan) = nan
pub fn acosh(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/asin.zig b/std/math/asin.zig
index b01a1ac49e..2db9f86ff1 100644
--- a/std/math/asin.zig
+++ b/std/math/asin.zig
@@ -1,12 +1,18 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - asin(+-0) = +-0
-// - asin(x) = nan if x < -1 or x > 1
+// https://git.musl-libc.org/cgit/musl/tree/src/math/asinf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/asin.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the arc-sin of x.
+///
+/// Special Cases:
+/// - asin(+-0) = +-0
+/// - asin(x) = nan if x < -1 or x > 1
pub fn asin(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/asinh.zig b/std/math/asinh.zig
index cef9bfb23f..0fb51d1b43 100644
--- a/std/math/asinh.zig
+++ b/std/math/asinh.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - asinh(+-0) = +-0
-// - asinh(+-inf) = +-inf
-// - asinh(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/asinhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/asinh.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns the hyperbolic arc-sin of x.
+///
+/// Special Cases:
+/// - asinh(+-0) = +-0
+/// - asinh(+-inf) = +-inf
+/// - asinh(nan) = nan
pub fn asinh(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/atan.zig b/std/math/atan.zig
index ba5a11dd10..cc4cad0dd4 100644
--- a/std/math/atan.zig
+++ b/std/math/atan.zig
@@ -1,12 +1,18 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - atan(+-0) = +-0
-// - atan(+-inf) = +-pi/2
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atanf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atan.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the arc-tangent of x.
+///
+/// Special Cases:
+/// - atan(+-0) = +-0
+/// - atan(+-inf) = +-pi/2
pub fn atan(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/atan2.zig b/std/math/atan2.zig
index 7f13507402..68e381607d 100644
--- a/std/math/atan2.zig
+++ b/std/math/atan2.zig
@@ -1,27 +1,33 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// atan2(y, nan) = nan
-// atan2(nan, x) = nan
-// atan2(+0, x>=0) = +0
-// atan2(-0, x>=0) = -0
-// atan2(+0, x<=-0) = +pi
-// atan2(-0, x<=-0) = -pi
-// atan2(y>0, 0) = +pi/2
-// atan2(y<0, 0) = -pi/2
-// atan2(+inf, +inf) = +pi/4
-// atan2(-inf, +inf) = -pi/4
-// atan2(+inf, -inf) = 3pi/4
-// atan2(-inf, -inf) = -3pi/4
-// atan2(y, +inf) = 0
-// atan2(y>0, -inf) = +pi
-// atan2(y<0, -inf) = -pi
-// atan2(+inf, x) = +pi/2
-// atan2(-inf, x) = -pi/2
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atan2f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atan2.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the arc-tangent of y/x.
+///
+/// Special Cases:
+/// - atan2(y, nan) = nan
+/// - atan2(nan, x) = nan
+/// - atan2(+0, x>=0) = +0
+/// - atan2(-0, x>=0) = -0
+/// - atan2(+0, x<=-0) = +pi
+/// - atan2(-0, x<=-0) = -pi
+/// - atan2(y>0, 0) = +pi/2
+/// - atan2(y<0, 0) = -pi/2
+/// - atan2(+inf, +inf) = +pi/4
+/// - atan2(-inf, +inf) = -pi/4
+/// - atan2(+inf, -inf) = 3pi/4
+/// - atan2(-inf, -inf) = -3pi/4
+/// - atan2(y, +inf) = 0
+/// - atan2(y>0, -inf) = +pi
+/// - atan2(y<0, -inf) = -pi
+/// - atan2(+inf, x) = +pi/2
+/// - atan2(-inf, x) = -pi/2
pub fn atan2(comptime T: type, y: T, x: T) T {
return switch (T) {
f32 => atan2_32(y, x),
diff --git a/std/math/atanh.zig b/std/math/atanh.zig
index 9056064f5a..8ba29be761 100644
--- a/std/math/atanh.zig
+++ b/std/math/atanh.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - atanh(+-1) = +-inf with signal
-// - atanh(x) = nan if |x| > 1 with signal
-// - atanh(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atanhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atanh.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns the hyperbolic arc-tangent of x.
+///
+/// Special Cases:
+/// - atanh(+-1) = +-inf with signal
+/// - atanh(x) = nan if |x| > 1 with signal
+/// - atanh(nan) = nan
pub fn atanh(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/big.zig b/std/math/big.zig
index 94b6d864e7..44b5ce675f 100644
--- a/std/math/big.zig
+++ b/std/math/big.zig
@@ -1,5 +1,7 @@
pub use @import("big/int.zig");
+pub use @import("big/rational.zig");
test "math.big" {
_ = @import("big/int.zig");
+ _ = @import("big/rational.zig");
}
diff --git a/std/math/big/int.zig b/std/math/big/int.zig
index 8800c2c7a9..beac3c85fe 100644
--- a/std/math/big/int.zig
+++ b/std/math/big/int.zig
@@ -21,78 +21,160 @@ comptime {
debug.assert(Limb.is_signed == false);
}
+/// An arbitrary-precision big integer.
+///
+/// Memory is allocated by an Int as needed to ensure operations never overflow. The range of an
+/// Int is bounded only by available memory.
pub const Int = struct {
- allocator: *Allocator,
- positive: bool,
- // - little-endian ordered
- // - len >= 1 always
- // - zero value -> len == 1 with limbs[0] == 0
+ const sign_bit: usize = 1 << (usize.bit_count - 1);
+
+ /// Default number of limbs to allocate on creation of an Int.
+ pub const default_capacity = 4;
+
+ /// Allocator used by the Int when requesting memory.
+ allocator: ?*Allocator,
+
+ /// Raw digits. These are:
+ ///
+ /// * Little-endian ordered
+ /// * limbs.len >= 1
+ /// * Zero is represent as Int.len() == 1 with limbs[0] == 0.
+ ///
+ /// Accessing limbs directly should be avoided.
limbs: []Limb,
- len: usize,
- const default_capacity = 4;
+ /// High bit is the sign bit. If set, Int is negative, else Int is positive.
+ /// The remaining bits represent the number of limbs used by Int.
+ metadata: usize,
+ /// Creates a new Int. default_capacity limbs will be allocated immediately.
+ /// Int will be zeroed.
pub fn init(allocator: *Allocator) !Int {
return try Int.initCapacity(allocator, default_capacity);
}
+ /// Creates a new Int. Int will be set to `value`.
+ ///
+ /// This is identical to an `init`, followed by a `set`.
pub fn initSet(allocator: *Allocator, value: var) !Int {
var s = try Int.init(allocator);
try s.set(value);
return s;
}
+ /// Creates a new Int with a specific capacity. If capacity < default_capacity then the
+ /// default capacity will be used instead.
pub fn initCapacity(allocator: *Allocator, capacity: usize) !Int {
return Int{
.allocator = allocator,
- .positive = true,
+ .metadata = 1,
.limbs = block: {
var limbs = try allocator.alloc(Limb, math.max(default_capacity, capacity));
limbs[0] = 0;
break :block limbs;
},
- .len = 1,
};
}
+ /// Returns the number of limbs currently in use.
+ pub fn len(self: Int) usize {
+ return self.metadata & ~sign_bit;
+ }
+
+ /// Returns whether an Int is positive.
+ pub fn isPositive(self: Int) bool {
+ return self.metadata & sign_bit == 0;
+ }
+
+ /// Sets the sign of an Int.
+ pub fn setSign(self: *Int, positive: bool) void {
+ if (positive) {
+ self.metadata &= ~sign_bit;
+ } else {
+ self.metadata |= sign_bit;
+ }
+ }
+
+ /// Sets the length of an Int.
+ ///
+ /// If setLen is used, then the Int must be normalized to suit.
+ pub fn setLen(self: *Int, new_len: usize) void {
+ self.metadata &= sign_bit;
+ self.metadata |= new_len;
+ }
+
+ /// Returns an Int backed by a fixed set of limb values.
+ /// This is read-only and cannot be used as a result argument. If the Int tries to allocate
+ /// memory a runtime panic will occur.
+ pub fn initFixed(limbs: []const Limb) Int {
+ var self = Int{
+ .allocator = null,
+ .metadata = limbs.len,
+ // Cast away the const, invalid use to pass as a pointer argument.
+ .limbs = @intToPtr([*]Limb, @ptrToInt(limbs.ptr))[0..limbs.len],
+ };
+
+ self.normalize(limbs.len);
+ return self;
+ }
+
+ /// Ensures an Int has enough space allocated for capacity limbs. If the Int does not have
+ /// sufficient capacity, the exact amount will be allocated. This occurs even if the requested
+ /// capacity is only greater than the current capacity by one limb.
pub fn ensureCapacity(self: *Int, capacity: usize) !void {
+ self.assertWritable();
if (capacity <= self.limbs.len) {
return;
}
- self.limbs = try self.allocator.realloc(self.limbs, capacity);
+ self.limbs = try self.allocator.?.realloc(self.limbs, capacity);
}
+ fn assertWritable(self: Int) void {
+ if (self.allocator == null) {
+ @panic("provided Int value is read-only but must be writable");
+ }
+ }
+
+ /// Frees all memory associated with an Int.
pub fn deinit(self: *Int) void {
- self.allocator.free(self.limbs);
+ self.assertWritable();
+ self.allocator.?.free(self.limbs);
self.* = undefined;
}
+ /// Clones an Int and returns a new Int with the same value. The new Int is a deep copy and
+ /// can be modified separately from the original.
pub fn clone(other: Int) !Int {
+ other.assertWritable();
return Int{
.allocator = other.allocator,
- .positive = other.positive,
+ .metadata = other.metadata,
.limbs = block: {
- var limbs = try other.allocator.alloc(Limb, other.len);
- mem.copy(Limb, limbs[0..], other.limbs[0..other.len]);
+ var limbs = try other.allocator.?.alloc(Limb, other.len());
+ mem.copy(Limb, limbs[0..], other.limbs[0..other.len()]);
break :block limbs;
},
- .len = other.len,
};
}
+ /// Copies the value of an Int to an existing Int so that they both have the same value.
+ /// Extra memory will be allocated if the receiver does not have enough capacity.
pub fn copy(self: *Int, other: Int) !void {
- if (self == &other) {
+ self.assertWritable();
+ if (self.limbs.ptr == other.limbs.ptr) {
return;
}
- self.positive = other.positive;
- try self.ensureCapacity(other.len);
- mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len]);
- self.len = other.len;
+ try self.ensureCapacity(other.len());
+ mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len()]);
+ self.metadata = other.metadata;
}
+ /// Efficiently swap an Int with another. This swaps the limb pointers and a full copy is not
+ /// performed. The address of the limbs field will not be the same after this function.
pub fn swap(self: *Int, other: *Int) void {
+ self.assertWritable();
mem.swap(Int, self, other);
}
@@ -103,45 +185,49 @@ pub const Int = struct {
debug.warn("\n");
}
- pub fn negate(r: *Int) void {
- r.positive = !r.positive;
+ /// Negate the sign of an Int.
+ pub fn negate(self: *Int) void {
+ self.metadata ^= sign_bit;
}
- pub fn abs(r: *Int) void {
- r.positive = true;
+ /// Make an Int positive.
+ pub fn abs(self: *Int) void {
+ self.metadata &= ~sign_bit;
}
- pub fn isOdd(r: Int) bool {
- return r.limbs[0] & 1 != 0;
+ /// Returns true if an Int is odd.
+ pub fn isOdd(self: Int) bool {
+ return self.limbs[0] & 1 != 0;
}
- pub fn isEven(r: Int) bool {
- return !r.isOdd();
+ /// Returns true if an Int is even.
+ pub fn isEven(self: Int) bool {
+ return !self.isOdd();
}
- // Returns the number of bits required to represent the absolute value of self.
+ /// Returns the number of bits required to represent the absolute value an Int.
fn bitCountAbs(self: Int) usize {
- return (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1]));
+ return (self.len() - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len() - 1]));
}
- // Returns the number of bits required to represent the integer in twos-complement form.
- //
- // If the integer is negative the value returned is the number of bits needed by a signed
- // integer to represent the value. If positive the value is the number of bits for an
- // unsigned integer. Any unsigned integer will fit in the signed integer with bitcount
- // one greater than the returned value.
- //
- // e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7.
+ /// Returns the number of bits required to represent the integer in twos-complement form.
+ ///
+ /// If the integer is negative the value returned is the number of bits needed by a signed
+ /// integer to represent the value. If positive the value is the number of bits for an
+ /// unsigned integer. Any unsigned integer will fit in the signed integer with bitcount
+ /// one greater than the returned value.
+ ///
+ /// e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7.
fn bitCountTwosComp(self: Int) usize {
var bits = self.bitCountAbs();
// If the entire value has only one bit set (e.g. 0b100000000) then the negation in twos
// complement requires one less bit.
- if (!self.positive) block: {
+ if (!self.isPositive()) block: {
bits += 1;
- if (@popCount(self.limbs[self.len - 1]) == 1) {
- for (self.limbs[0 .. self.len - 1]) |limb| {
+ if (@popCount(self.limbs[self.len() - 1]) == 1) {
+ for (self.limbs[0 .. self.len() - 1]) |limb| {
if (@popCount(limb) != 0) {
break :block;
}
@@ -154,31 +240,34 @@ pub const Int = struct {
return bits;
}
- pub fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool {
+ fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool {
if (self.eqZero()) {
return true;
}
- if (!is_signed and !self.positive) {
+ if (!is_signed and !self.isPositive()) {
return false;
}
- const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and is_signed);
+ const req_bits = self.bitCountTwosComp() + @boolToInt(self.isPositive() and is_signed);
return bit_count >= req_bits;
}
+ /// Returns whether self can fit into an integer of the requested type.
pub fn fits(self: Int, comptime T: type) bool {
return self.fitsInTwosComp(T.is_signed, T.bit_count);
}
- // Returns the approximate size of the integer in the given base. Negative values accommodate for
- // the minus sign. This is used for determining the number of characters needed to print the
- // value. It is inexact and will exceed the given value by 1-2 digits.
+ /// Returns the approximate size of the integer in the given base. Negative values accommodate for
+ /// the minus sign. This is used for determining the number of characters needed to print the
+ /// value. It is inexact and may exceed the given value by ~1-2 bytes.
pub fn sizeInBase(self: Int, base: usize) usize {
- const bit_count = usize(@boolToInt(!self.positive)) + self.bitCountAbs();
+ const bit_count = usize(@boolToInt(!self.isPositive())) + self.bitCountAbs();
return (bit_count / math.log2(base)) + 1;
}
+ /// Sets an Int to value. Value must be an primitive integer type.
pub fn set(self: *Int, value: var) Allocator.Error!void {
+ self.assertWritable();
const T = @typeOf(value);
switch (@typeInfo(T)) {
@@ -186,19 +275,19 @@ pub const Int = struct {
const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T;
try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb));
- self.positive = value >= 0;
- self.len = 0;
+ self.metadata = 0;
+ self.setSign(value >= 0);
var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value);
if (info.bits <= Limb.bit_count) {
self.limbs[0] = Limb(w_value);
- self.len = 1;
+ self.metadata += 1;
} else {
var i: usize = 0;
while (w_value != 0) : (i += 1) {
self.limbs[i] = @truncate(Limb, w_value);
- self.len += 1;
+ self.metadata += 1;
// TODO: shift == 64 at compile-time fails. Fails on u128 limbs.
w_value >>= Limb.bit_count / 2;
@@ -212,8 +301,8 @@ pub const Int = struct {
const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1;
try self.ensureCapacity(req_limbs);
- self.positive = value >= 0;
- self.len = req_limbs;
+ self.metadata = req_limbs;
+ self.setSign(value >= 0);
if (w_value <= maxInt(Limb)) {
self.limbs[0] = w_value;
@@ -240,6 +329,9 @@ pub const Int = struct {
TargetTooSmall,
};
+ /// Convert self to type T.
+ ///
+ /// Returns an error if self cannot be narrowed into the requested type without truncation.
pub fn to(self: Int, comptime T: type) ConvertError!T {
switch (@typeId(T)) {
TypeId.Int => {
@@ -254,17 +346,17 @@ pub const Int = struct {
if (@sizeOf(UT) <= @sizeOf(Limb)) {
r = @intCast(UT, self.limbs[0]);
} else {
- for (self.limbs[0..self.len]) |_, ri| {
- const limb = self.limbs[self.len - ri - 1];
+ for (self.limbs[0..self.len()]) |_, ri| {
+ const limb = self.limbs[self.len() - ri - 1];
r <<= Limb.bit_count;
r |= limb;
}
}
if (!T.is_signed) {
- return if (self.positive) @intCast(T, r) else error.NegativeIntoUnsigned;
+ return if (self.isPositive()) @intCast(T, r) else error.NegativeIntoUnsigned;
} else {
- if (self.positive) {
+ if (self.isPositive()) {
return @intCast(T, r);
} else {
if (math.cast(T, r)) |ok| {
@@ -303,7 +395,15 @@ pub const Int = struct {
};
}
+ /// Set self from the string representation `value`.
+ ///
+ /// value must contain only digits <= `base`. Base prefixes are not allowed (e.g. 0x43 should
+ /// simply be 43).
+ ///
+ /// Returns an error if memory could not be allocated or `value` has invalid digits for the
+ /// requested base.
pub fn setString(self: *Int, base: u8, value: []const u8) !void {
+ self.assertWritable();
if (base < 2 or base > 16) {
return error.InvalidBase;
}
@@ -315,27 +415,22 @@ pub const Int = struct {
i += 1;
}
- // TODO values less than limb size should guarantee non allocating
- var base_buffer: [512]u8 = undefined;
- const base_al = &std.heap.FixedBufferAllocator.init(base_buffer[0..]).allocator;
- const base_ap = try Int.initSet(base_al, base);
-
- var d_buffer: [512]u8 = undefined;
- var d_fba = std.heap.FixedBufferAllocator.init(d_buffer[0..]);
- const d_al = &d_fba.allocator;
-
+ const ap_base = Int.initFixed(([]Limb{base})[0..]);
try self.set(0);
+
for (value[i..]) |ch| {
const d = try charToDigit(ch, base);
- d_fba.end_index = 0;
- const d_ap = try Int.initSet(d_al, d);
- try self.mul(self.*, base_ap);
- try self.add(self.*, d_ap);
+ const ap_d = Int.initFixed(([]Limb{d})[0..]);
+
+ try self.mul(self.*, ap_base);
+ try self.add(self.*, ap_d);
}
- self.positive = positive;
+ self.setSign(positive);
}
+ /// Converts self to a string in the requested base. Memory is allocated from the provided
+ /// allocator and not the one present in self.
/// TODO make this call format instead of the other way around
pub fn toString(self: Int, allocator: *Allocator, base: u8) ![]const u8 {
if (base < 2 or base > 16) {
@@ -355,7 +450,7 @@ pub const Int = struct {
if (base & (base - 1) == 0) {
const base_shift = math.log2_int(Limb, base);
- for (self.limbs[0..self.len]) |limb| {
+ for (self.limbs[0..self.len()]) |limb| {
var shift: usize = 0;
while (shift < Limb.bit_count) : (shift += base_shift) {
const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & Limb(base - 1));
@@ -382,11 +477,11 @@ pub const Int = struct {
}
var q = try self.clone();
- q.positive = true;
+ q.abs();
var r = try Int.init(allocator);
var b = try Int.initSet(allocator, limb_base);
- while (q.len >= 2) {
+ while (q.len() >= 2) {
try Int.divTrunc(&q, &r, q, b);
var r_word = r.limbs[0];
@@ -399,7 +494,7 @@ pub const Int = struct {
}
{
- debug.assert(q.len == 1);
+ debug.assert(q.len() == 1);
var r_word = q.limbs[0];
while (r_word != 0) {
@@ -410,7 +505,7 @@ pub const Int = struct {
}
}
- if (!self.positive) {
+ if (!self.isPositive()) {
try digits.append('-');
}
@@ -419,7 +514,7 @@ pub const Int = struct {
return s;
}
- /// for the std lib format function
+ /// To allow `std.fmt.printf` to work with Int.
/// TODO make this non-allocating
pub fn format(
self: Int,
@@ -428,22 +523,24 @@ pub const Int = struct {
comptime FmtError: type,
output: fn (@typeOf(context), []const u8) FmtError!void,
) FmtError!void {
+ self.assertWritable();
// TODO look at fmt and support other bases
- const str = self.toString(self.allocator, 10) catch @panic("TODO make this non allocating");
- defer self.allocator.free(str);
+ // TODO support read-only fixed integers
+ const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
+ defer self.allocator.?.free(str);
return output(context, str);
}
- // returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
+ /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
pub fn cmpAbs(a: Int, b: Int) i8 {
- if (a.len < b.len) {
+ if (a.len() < b.len()) {
return -1;
}
- if (a.len > b.len) {
+ if (a.len() > b.len()) {
return 1;
}
- var i: usize = a.len - 1;
+ var i: usize = a.len() - 1;
while (i != 0) : (i -= 1) {
if (a.limbs[i] != b.limbs[i]) {
break;
@@ -459,53 +556,37 @@ pub const Int = struct {
}
}
- // returns -1, 0, 1 if a < b, a == b or a > b respectively.
+ /// Returns -1, 0, 1 if a < b, a == b or a > b respectively.
pub fn cmp(a: Int, b: Int) i8 {
- if (a.positive != b.positive) {
- return if (a.positive) i8(1) else -1;
+ if (a.isPositive() != b.isPositive()) {
+ return if (a.isPositive()) i8(1) else -1;
} else {
const r = cmpAbs(a, b);
- return if (a.positive) r else -r;
+ return if (a.isPositive()) r else -r;
}
}
- // if a == 0
+ /// Returns true if a == 0.
pub fn eqZero(a: Int) bool {
- return a.len == 1 and a.limbs[0] == 0;
+ return a.len() == 1 and a.limbs[0] == 0;
}
- // if |a| == |b|
+ /// Returns true if |a| == |b|.
pub fn eqAbs(a: Int, b: Int) bool {
return cmpAbs(a, b) == 0;
}
- // if a == b
+ /// Returns true if a == b.
pub fn eq(a: Int, b: Int) bool {
return cmp(a, b) == 0;
}
- // Normalize for a possible single carry digit.
- //
- // [1, 2, 3, 4, 0] -> [1, 2, 3, 4]
- // [1, 2, 3, 4, 5] -> [1, 2, 3, 4, 5]
- // [0] -> [0]
- fn norm1(r: *Int, length: usize) void {
- debug.assert(length > 0);
- debug.assert(length <= r.limbs.len);
-
- if (r.limbs[length - 1] == 0) {
- r.len = if (length > 1) length - 1 else 1;
- } else {
- r.len = length;
- }
- }
-
// Normalize a possible sequence of leading zeros.
//
// [1, 2, 3, 4, 0] -> [1, 2, 3, 4]
// [1, 2, 0, 0, 0] -> [1, 2]
// [0, 0, 0, 0, 0] -> [0]
- fn normN(r: *Int, length: usize) void {
+ fn normalize(r: *Int, length: usize) void {
debug.assert(length > 0);
debug.assert(length <= r.limbs.len);
@@ -517,11 +598,25 @@ pub const Int = struct {
}
// Handle zero
- r.len = if (j != 0) j else 1;
+ r.setLen(if (j != 0) j else 1);
}
- // r = a + b
+ // Cannot be used as a result argument to any function.
+ fn readOnlyPositive(a: Int) Int {
+ return Int{
+ .allocator = null,
+ .metadata = a.len(),
+ .limbs = a.limbs,
+ };
+ }
+
+ /// r = a + b
+ ///
+ /// r, a and b may be aliases.
+ ///
+ /// Returns an error if memory could not be allocated.
pub fn add(r: *Int, a: Int, b: Int) Allocator.Error!void {
+ r.assertWritable();
if (a.eqZero()) {
try r.copy(b);
return;
@@ -530,38 +625,26 @@ pub const Int = struct {
return;
}
- if (a.positive != b.positive) {
- if (a.positive) {
+ if (a.isPositive() != b.isPositive()) {
+ if (a.isPositive()) {
// (a) + (-b) => a - b
- const bp = Int{
- .allocator = undefined,
- .positive = true,
- .limbs = b.limbs,
- .len = b.len,
- };
- try r.sub(a, bp);
+ try r.sub(a, readOnlyPositive(b));
} else {
// (-a) + (b) => b - a
- const ap = Int{
- .allocator = undefined,
- .positive = true,
- .limbs = a.limbs,
- .len = a.len,
- };
- try r.sub(b, ap);
+ try r.sub(b, readOnlyPositive(a));
}
} else {
- if (a.len >= b.len) {
- try r.ensureCapacity(a.len + 1);
- lladd(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);
- r.norm1(a.len + 1);
+ if (a.len() >= b.len()) {
+ try r.ensureCapacity(a.len() + 1);
+ lladd(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
+ r.normalize(a.len() + 1);
} else {
- try r.ensureCapacity(b.len + 1);
- lladd(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);
- r.norm1(b.len + 1);
+ try r.ensureCapacity(b.len() + 1);
+ lladd(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
+ r.normalize(b.len() + 1);
}
- r.positive = a.positive;
+ r.setSign(a.isPositive());
}
}
@@ -589,55 +672,48 @@ pub const Int = struct {
r[i] = carry;
}
- // r = a - b
+ /// r = a - b
+ ///
+ /// r, a and b may be aliases.
+ ///
+ /// Returns an error if memory could not be allocated.
pub fn sub(r: *Int, a: Int, b: Int) !void {
- if (a.positive != b.positive) {
- if (a.positive) {
+ r.assertWritable();
+ if (a.isPositive() != b.isPositive()) {
+ if (a.isPositive()) {
// (a) - (-b) => a + b
- const bp = Int{
- .allocator = undefined,
- .positive = true,
- .limbs = b.limbs,
- .len = b.len,
- };
- try r.add(a, bp);
+ try r.add(a, readOnlyPositive(b));
} else {
// (-a) - (b) => -(a + b)
- const ap = Int{
- .allocator = undefined,
- .positive = true,
- .limbs = a.limbs,
- .len = a.len,
- };
- try r.add(ap, b);
- r.positive = false;
+ try r.add(readOnlyPositive(a), b);
+ r.setSign(false);
}
} else {
- if (a.positive) {
+ if (a.isPositive()) {
// (a) - (b) => a - b
if (a.cmp(b) >= 0) {
- try r.ensureCapacity(a.len + 1);
- llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);
- r.normN(a.len);
- r.positive = true;
+ try r.ensureCapacity(a.len() + 1);
+ llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
+ r.normalize(a.len());
+ r.setSign(true);
} else {
- try r.ensureCapacity(b.len + 1);
- llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);
- r.normN(b.len);
- r.positive = false;
+ try r.ensureCapacity(b.len() + 1);
+ llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
+ r.normalize(b.len());
+ r.setSign(false);
}
} else {
// (-a) - (-b) => -(a - b)
if (a.cmp(b) < 0) {
- try r.ensureCapacity(a.len + 1);
- llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);
- r.normN(a.len);
- r.positive = false;
+ try r.ensureCapacity(a.len() + 1);
+ llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
+ r.normalize(a.len());
+ r.setSign(false);
} else {
- try r.ensureCapacity(b.len + 1);
- llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);
- r.normN(b.len);
- r.positive = true;
+ try r.ensureCapacity(b.len() + 1);
+ llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
+ r.normalize(b.len());
+ r.setSign(true);
}
}
}
@@ -667,16 +743,20 @@ pub const Int = struct {
debug.assert(borrow == 0);
}
- // rma = a * b
- //
- // For greatest efficiency, ensure rma does not alias a or b.
+ /// rma = a * b
+ ///
+ /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+ ///
+ /// Returns an error if memory could not be allocated.
pub fn mul(rma: *Int, a: Int, b: Int) !void {
+ rma.assertWritable();
+
var r = rma;
var aliased = rma.limbs.ptr == a.limbs.ptr or rma.limbs.ptr == b.limbs.ptr;
var sr: Int = undefined;
if (aliased) {
- sr = try Int.initCapacity(rma.allocator, a.len + b.len);
+ sr = try Int.initCapacity(rma.allocator.?, a.len() + b.len());
r = &sr;
aliased = true;
}
@@ -685,16 +765,16 @@ pub const Int = struct {
r.deinit();
};
- try r.ensureCapacity(a.len + b.len);
+ try r.ensureCapacity(a.len() + b.len());
- if (a.len >= b.len) {
- llmul(r.limbs, a.limbs[0..a.len], b.limbs[0..b.len]);
+ if (a.len() >= b.len()) {
+ llmul(r.limbs, a.limbs[0..a.len()], b.limbs[0..b.len()]);
} else {
- llmul(r.limbs, b.limbs[0..b.len], a.limbs[0..a.len]);
+ llmul(r.limbs, b.limbs[0..b.len()], a.limbs[0..a.len()]);
}
- r.positive = a.positive == b.positive;
- r.normN(a.len + b.len);
+ r.normalize(a.len() + b.len());
+ r.setSign(a.isPositive() == b.isPositive());
}
// a + b * c + *carry, sets carry to the overflow bits
@@ -740,29 +820,34 @@ pub const Int = struct {
}
}
+ /// q = a / b (rem r)
+ ///
+ /// a / b are floored (rounded towards 0).
pub fn divFloor(q: *Int, r: *Int, a: Int, b: Int) !void {
try div(q, r, a, b);
// Trunc -> Floor.
- if (!q.positive) {
- // TODO values less than limb size should guarantee non allocating
- var one_buffer: [512]u8 = undefined;
- const one_al = &std.heap.FixedBufferAllocator.init(one_buffer[0..]).allocator;
- const one_ap = try Int.initSet(one_al, 1);
-
- try q.sub(q.*, one_ap);
- try r.add(q.*, one_ap);
+ if (!q.isPositive()) {
+ const one = Int.initFixed(([]Limb{1})[0..]);
+ try q.sub(q.*, one);
+ try r.add(q.*, one);
}
- r.positive = b.positive;
+ r.setSign(b.isPositive());
}
+ /// q = a / b (rem r)
+ ///
+ /// a / b are truncated (rounded towards -inf).
pub fn divTrunc(q: *Int, r: *Int, a: Int, b: Int) !void {
try div(q, r, a, b);
- r.positive = a.positive;
+ r.setSign(a.isPositive());
}
// Truncates by default.
fn div(quo: *Int, rem: *Int, a: Int, b: Int) !void {
+ quo.assertWritable();
+ rem.assertWritable();
+
if (b.eqZero()) {
@panic("division by zero");
}
@@ -773,36 +858,67 @@ pub const Int = struct {
if (a.cmpAbs(b) < 0) {
// quo may alias a so handle rem first
try rem.copy(a);
- rem.positive = a.positive == b.positive;
+ rem.setSign(a.isPositive() == b.isPositive());
- quo.positive = true;
- quo.len = 1;
+ quo.metadata = 1;
quo.limbs[0] = 0;
return;
}
- if (b.len == 1) {
- try quo.ensureCapacity(a.len);
+ // Handle trailing zero-words of divisor/dividend. These are not handled in the following
+ // algorithms.
+ const a_zero_limb_count = blk: {
+ var i: usize = 0;
+ while (i < a.len()) : (i += 1) {
+ if (a.limbs[i] != 0) break;
+ }
+ break :blk i;
+ };
+ const b_zero_limb_count = blk: {
+ var i: usize = 0;
+ while (i < b.len()) : (i += 1) {
+ if (b.limbs[i] != 0) break;
+ }
+ break :blk i;
+ };
- lldiv1(quo.limbs[0..], &rem.limbs[0], a.limbs[0..a.len], b.limbs[0]);
- quo.norm1(a.len);
- quo.positive = a.positive == b.positive;
+ const ab_zero_limb_count = std.math.min(a_zero_limb_count, b_zero_limb_count);
- rem.len = 1;
- rem.positive = true;
+ if (b.len() - ab_zero_limb_count == 1) {
+ try quo.ensureCapacity(a.len());
+
+ lldiv1(quo.limbs[0..], &rem.limbs[0], a.limbs[ab_zero_limb_count..a.len()], b.limbs[b.len() - 1]);
+ quo.normalize(a.len() - ab_zero_limb_count);
+ quo.setSign(a.isPositive() == b.isPositive());
+
+ rem.metadata = 1;
} else {
// x and y are modified during division
- var x = try a.clone();
+ var x = try Int.initCapacity(quo.allocator.?, a.len());
defer x.deinit();
+ try x.copy(a);
- var y = try b.clone();
+ var y = try Int.initCapacity(quo.allocator.?, b.len());
defer y.deinit();
+ try y.copy(b);
// x may grow one limb during normalization
- try quo.ensureCapacity(a.len + y.len);
- try divN(quo.allocator, quo, rem, &x, &y);
+ try quo.ensureCapacity(a.len() + y.len());
+
+ // Shrink x, y such that the trailing zero limbs shared between are removed.
+ if (ab_zero_limb_count != 0) {
+ std.mem.copy(Limb, x.limbs[0..], x.limbs[ab_zero_limb_count..]);
+ std.mem.copy(Limb, y.limbs[0..], y.limbs[ab_zero_limb_count..]);
+ x.metadata -= ab_zero_limb_count;
+ y.metadata -= ab_zero_limb_count;
+ }
- quo.positive = a.positive == b.positive;
+ try divN(quo.allocator.?, quo, rem, &x, &y);
+ quo.setSign(a.isPositive() == b.isPositive());
+ }
+
+ if (ab_zero_limb_count != 0) {
+ try rem.shiftLeft(rem.*, ab_zero_limb_count * Limb.bit_count);
}
}
@@ -837,25 +953,28 @@ pub const Int = struct {
//
// x = qy + r where 0 <= r < y
fn divN(allocator: *Allocator, q: *Int, r: *Int, x: *Int, y: *Int) !void {
- debug.assert(y.len >= 2);
- debug.assert(x.len >= y.len);
- debug.assert(q.limbs.len >= x.len + y.len - 1);
+ debug.assert(y.len() >= 2);
+ debug.assert(x.len() >= y.len());
+ debug.assert(q.limbs.len >= x.len() + y.len() - 1);
debug.assert(default_capacity >= 3); // see 3.2
var tmp = try Int.init(allocator);
defer tmp.deinit();
- // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set)
- const norm_shift = @clz(y.limbs[y.len - 1]);
+ // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) and even
+ var norm_shift = @clz(y.limbs[y.len() - 1]);
+ if (norm_shift == 0 and y.isOdd()) {
+ norm_shift = Limb.bit_count;
+ }
try x.shiftLeft(x.*, norm_shift);
try y.shiftLeft(y.*, norm_shift);
- const n = x.len - 1;
- const t = y.len - 1;
+ const n = x.len() - 1;
+ const t = y.len() - 1;
// 1.
- q.len = n - t + 1;
- mem.set(Limb, q.limbs[0..q.len], 0);
+ q.metadata = n - t + 1;
+ mem.set(Limb, q.limbs[0..q.len()], 0);
// 2.
try tmp.shiftLeft(y.*, Limb.bit_count * (n - t));
@@ -880,7 +999,7 @@ pub const Int = struct {
tmp.limbs[0] = if (i >= 2) x.limbs[i - 2] else 0;
tmp.limbs[1] = if (i >= 1) x.limbs[i - 1] else 0;
tmp.limbs[2] = x.limbs[i];
- tmp.normN(3);
+ tmp.normalize(3);
while (true) {
// 2x1 limb multiplication unrolled against single-limb q[i-t-1]
@@ -888,7 +1007,7 @@ pub const Int = struct {
r.limbs[0] = addMulLimbWithCarry(0, if (t >= 1) y.limbs[t - 1] else 0, q.limbs[i - t - 1], &carry);
r.limbs[1] = addMulLimbWithCarry(0, y.limbs[t], q.limbs[i - t - 1], &carry);
r.limbs[2] = carry;
- r.normN(3);
+ r.normalize(3);
if (r.cmpAbs(tmp) <= 0) {
break;
@@ -903,7 +1022,7 @@ pub const Int = struct {
try tmp.shiftLeft(tmp, Limb.bit_count * (i - t - 1));
try x.sub(x.*, tmp);
- if (!x.positive) {
+ if (!x.isPositive()) {
try tmp.shiftLeft(y.*, Limb.bit_count * (i - t - 1));
try x.add(x.*, tmp);
q.limbs[i - t - 1] -= 1;
@@ -911,18 +1030,20 @@ pub const Int = struct {
}
// Denormalize
- q.normN(q.len);
+ q.normalize(q.len());
try r.shiftRight(x.*, norm_shift);
- r.normN(r.len);
+ r.normalize(r.len());
}
- // r = a << shift, in other words, r = a * 2^shift
+ /// r = a << shift, in other words, r = a * 2^shift
pub fn shiftLeft(r: *Int, a: Int, shift: usize) !void {
- try r.ensureCapacity(a.len + (shift / Limb.bit_count) + 1);
- llshl(r.limbs[0..], a.limbs[0..a.len], shift);
- r.norm1(a.len + (shift / Limb.bit_count) + 1);
- r.positive = a.positive;
+ r.assertWritable();
+
+ try r.ensureCapacity(a.len() + (shift / Limb.bit_count) + 1);
+ llshl(r.limbs[0..], a.limbs[0..a.len()], shift);
+ r.normalize(a.len() + (shift / Limb.bit_count) + 1);
+ r.setSign(a.isPositive());
}
fn llshl(r: []Limb, a: []const Limb, shift: usize) void {
@@ -948,19 +1069,20 @@ pub const Int = struct {
mem.set(Limb, r[0 .. limb_shift - 1], 0);
}
- // r = a >> shift
+ /// r = a >> shift
pub fn shiftRight(r: *Int, a: Int, shift: usize) !void {
- if (a.len <= shift / Limb.bit_count) {
- r.len = 1;
+ r.assertWritable();
+
+ if (a.len() <= shift / Limb.bit_count) {
+ r.metadata = 1;
r.limbs[0] = 0;
- r.positive = true;
return;
}
- try r.ensureCapacity(a.len - (shift / Limb.bit_count));
- const r_len = llshr(r.limbs[0..], a.limbs[0..a.len], shift);
- r.len = a.len - (shift / Limb.bit_count);
- r.positive = a.positive;
+ try r.ensureCapacity(a.len() - (shift / Limb.bit_count));
+ const r_len = llshr(r.limbs[0..], a.limbs[0..a.len()], shift);
+ r.metadata = a.len() - (shift / Limb.bit_count);
+ r.setSign(a.isPositive());
}
fn llshr(r: []Limb, a: []const Limb, shift: usize) void {
@@ -983,16 +1105,20 @@ pub const Int = struct {
}
}
- // r = a | b
+ /// r = a | b
+ ///
+ /// a and b are zero-extended to the longer of a or b.
pub fn bitOr(r: *Int, a: Int, b: Int) !void {
- if (a.len > b.len) {
- try r.ensureCapacity(a.len);
- llor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);
- r.len = a.len;
+ r.assertWritable();
+
+ if (a.len() > b.len()) {
+ try r.ensureCapacity(a.len());
+ llor(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
+ r.setLen(a.len());
} else {
- try r.ensureCapacity(b.len);
- llor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);
- r.len = b.len;
+ try r.ensureCapacity(b.len());
+ llor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
+ r.setLen(b.len());
}
}
@@ -1010,16 +1136,18 @@ pub const Int = struct {
}
}
- // r = a & b
+ /// r = a & b
pub fn bitAnd(r: *Int, a: Int, b: Int) !void {
- if (a.len > b.len) {
- try r.ensureCapacity(b.len);
- lland(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);
- r.normN(b.len);
+ r.assertWritable();
+
+ if (a.len() > b.len()) {
+ try r.ensureCapacity(b.len());
+ lland(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
+ r.normalize(b.len());
} else {
- try r.ensureCapacity(a.len);
- lland(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);
- r.normN(a.len);
+ try r.ensureCapacity(a.len());
+ lland(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
+ r.normalize(a.len());
}
}
@@ -1034,16 +1162,18 @@ pub const Int = struct {
}
}
- // r = a ^ b
+ /// r = a ^ b
pub fn bitXor(r: *Int, a: Int, b: Int) !void {
- if (a.len > b.len) {
- try r.ensureCapacity(a.len);
- llxor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);
- r.normN(a.len);
+ r.assertWritable();
+
+ if (a.len() > b.len()) {
+ try r.ensureCapacity(a.len());
+ llxor(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
+ r.normalize(a.len());
} else {
- try r.ensureCapacity(b.len);
- llxor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);
- r.normN(b.len);
+ try r.ensureCapacity(b.len());
+ llxor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
+ r.normalize(b.len());
}
}
@@ -1067,7 +1197,9 @@ pub const Int = struct {
// They will still run on larger than this and should pass, but the multi-limb code-paths
// may be untested in some cases.
-const al = debug.global_allocator;
+var buffer: [64 * 8192]u8 = undefined;
+var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
+const al = &fixed.allocator;
test "big.int comptime_int set" {
comptime var s = 0xefffffff00000001eeeeeeefaaaaaaab;
@@ -1088,14 +1220,14 @@ test "big.int comptime_int set negative" {
var a = try Int.initSet(al, -10);
testing.expect(a.limbs[0] == 10);
- testing.expect(a.positive == false);
+ testing.expect(a.isPositive() == false);
}
test "big.int int set unaligned small" {
var a = try Int.initSet(al, u7(45));
testing.expect(a.limbs[0] == 45);
- testing.expect(a.positive == true);
+ testing.expect(a.isPositive() == true);
}
test "big.int comptime_int to" {
@@ -1116,7 +1248,7 @@ test "big.int to target too small error" {
testing.expectError(error.TargetTooSmall, a.to(u8));
}
-test "big.int norm1" {
+test "big.int normalize" {
var a = try Int.init(al);
try a.ensureCapacity(8);
@@ -1124,26 +1256,26 @@ test "big.int norm1" {
a.limbs[1] = 2;
a.limbs[2] = 3;
a.limbs[3] = 0;
- a.norm1(4);
- testing.expect(a.len == 3);
+ a.normalize(4);
+ testing.expect(a.len() == 3);
a.limbs[0] = 1;
a.limbs[1] = 2;
a.limbs[2] = 3;
- a.norm1(3);
- testing.expect(a.len == 3);
+ a.normalize(3);
+ testing.expect(a.len() == 3);
a.limbs[0] = 0;
a.limbs[1] = 0;
- a.norm1(2);
- testing.expect(a.len == 1);
+ a.normalize(2);
+ testing.expect(a.len() == 1);
a.limbs[0] = 0;
- a.norm1(1);
- testing.expect(a.len == 1);
+ a.normalize(1);
+ testing.expect(a.len() == 1);
}
-test "big.int normN" {
+test "big.int normalize multi" {
var a = try Int.init(al);
try a.ensureCapacity(8);
@@ -1151,25 +1283,25 @@ test "big.int normN" {
a.limbs[1] = 2;
a.limbs[2] = 0;
a.limbs[3] = 0;
- a.normN(4);
- testing.expect(a.len == 2);
+ a.normalize(4);
+ testing.expect(a.len() == 2);
a.limbs[0] = 1;
a.limbs[1] = 2;
a.limbs[2] = 3;
- a.normN(3);
- testing.expect(a.len == 3);
+ a.normalize(3);
+ testing.expect(a.len() == 3);
a.limbs[0] = 0;
a.limbs[1] = 0;
a.limbs[2] = 0;
a.limbs[3] = 0;
- a.normN(4);
- testing.expect(a.len == 1);
+ a.normalize(4);
+ testing.expect(a.len() == 1);
a.limbs[0] = 0;
- a.normN(1);
- testing.expect(a.len == 1);
+ a.normalize(1);
+ testing.expect(a.len() == 1);
}
test "big.int parity" {
@@ -1204,7 +1336,7 @@ test "big.int bitcount + sizeInBase" {
try a.shiftLeft(a, 5000);
testing.expect(a.bitCountAbs() == 5032);
testing.expect(a.sizeInBase(2) >= 5032);
- a.positive = false;
+ a.setSign(false);
testing.expect(a.bitCountAbs() == 5032);
testing.expect(a.sizeInBase(2) >= 5033);
@@ -1216,10 +1348,8 @@ test "big.int bitcount/to" {
try a.set(0);
testing.expect(a.bitCountTwosComp() == 0);
- // TODO: stack smashing
- // testing.expect((try a.to(u0)) == 0);
- // TODO: sigsegv
- // testing.expect((try a.to(i0)) == 0);
+ testing.expect((try a.to(u0)) == 0);
+ testing.expect((try a.to(i0)) == 0);
try a.set(-1);
testing.expect(a.bitCountTwosComp() == 1);
@@ -1980,6 +2110,98 @@ test "big.int div multi-multi (3.1/3.3 branch)" {
testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);
}
+test "big.int div multi-single zero-limb trailing" {
+ var a = try Int.initSet(al, 0x60000000000000000000000000000000000000000000000000000000000000000);
+ var b = try Int.initSet(al, 0x10000000000000000);
+
+ var q = try Int.init(al);
+ var r = try Int.init(al);
+ try Int.divTrunc(&q, &r, a, b);
+
+ var expected = try Int.initSet(al, 0x6000000000000000000000000000000000000000000000000);
+ testing.expect(q.eq(expected));
+ testing.expect(r.eqZero());
+}
+
+test "big.int div multi-multi zero-limb trailing (with rem)" {
+ var a = try Int.initSet(al, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
+ var b = try Int.initSet(al, 0x8666666655555555444444443333333300000000000000000000000000000000);
+
+ var q = try Int.init(al);
+ var r = try Int.init(al);
+ try Int.divTrunc(&q, &r, a, b);
+
+ testing.expect((try q.to(u128)) == 0x10000000000000000);
+
+ const rs = try r.toString(al, 16);
+ testing.expect(std.mem.eql(u8, rs, "4444444344444443111111111111111100000000000000000000000000000000"));
+}
+
+test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" {
+ var a = try Int.initSet(al, 0x8666666655555555888888877777777611111111111111110000000000000000);
+ var b = try Int.initSet(al, 0x8666666655555555444444443333333300000000000000000000000000000000);
+
+ var q = try Int.init(al);
+ var r = try Int.init(al);
+ try Int.divTrunc(&q, &r, a, b);
+
+ testing.expect((try q.to(u128)) == 0x1);
+
+ const rs = try r.toString(al, 16);
+ testing.expect(std.mem.eql(u8, rs, "444444434444444311111111111111110000000000000000"));
+}
+
+test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" {
+ var a = try Int.initSet(al, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
+ var b = try Int.initSet(al, 0x866666665555555544444444333333330000000000000000);
+
+ var q = try Int.init(al);
+ var r = try Int.init(al);
+ try Int.divTrunc(&q, &r, a, b);
+
+ const qs = try q.toString(al, 16);
+ testing.expect(std.mem.eql(u8, qs, "10000000000000000820820803105186f"));
+
+ const rs = try r.toString(al, 16);
+ testing.expect(std.mem.eql(u8, rs, "4e11f2baa5896a321d463b543d0104e30000000000000000"));
+}
+
+test "big.int div multi-multi fuzz case #1" {
+ var a = try Int.init(al);
+ var b = try Int.init(al);
+
+ try a.setString(16, "ffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
+ try b.setString(16, "3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000007fffffffffff");
+
+ var q = try Int.init(al);
+ var r = try Int.init(al);
+ try Int.divTrunc(&q, &r, a, b);
+
+ const qs = try q.toString(al, 16);
+ testing.expect(std.mem.eql(u8, qs, "3ffffffffffffffffffffffffffff0000000000000000000000000000000000001ffffffffffffffffffffffffffff7fffffffe000000000000000000000000000180000000000000000000003fffffbfffffffdfffffffffffffeffff800000100101000000100000000020003fffffdfbfffffe3ffffffffffffeffff7fffc00800a100000017ffe000002000400007efbfff7fe9f00000037ffff3fff7fffa004006100000009ffe00000190038200bf7d2ff7fefe80400060000f7d7f8fbf9401fe38e0403ffc0bdffffa51102c300d7be5ef9df4e5060007b0127ad3fa69f97d0f820b6605ff617ddf7f32ad7a05c0d03f2e7bc78a6000e087a8bbcdc59e07a5a079128a7861f553ddebed7e8e56701756f9ead39b48cd1b0831889ea6ec1fddf643d0565b075ff07e6caea4e2854ec9227fd635ed60a2f5eef2893052ffd54718fa08604acbf6a15e78a467c4a3c53c0278af06c4416573f925491b195e8fd79302cb1aaf7caf4ecfc9aec1254cc969786363ac729f914c6ddcc26738d6b0facd54eba026580aba2eb6482a088b0d224a8852420b91ec1"));
+
+ const rs = try r.toString(al, 16);
+ testing.expect(std.mem.eql(u8, rs, "310d1d4c414426b4836c2635bad1df3a424e50cbdd167ffccb4dfff57d36b4aae0d6ca0910698220171a0f3373c1060a046c2812f0027e321f72979daa5e7973214170d49e885de0c0ecc167837d44502430674a82522e5df6a0759548052420b91ec1"));
+}
+
+test "big.int div multi-multi fuzz case #2" {
+ var a = try Int.init(al);
+ var b = try Int.init(al);
+
+ try a.setString(16, "3ffffffffe00000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000001fffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffc000000000000000000000000000000000000000000000000000000000000000");
+ try b.setString(16, "ffc0000000000000000000000000000000000000000000000000");
+
+ var q = try Int.init(al);
+ var r = try Int.init(al);
+ try Int.divTrunc(&q, &r, a, b);
+
+ const qs = try q.toString(al, 16);
+ testing.expect(std.mem.eql(u8, qs, "40100400fe3f8fe3f8fe3f8fe3f8fe3f8fe4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f91e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4992649926499264991e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4792e4b92e4b92e4b92e4b92a4a92a4a92a4"));
+
+ const rs = try r.toString(al, 16);
+ testing.expect(std.mem.eql(u8, rs, "a900000000000000000000000000000000000000000000000000"));
+}
+
test "big.int shift-right single" {
var a = try Int.initSet(al, 0xffff0000);
try a.shiftRight(a, 16);
diff --git a/std/math/big/rational.zig b/std/math/big/rational.zig
new file mode 100644
index 0000000000..58a5e3ac76
--- /dev/null
+++ b/std/math/big/rational.zig
@@ -0,0 +1,938 @@
+const std = @import("../../std.zig");
+const builtin = @import("builtin");
+const debug = std.debug;
+const math = std.math;
+const mem = std.mem;
+const testing = std.testing;
+const Allocator = mem.Allocator;
+const ArrayList = std.ArrayList;
+
+const TypeId = builtin.TypeId;
+
+const bn = @import("int.zig");
+const Limb = bn.Limb;
+const DoubleLimb = bn.DoubleLimb;
+const Int = bn.Int;
+
+/// An arbitrary-precision rational number.
+///
+/// Memory is allocated as needed for operations to ensure full precision is kept. The precision
+/// of a Rational is only bounded by memory.
+///
+/// Rational's are always normalized. That is, for a Rational r = p/q where p and q are integers,
+/// gcd(p, q) = 1 always.
+pub const Rational = struct {
+ /// Numerator. Determines the sign of the Rational.
+ p: Int,
+
+ /// Denominator. Sign is ignored.
+ q: Int,
+
+ /// Create a new Rational. A small amount of memory will be allocated on initialization.
+ /// This will be 2 * Int.default_capacity.
+ pub fn init(a: *Allocator) !Rational {
+ return Rational{
+ .p = try Int.init(a),
+ .q = try Int.initSet(a, 1),
+ };
+ }
+
+ /// Frees all memory associated with a Rational.
+ pub fn deinit(self: *Rational) void {
+ self.p.deinit();
+ self.q.deinit();
+ }
+
+ /// Set a Rational from a primitive integer type.
+ pub fn setInt(self: *Rational, a: var) !void {
+ try self.p.set(a);
+ try self.q.set(1);
+ }
+
+ /// Set a Rational from a string of the form `A/B` where A and B are base-10 integers.
+ pub fn setFloatString(self: *Rational, str: []const u8) !void {
+ // TODO: Accept a/b fractions and exponent form
+ if (str.len == 0) {
+ return error.InvalidFloatString;
+ }
+
+ const State = enum {
+ Integer,
+ Fractional,
+ };
+
+ var state = State.Integer;
+ var point: ?usize = null;
+
+ var start: usize = 0;
+ if (str[0] == '-') {
+ start += 1;
+ }
+
+ for (str) |c, i| {
+ switch (state) {
+ State.Integer => {
+ switch (c) {
+ '.' => {
+ state = State.Fractional;
+ point = i;
+ },
+ '0'...'9' => {
+ // okay
+ },
+ else => {
+ return error.InvalidFloatString;
+ },
+ }
+ },
+ State.Fractional => {
+ switch (c) {
+ '0'...'9' => {
+ // okay
+ },
+ else => {
+ return error.InvalidFloatString;
+ },
+ }
+ },
+ }
+ }
+
+ // TODO: batch the multiplies by 10
+ if (point) |i| {
+ try self.p.setString(10, str[0..i]);
+
+ const base = Int.initFixed(([]Limb{10})[0..]);
+
+ var j: usize = start;
+ while (j < str.len - i - 1) : (j += 1) {
+ try self.p.mul(self.p, base);
+ }
+
+ try self.q.setString(10, str[i + 1 ..]);
+ try self.p.add(self.p, self.q);
+
+ try self.q.set(1);
+ var k: usize = i + 1;
+ while (k < str.len) : (k += 1) {
+ try self.q.mul(self.q, base);
+ }
+
+ try self.reduce();
+ } else {
+ try self.p.setString(10, str[0..]);
+ try self.q.set(1);
+ }
+ }
+
+ /// Set a Rational from a floating-point value. The rational will have enough precision to
+ /// completely represent the provided float.
+ pub fn setFloat(self: *Rational, comptime T: type, f: T) !void {
+ // Translated from golang.go/src/math/big/rat.go.
+ debug.assert(@typeId(T) == builtin.TypeId.Float);
+
+ const UnsignedIntType = @IntType(false, T.bit_count);
+ const f_bits = @bitCast(UnsignedIntType, f);
+
+ const exponent_bits = math.floatExponentBits(T);
+ const exponent_bias = (1 << (exponent_bits - 1)) - 1;
+ const mantissa_bits = math.floatMantissaBits(T);
+
+ const exponent_mask = (1 << exponent_bits) - 1;
+ const mantissa_mask = (1 << mantissa_bits) - 1;
+
+ var exponent = @intCast(i16, (f_bits >> mantissa_bits) & exponent_mask);
+ var mantissa = f_bits & mantissa_mask;
+
+ switch (exponent) {
+ exponent_mask => {
+ return error.NonFiniteFloat;
+ },
+ 0 => {
+ // denormal
+ exponent -= exponent_bias - 1;
+ },
+ else => {
+ // normal
+ mantissa |= 1 << mantissa_bits;
+ exponent -= exponent_bias;
+ },
+ }
+
+ var shift: i16 = mantissa_bits - exponent;
+
+ // factor out powers of two early from rational
+ while (mantissa & 1 == 0 and shift > 0) {
+ mantissa >>= 1;
+ shift -= 1;
+ }
+
+ try self.p.set(mantissa);
+ self.p.setSign(f >= 0);
+
+ try self.q.set(1);
+ if (shift >= 0) {
+ try self.q.shiftLeft(self.q, @intCast(usize, shift));
+ } else {
+ try self.p.shiftLeft(self.p, @intCast(usize, -shift));
+ }
+
+ try self.reduce();
+ }
+
+ /// Return a floating-point value that is the closest value to a Rational.
+ ///
+ /// The result may not be exact if the Rational is too precise or too large for the
+ /// target type.
+ pub fn toFloat(self: Rational, comptime T: type) !T {
+ // Translated from golang.go/src/math/big/rat.go.
+ // TODO: Indicate whether the result is not exact.
+ debug.assert(@typeId(T) == builtin.TypeId.Float);
+
+ const fsize = T.bit_count;
+ const BitReprType = @IntType(false, T.bit_count);
+
+ const msize = math.floatMantissaBits(T);
+ const msize1 = msize + 1;
+ const msize2 = msize1 + 1;
+
+ const esize = math.floatExponentBits(T);
+ const ebias = (1 << (esize - 1)) - 1;
+ const emin = 1 - ebias;
+ const emax = ebias;
+
+ if (self.p.eqZero()) {
+ return 0;
+ }
+
+ // 1. left-shift a or sub so that a/b is in [1 << msize1, 1 << (msize2 + 1)]
+ var exp = @intCast(isize, self.p.bitCountTwosComp()) - @intCast(isize, self.q.bitCountTwosComp());
+
+ var a2 = try self.p.clone();
+ defer a2.deinit();
+
+ var b2 = try self.q.clone();
+ defer b2.deinit();
+
+ const shift = msize2 - exp;
+ if (shift >= 0) {
+ try a2.shiftLeft(a2, @intCast(usize, shift));
+ } else {
+ try b2.shiftLeft(b2, @intCast(usize, -shift));
+ }
+
+ // 2. compute quotient and remainder
+ var q = try Int.init(self.p.allocator.?);
+ defer q.deinit();
+
+ // unused
+ var r = try Int.init(self.p.allocator.?);
+ defer r.deinit();
+
+ try Int.divTrunc(&q, &r, a2, b2);
+
+ var mantissa = extractLowBits(q, BitReprType);
+ var have_rem = r.len() > 0;
+
+ // 3. q didn't fit in msize2 bits, redo division b2 << 1
+ if (mantissa >> msize2 == 1) {
+ if (mantissa & 1 == 1) {
+ have_rem = true;
+ }
+ mantissa >>= 1;
+ exp += 1;
+ }
+ if (mantissa >> msize1 != 1) {
+ // NOTE: This can be hit if the limb size is small (u8/16).
+ @panic("unexpected bits in result");
+ }
+
+ // 4. Rounding
+ if (emin - msize <= exp and exp <= emin) {
+ // denormal
+ const shift1 = @intCast(math.Log2Int(BitReprType), emin - (exp - 1));
+ const lost_bits = mantissa & ((@intCast(BitReprType, 1) << shift1) - 1);
+ have_rem = have_rem or lost_bits != 0;
+ mantissa >>= shift1;
+ exp = 2 - ebias;
+ }
+
+ // round q using round-half-to-even
+ var exact = !have_rem;
+ if (mantissa & 1 != 0) {
+ exact = false;
+ if (have_rem or (mantissa & 2 != 0)) {
+ mantissa += 1;
+ if (mantissa >= 1 << msize2) {
+ // 11...1 => 100...0
+ mantissa >>= 1;
+ exp += 1;
+ }
+ }
+ }
+ mantissa >>= 1;
+
+ const f = math.scalbn(@intToFloat(T, mantissa), @intCast(i32, exp - msize1));
+ if (math.isInf(f)) {
+ exact = false;
+ }
+
+ return if (self.p.isPositive()) f else -f;
+ }
+
+ /// Set a rational from an integer ratio.
+ pub fn setRatio(self: *Rational, p: var, q: var) !void {
+ try self.p.set(p);
+ try self.q.set(q);
+
+ self.p.setSign(@boolToInt(self.p.isPositive()) ^ @boolToInt(self.q.isPositive()) == 0);
+ self.q.setSign(true);
+
+ try self.reduce();
+
+ if (self.q.eqZero()) {
+ @panic("cannot set rational with denominator = 0");
+ }
+ }
+
+ /// Set a Rational directly from an Int.
+ pub fn copyInt(self: *Rational, a: Int) !void {
+ try self.p.copy(a);
+ try self.q.set(1);
+ }
+
+ /// Set a Rational directly from a ratio of two Int's.
+ pub fn copyRatio(self: *Rational, a: Int, b: Int) !void {
+ try self.p.copy(a);
+ try self.q.copy(b);
+
+ self.p.setSign(@boolToInt(self.p.isPositive()) ^ @boolToInt(self.q.isPositive()) == 0);
+ self.q.setSign(true);
+
+ try self.reduce();
+ }
+
+ /// Make a Rational positive.
+ pub fn abs(r: *Rational) void {
+ r.p.abs();
+ }
+
+ /// Negate the sign of a Rational.
+ pub fn negate(r: *Rational) void {
+ r.p.negate();
+ }
+
+ /// Efficiently swap a Rational with another. This swaps the limb pointers and a full copy is not
+ /// performed. The address of the limbs field will not be the same after this function.
+ pub fn swap(r: *Rational, other: *Rational) void {
+ r.p.swap(&other.p);
+ r.q.swap(&other.q);
+ }
+
+ /// Returns -1, 0, 1 if a < b, a == b or a > b respectively.
+ pub fn cmp(a: Rational, b: Rational) !i8 {
+ return cmpInternal(a, b, true);
+ }
+
+ /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
+ pub fn cmpAbs(a: Rational, b: Rational) !i8 {
+ return cmpInternal(a, b, false);
+ }
+
+ // p/q > x/y iff p*y > x*q
+ fn cmpInternal(a: Rational, b: Rational, is_abs: bool) !i8 {
+ // TODO: Would a div compare algorithm of sorts be viable and quicker? Can we avoid
+ // the memory allocations here?
+ var q = try Int.init(a.p.allocator.?);
+ defer q.deinit();
+
+ var p = try Int.init(b.p.allocator.?);
+ defer p.deinit();
+
+ try q.mul(a.p, b.q);
+ try p.mul(b.p, a.q);
+
+ return if (is_abs) q.cmpAbs(p) else q.cmp(p);
+ }
+
+ /// rma = a + b.
+ ///
+ /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+ ///
+ /// Returns an error if memory could not be allocated.
+ pub fn add(rma: *Rational, a: Rational, b: Rational) !void {
+ var r = rma;
+ var aliased = rma.p.limbs.ptr == a.p.limbs.ptr or rma.p.limbs.ptr == b.p.limbs.ptr;
+
+ var sr: Rational = undefined;
+ if (aliased) {
+ sr = try Rational.init(rma.p.allocator.?);
+ r = &sr;
+ aliased = true;
+ }
+ defer if (aliased) {
+ rma.swap(r);
+ r.deinit();
+ };
+
+ try r.p.mul(a.p, b.q);
+ try r.q.mul(b.p, a.q);
+ try r.p.add(r.p, r.q);
+
+ try r.q.mul(a.q, b.q);
+ try r.reduce();
+ }
+
+ /// rma = a - b.
+ ///
+ /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+ ///
+ /// Returns an error if memory could not be allocated.
+ pub fn sub(rma: *Rational, a: Rational, b: Rational) !void {
+ var r = rma;
+ var aliased = rma.p.limbs.ptr == a.p.limbs.ptr or rma.p.limbs.ptr == b.p.limbs.ptr;
+
+ var sr: Rational = undefined;
+ if (aliased) {
+ sr = try Rational.init(rma.p.allocator.?);
+ r = &sr;
+ aliased = true;
+ }
+ defer if (aliased) {
+ rma.swap(r);
+ r.deinit();
+ };
+
+ try r.p.mul(a.p, b.q);
+ try r.q.mul(b.p, a.q);
+ try r.p.sub(r.p, r.q);
+
+ try r.q.mul(a.q, b.q);
+ try r.reduce();
+ }
+
+ /// rma = a * b.
+ ///
+ /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+ ///
+ /// Returns an error if memory could not be allocated.
+ pub fn mul(r: *Rational, a: Rational, b: Rational) !void {
+ try r.p.mul(a.p, b.p);
+ try r.q.mul(a.q, b.q);
+ try r.reduce();
+ }
+
+ /// rma = a / b.
+ ///
+ /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+ ///
+ /// Returns an error if memory could not be allocated.
+ pub fn div(r: *Rational, a: Rational, b: Rational) !void {
+ if (b.p.eqZero()) {
+ @panic("division by zero");
+ }
+
+ try r.p.mul(a.p, b.q);
+ try r.q.mul(b.p, a.q);
+ try r.reduce();
+ }
+
+ /// Invert the numerator and denominator fields of a Rational. p/q => q/p.
+ pub fn invert(r: *Rational) void {
+ Int.swap(&r.p, &r.q);
+ }
+
+ // reduce r/q such that gcd(r, q) = 1
+ fn reduce(r: *Rational) !void {
+ var a = try Int.init(r.p.allocator.?);
+ defer a.deinit();
+
+ const sign = r.p.isPositive();
+ r.p.abs();
+ try gcd(&a, r.p, r.q);
+ r.p.setSign(sign);
+
+ const one = Int.initFixed(([]Limb{1})[0..]);
+ if (a.cmp(one) != 0) {
+ var unused = try Int.init(r.p.allocator.?);
+ defer unused.deinit();
+
+ // TODO: divexact would be useful here
+ // TODO: don't copy r.q for div
+ try Int.divTrunc(&r.p, &unused, r.p, a);
+ try Int.divTrunc(&r.q, &unused, r.q, a);
+ }
+ }
+};
+
+const SignedDoubleLimb = @IntType(true, DoubleLimb.bit_count);
+
+fn gcd(rma: *Int, x: Int, y: Int) !void {
+ rma.assertWritable();
+ var r = rma;
+ var aliased = rma.limbs.ptr == x.limbs.ptr or rma.limbs.ptr == y.limbs.ptr;
+
+ var sr: Int = undefined;
+ if (aliased) {
+ sr = try Int.initCapacity(rma.allocator.?, math.max(x.len(), y.len()));
+ r = &sr;
+ aliased = true;
+ }
+ defer if (aliased) {
+ rma.swap(r);
+ r.deinit();
+ };
+
+ try gcdLehmer(r, x, y);
+}
+
+// Storage must live for the lifetime of the returned value
+fn FixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Int {
+ std.debug.assert(storage.len >= 2);
+
+ var A_is_positive = A >= 0;
+ const Au = @intCast(DoubleLimb, if (A < 0) -A else A);
+ storage[0] = @truncate(Limb, Au);
+ storage[1] = @truncate(Limb, Au >> Limb.bit_count);
+ var Ap = Int.initFixed(storage[0..2]);
+ Ap.setSign(A_is_positive);
+ return Ap;
+}
+
+fn gcdLehmer(r: *Int, xa: Int, ya: Int) !void {
+ var x = try xa.clone();
+ x.abs();
+ defer x.deinit();
+
+ var y = try ya.clone();
+ y.abs();
+ defer y.deinit();
+
+ if (x.cmp(y) < 0) {
+ x.swap(&y);
+ }
+
+ var T = try Int.init(r.allocator.?);
+ defer T.deinit();
+
+ while (y.len() > 1) {
+ debug.assert(x.isPositive() and y.isPositive());
+ debug.assert(x.len() >= y.len());
+
+ var xh: SignedDoubleLimb = x.limbs[x.len() - 1];
+ var yh: SignedDoubleLimb = if (x.len() > y.len()) 0 else y.limbs[x.len() - 1];
+
+ var A: SignedDoubleLimb = 1;
+ var B: SignedDoubleLimb = 0;
+ var C: SignedDoubleLimb = 0;
+ var D: SignedDoubleLimb = 1;
+
+ while (yh + C != 0 and yh + D != 0) {
+ const q = @divFloor(xh + A, yh + C);
+ const qp = @divFloor(xh + B, yh + D);
+ if (q != qp) {
+ break;
+ }
+
+ var t = A - q * C;
+ A = C;
+ C = t;
+ t = B - q * D;
+ B = D;
+ D = t;
+
+ t = xh - q * yh;
+ xh = yh;
+ yh = t;
+ }
+
+ if (B == 0) {
+ // T = x % y, r is unused
+ try Int.divTrunc(r, &T, x, y);
+ debug.assert(T.isPositive());
+
+ x.swap(&y);
+ y.swap(&T);
+ } else {
+ var storage: [8]Limb = undefined;
+ const Ap = FixedIntFromSignedDoubleLimb(A, storage[0..2]);
+ const Bp = FixedIntFromSignedDoubleLimb(B, storage[2..4]);
+ const Cp = FixedIntFromSignedDoubleLimb(C, storage[4..6]);
+ const Dp = FixedIntFromSignedDoubleLimb(D, storage[6..8]);
+
+ // T = Ax + By
+ try r.mul(x, Ap);
+ try T.mul(y, Bp);
+ try T.add(r.*, T);
+
+ // u = Cx + Dy, r as u
+ try x.mul(x, Cp);
+ try r.mul(y, Dp);
+ try r.add(x, r.*);
+
+ x.swap(&T);
+ y.swap(r);
+ }
+ }
+
+ // euclidean algorithm
+ debug.assert(x.cmp(y) >= 0);
+
+ while (!y.eqZero()) {
+ try Int.divTrunc(&T, r, x, y);
+ x.swap(&y);
+ y.swap(r);
+ }
+
+ r.swap(&x);
+}
+
+var buffer: [64 * 8192]u8 = undefined;
+var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
+var al = &fixed.allocator;
+
+test "big.rational gcd non-one small" {
+ var a = try Int.initSet(al, 17);
+ var b = try Int.initSet(al, 97);
+ var r = try Int.init(al);
+
+ try gcd(&r, a, b);
+
+ testing.expect((try r.to(u32)) == 1);
+}
+
+test "big.rational gcd non-one small" {
+ var a = try Int.initSet(al, 4864);
+ var b = try Int.initSet(al, 3458);
+ var r = try Int.init(al);
+
+ try gcd(&r, a, b);
+
+ testing.expect((try r.to(u32)) == 38);
+}
+
+test "big.rational gcd non-one large" {
+ var a = try Int.initSet(al, 0xffffffffffffffff);
+ var b = try Int.initSet(al, 0xffffffffffffffff7777);
+ var r = try Int.init(al);
+
+ try gcd(&r, a, b);
+
+ testing.expect((try r.to(u32)) == 4369);
+}
+
+test "big.rational gcd large multi-limb result" {
+ var a = try Int.initSet(al, 0x12345678123456781234567812345678123456781234567812345678);
+ var b = try Int.initSet(al, 0x12345671234567123456712345671234567123456712345671234567);
+ var r = try Int.init(al);
+
+ try gcd(&r, a, b);
+
+ testing.expect((try r.to(u256)) == 0xf000000ff00000fff0000ffff000fffff00ffffff1);
+}
+
+test "big.rational gcd one large" {
+ var a = try Int.initSet(al, 1897056385327307);
+ var b = try Int.initSet(al, 2251799813685248);
+ var r = try Int.init(al);
+
+ try gcd(&r, a, b);
+
+ testing.expect((try r.to(u64)) == 1);
+}
+
+fn extractLowBits(a: Int, comptime T: type) T {
+ testing.expect(@typeId(T) == builtin.TypeId.Int);
+
+ if (T.bit_count <= Limb.bit_count) {
+ return @truncate(T, a.limbs[0]);
+ } else {
+ var r: T = 0;
+ comptime var i: usize = 0;
+
+ // Remainder is always 0 since if T.bit_count >= Limb.bit_count -> Limb | T and both
+ // are powers of two.
+ inline while (i < T.bit_count / Limb.bit_count) : (i += 1) {
+ r |= math.shl(T, a.limbs[i], i * Limb.bit_count);
+ }
+
+ return r;
+ }
+}
+
+test "big.rational extractLowBits" {
+ var a = try Int.initSet(al, 0x11112222333344441234567887654321);
+
+ const a1 = extractLowBits(a, u8);
+ testing.expect(a1 == 0x21);
+
+ const a2 = extractLowBits(a, u16);
+ testing.expect(a2 == 0x4321);
+
+ const a3 = extractLowBits(a, u32);
+ testing.expect(a3 == 0x87654321);
+
+ const a4 = extractLowBits(a, u64);
+ testing.expect(a4 == 0x1234567887654321);
+
+ const a5 = extractLowBits(a, u128);
+ testing.expect(a5 == 0x11112222333344441234567887654321);
+}
+
+test "big.rational set" {
+ var a = try Rational.init(al);
+
+ try a.setInt(5);
+ testing.expect((try a.p.to(u32)) == 5);
+ testing.expect((try a.q.to(u32)) == 1);
+
+ try a.setRatio(7, 3);
+ testing.expect((try a.p.to(u32)) == 7);
+ testing.expect((try a.q.to(u32)) == 3);
+
+ try a.setRatio(9, 3);
+ testing.expect((try a.p.to(i32)) == 3);
+ testing.expect((try a.q.to(i32)) == 1);
+
+ try a.setRatio(-9, 3);
+ testing.expect((try a.p.to(i32)) == -3);
+ testing.expect((try a.q.to(i32)) == 1);
+
+ try a.setRatio(9, -3);
+ testing.expect((try a.p.to(i32)) == -3);
+ testing.expect((try a.q.to(i32)) == 1);
+
+ try a.setRatio(-9, -3);
+ testing.expect((try a.p.to(i32)) == 3);
+ testing.expect((try a.q.to(i32)) == 1);
+}
+
+test "big.rational setFloat" {
+ var a = try Rational.init(al);
+
+ try a.setFloat(f64, 2.5);
+ testing.expect((try a.p.to(i32)) == 5);
+ testing.expect((try a.q.to(i32)) == 2);
+
+ try a.setFloat(f32, -2.5);
+ testing.expect((try a.p.to(i32)) == -5);
+ testing.expect((try a.q.to(i32)) == 2);
+
+ try a.setFloat(f32, 3.141593);
+
+ // = 3.14159297943115234375
+ testing.expect((try a.p.to(u32)) == 3294199);
+ testing.expect((try a.q.to(u32)) == 1048576);
+
+ try a.setFloat(f64, 72.141593120712409172417410926841290461290467124);
+
+ // = 72.1415931207124145885245525278151035308837890625
+ testing.expect((try a.p.to(u128)) == 5076513310880537);
+ testing.expect((try a.q.to(u128)) == 70368744177664);
+}
+
+test "big.rational setFloatString" {
+ var a = try Rational.init(al);
+
+ try a.setFloatString("72.14159312071241458852455252781510353");
+
+ // = 72.1415931207124145885245525278151035308837890625
+ testing.expect((try a.p.to(u128)) == 7214159312071241458852455252781510353);
+ testing.expect((try a.q.to(u128)) == 100000000000000000000000000000000000);
+}
+
+test "big.rational toFloat" {
+ var a = try Rational.init(al);
+
+ // = 3.14159297943115234375
+ try a.setRatio(3294199, 1048576);
+ testing.expect((try a.toFloat(f64)) == 3.14159297943115234375);
+
+ // = 72.1415931207124145885245525278151035308837890625
+ try a.setRatio(5076513310880537, 70368744177664);
+ testing.expect((try a.toFloat(f64)) == 72.141593120712409172417410926841290461290467124);
+}
+
+test "big.rational set/to Float round-trip" {
+ var a = try Rational.init(al);
+ var prng = std.rand.DefaultPrng.init(0x5EED);
+ var i: usize = 0;
+ while (i < 512) : (i += 1) {
+ const r = prng.random.float(f64);
+ try a.setFloat(f64, r);
+ testing.expect((try a.toFloat(f64)) == r);
+ }
+}
+
+test "big.rational copy" {
+ var a = try Rational.init(al);
+
+ const b = try Int.initSet(al, 5);
+
+ try a.copyInt(b);
+ testing.expect((try a.p.to(u32)) == 5);
+ testing.expect((try a.q.to(u32)) == 1);
+
+ const c = try Int.initSet(al, 7);
+ const d = try Int.initSet(al, 3);
+
+ try a.copyRatio(c, d);
+ testing.expect((try a.p.to(u32)) == 7);
+ testing.expect((try a.q.to(u32)) == 3);
+
+ const e = try Int.initSet(al, 9);
+ const f = try Int.initSet(al, 3);
+
+ try a.copyRatio(e, f);
+ testing.expect((try a.p.to(u32)) == 3);
+ testing.expect((try a.q.to(u32)) == 1);
+}
+
+test "big.rational negate" {
+ var a = try Rational.init(al);
+
+ try a.setInt(-50);
+ testing.expect((try a.p.to(i32)) == -50);
+ testing.expect((try a.q.to(i32)) == 1);
+
+ a.negate();
+ testing.expect((try a.p.to(i32)) == 50);
+ testing.expect((try a.q.to(i32)) == 1);
+
+ a.negate();
+ testing.expect((try a.p.to(i32)) == -50);
+ testing.expect((try a.q.to(i32)) == 1);
+}
+
+test "big.rational abs" {
+ var a = try Rational.init(al);
+
+ try a.setInt(-50);
+ testing.expect((try a.p.to(i32)) == -50);
+ testing.expect((try a.q.to(i32)) == 1);
+
+ a.abs();
+ testing.expect((try a.p.to(i32)) == 50);
+ testing.expect((try a.q.to(i32)) == 1);
+
+ a.abs();
+ testing.expect((try a.p.to(i32)) == 50);
+ testing.expect((try a.q.to(i32)) == 1);
+}
+
+test "big.rational swap" {
+ var a = try Rational.init(al);
+ var b = try Rational.init(al);
+
+ try a.setRatio(50, 23);
+ try b.setRatio(17, 3);
+
+ testing.expect((try a.p.to(u32)) == 50);
+ testing.expect((try a.q.to(u32)) == 23);
+
+ testing.expect((try b.p.to(u32)) == 17);
+ testing.expect((try b.q.to(u32)) == 3);
+
+ a.swap(&b);
+
+ testing.expect((try a.p.to(u32)) == 17);
+ testing.expect((try a.q.to(u32)) == 3);
+
+ testing.expect((try b.p.to(u32)) == 50);
+ testing.expect((try b.q.to(u32)) == 23);
+}
+
+test "big.rational cmp" {
+ var a = try Rational.init(al);
+ var b = try Rational.init(al);
+
+ try a.setRatio(500, 231);
+ try b.setRatio(18903, 8584);
+ testing.expect((try a.cmp(b)) < 0);
+
+ try a.setRatio(890, 10);
+ try b.setRatio(89, 1);
+ testing.expect((try a.cmp(b)) == 0);
+}
+
+test "big.rational add single-limb" {
+ var a = try Rational.init(al);
+ var b = try Rational.init(al);
+
+ try a.setRatio(500, 231);
+ try b.setRatio(18903, 8584);
+ testing.expect((try a.cmp(b)) < 0);
+
+ try a.setRatio(890, 10);
+ try b.setRatio(89, 1);
+ testing.expect((try a.cmp(b)) == 0);
+}
+
+test "big.rational add" {
+ var a = try Rational.init(al);
+ var b = try Rational.init(al);
+ var r = try Rational.init(al);
+
+ try a.setRatio(78923, 23341);
+ try b.setRatio(123097, 12441414);
+ try a.add(a, b);
+
+ try r.setRatio(984786924199, 290395044174);
+ testing.expect((try a.cmp(r)) == 0);
+}
+
+test "big.rational sub" {
+ var a = try Rational.init(al);
+ var b = try Rational.init(al);
+ var r = try Rational.init(al);
+
+ try a.setRatio(78923, 23341);
+ try b.setRatio(123097, 12441414);
+ try a.sub(a, b);
+
+ try r.setRatio(979040510045, 290395044174);
+ testing.expect((try a.cmp(r)) == 0);
+}
+
+test "big.rational mul" {
+ var a = try Rational.init(al);
+ var b = try Rational.init(al);
+ var r = try Rational.init(al);
+
+ try a.setRatio(78923, 23341);
+ try b.setRatio(123097, 12441414);
+ try a.mul(a, b);
+
+ try r.setRatio(571481443, 17082061422);
+ testing.expect((try a.cmp(r)) == 0);
+}
+
+test "big.rational div" {
+ var a = try Rational.init(al);
+ var b = try Rational.init(al);
+ var r = try Rational.init(al);
+
+ try a.setRatio(78923, 23341);
+ try b.setRatio(123097, 12441414);
+ try a.div(a, b);
+
+ try r.setRatio(75531824394, 221015929);
+ testing.expect((try a.cmp(r)) == 0);
+}
+
+test "big.rational div" {
+ var a = try Rational.init(al);
+ var r = try Rational.init(al);
+
+ try a.setRatio(78923, 23341);
+ a.invert();
+
+ try r.setRatio(23341, 78923);
+ testing.expect((try a.cmp(r)) == 0);
+
+ try a.setRatio(-78923, 23341);
+ a.invert();
+
+ try r.setRatio(-23341, 78923);
+ testing.expect((try a.cmp(r)) == 0);
+}
diff --git a/std/math/cbrt.zig b/std/math/cbrt.zig
index 9497255269..5241e31323 100644
--- a/std/math/cbrt.zig
+++ b/std/math/cbrt.zig
@@ -1,13 +1,19 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - cbrt(+-0) = +-0
-// - cbrt(+-inf) = +-inf
-// - cbrt(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/cbrtf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/cbrt.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the cube root of x.
+///
+/// Special Cases:
+/// - cbrt(+-0) = +-0
+/// - cbrt(+-inf) = +-inf
+/// - cbrt(nan) = nan
pub fn cbrt(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/ceil.zig b/std/math/ceil.zig
index da83e0ec59..5f86093a6d 100644
--- a/std/math/ceil.zig
+++ b/std/math/ceil.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - ceil(+-0) = +-0
-// - ceil(+-inf) = +-inf
-// - ceil(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c
const builtin = @import("builtin");
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the least integer value greater than of equal to x.
+///
+/// Special Cases:
+/// - ceil(+-0) = +-0
+/// - ceil(+-inf) = +-inf
+/// - ceil(nan) = nan
pub fn ceil(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/complex.zig b/std/math/complex.zig
index cc0573b227..e5574f9cee 100644
--- a/std/math/complex.zig
+++ b/std/math/complex.zig
@@ -23,13 +23,18 @@ pub const sqrt = @import("complex/sqrt.zig").sqrt;
pub const tanh = @import("complex/tanh.zig").tanh;
pub const tan = @import("complex/tan.zig").tan;
+/// A complex number consisting of a real an imaginary part. T must be a floating-point value.
pub fn Complex(comptime T: type) type {
return struct {
const Self = @This();
+ /// Real part.
re: T,
+
+ /// Imaginary part.
im: T,
+ /// Create a new Complex number from the given real and imaginary parts.
pub fn new(re: T, im: T) Self {
return Self{
.re = re,
@@ -37,6 +42,7 @@ pub fn Complex(comptime T: type) type {
};
}
+ /// Returns the sum of two complex numbers.
pub fn add(self: Self, other: Self) Self {
return Self{
.re = self.re + other.re,
@@ -44,6 +50,7 @@ pub fn Complex(comptime T: type) type {
};
}
+ /// Returns the subtraction of two complex numbers.
pub fn sub(self: Self, other: Self) Self {
return Self{
.re = self.re - other.re,
@@ -51,6 +58,7 @@ pub fn Complex(comptime T: type) type {
};
}
+ /// Returns the product of two complex numbers.
pub fn mul(self: Self, other: Self) Self {
return Self{
.re = self.re * other.re - self.im * other.im,
@@ -58,6 +66,7 @@ pub fn Complex(comptime T: type) type {
};
}
+ /// Returns the quotient of two complex numbers.
pub fn div(self: Self, other: Self) Self {
const re_num = self.re * other.re + self.im * other.im;
const im_num = self.im * other.re - self.re * other.im;
@@ -69,6 +78,7 @@ pub fn Complex(comptime T: type) type {
};
}
+ /// Returns the complex conjugate of a number.
pub fn conjugate(self: Self) Self {
return Self{
.re = self.re,
@@ -76,6 +86,7 @@ pub fn Complex(comptime T: type) type {
};
}
+ /// Returns the reciprocal of a complex number.
pub fn reciprocal(self: Self) Self {
const m = self.re * self.re + self.im * self.im;
return Self{
@@ -84,6 +95,7 @@ pub fn Complex(comptime T: type) type {
};
}
+ /// Returns the magnitude of a complex number.
pub fn magnitude(self: Self) T {
return math.sqrt(self.re * self.re + self.im * self.im);
}
diff --git a/std/math/complex/abs.zig b/std/math/complex/abs.zig
index e1368d6ef6..8105f57218 100644
--- a/std/math/complex/abs.zig
+++ b/std/math/complex/abs.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the absolute value (modulus) of z.
pub fn abs(z: var) @typeOf(z.re) {
const T = @typeOf(z.re);
return math.hypot(T, z.re, z.im);
diff --git a/std/math/complex/acos.zig b/std/math/complex/acos.zig
index 8aed26a71b..f3526cc9ff 100644
--- a/std/math/complex/acos.zig
+++ b/std/math/complex/acos.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the arc-cosine of z.
pub fn acos(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
const q = cmath.asin(z);
diff --git a/std/math/complex/acosh.zig b/std/math/complex/acosh.zig
index e72bf431fe..6f0fd2e36c 100644
--- a/std/math/complex/acosh.zig
+++ b/std/math/complex/acosh.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the hyperbolic arc-cosine of z.
pub fn acosh(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
const q = cmath.acos(z);
diff --git a/std/math/complex/arg.zig b/std/math/complex/arg.zig
index 0a2441d1fd..d0c9588b8d 100644
--- a/std/math/complex/arg.zig
+++ b/std/math/complex/arg.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the angular component (in radians) of z.
pub fn arg(z: var) @typeOf(z.re) {
const T = @typeOf(z.re);
return math.atan2(T, z.im, z.re);
diff --git a/std/math/complex/asin.zig b/std/math/complex/asin.zig
index 6be775d748..76f94a286c 100644
--- a/std/math/complex/asin.zig
+++ b/std/math/complex/asin.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+// Returns the arc-sine of z.
pub fn asin(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
const x = z.re;
diff --git a/std/math/complex/asinh.zig b/std/math/complex/asinh.zig
index 8e09036750..da065aad01 100644
--- a/std/math/complex/asinh.zig
+++ b/std/math/complex/asinh.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the hyperbolic arc-sine of z.
pub fn asinh(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
const q = Complex(T).new(-z.im, z.re);
diff --git a/std/math/complex/atan.zig b/std/math/complex/atan.zig
index 6b83adbd97..89bc8dfaf0 100644
--- a/std/math/complex/atan.zig
+++ b/std/math/complex/atan.zig
@@ -1,9 +1,16 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/catanf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/catan.c
+
const std = @import("../../std.zig");
const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the arc-tangent of z.
pub fn atan(z: var) @typeOf(z) {
const T = @typeOf(z.re);
return switch (T) {
diff --git a/std/math/complex/atanh.zig b/std/math/complex/atanh.zig
index 8edfb6e78e..225e7c61de 100644
--- a/std/math/complex/atanh.zig
+++ b/std/math/complex/atanh.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the hyperbolic arc-tangent of z.
pub fn atanh(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
const q = Complex(T).new(-z.im, z.re);
diff --git a/std/math/complex/conj.zig b/std/math/complex/conj.zig
index 7a42d365ea..bd71ca3c06 100644
--- a/std/math/complex/conj.zig
+++ b/std/math/complex/conj.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the complex conjugate of z.
pub fn conj(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
return Complex(T).new(z.re, -z.im);
diff --git a/std/math/complex/cos.zig b/std/math/complex/cos.zig
index 71f9603c75..332009ffe5 100644
--- a/std/math/complex/cos.zig
+++ b/std/math/complex/cos.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the cosine of z.
pub fn cos(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
const p = Complex(T).new(-z.im, z.re);
diff --git a/std/math/complex/cosh.zig b/std/math/complex/cosh.zig
index 9806e41170..be7bfde963 100644
--- a/std/math/complex/cosh.zig
+++ b/std/math/complex/cosh.zig
@@ -1,3 +1,9 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccoshf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccosh.c
+
const std = @import("../../std.zig");
const testing = std.testing;
const math = std.math;
@@ -6,6 +12,7 @@ const Complex = cmath.Complex;
const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
+/// Returns the hyperbolic arc-cosine of z.
pub fn cosh(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
return switch (T) {
diff --git a/std/math/complex/exp.zig b/std/math/complex/exp.zig
index c74ac2fc08..9b686bebc3 100644
--- a/std/math/complex/exp.zig
+++ b/std/math/complex/exp.zig
@@ -1,3 +1,9 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexpf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexp.c
+
const std = @import("../../std.zig");
const testing = std.testing;
const math = std.math;
@@ -6,6 +12,7 @@ const Complex = cmath.Complex;
const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
+/// Returns e raised to the power of z (e^z).
pub fn exp(z: var) @typeOf(z) {
const T = @typeOf(z.re);
diff --git a/std/math/complex/ldexp.zig b/std/math/complex/ldexp.zig
index 6b4306bf77..d6f810793f 100644
--- a/std/math/complex/ldexp.zig
+++ b/std/math/complex/ldexp.zig
@@ -1,9 +1,16 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/__cexpf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/__cexp.c
+
const std = @import("../../std.zig");
const debug = std.debug;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns exp(z) scaled to avoid overflow.
pub fn ldexp_cexp(z: var, expt: i32) @typeOf(z) {
const T = @typeOf(z.re);
diff --git a/std/math/complex/log.zig b/std/math/complex/log.zig
index 2b43a6970f..762b4fde9a 100644
--- a/std/math/complex/log.zig
+++ b/std/math/complex/log.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the natural logarithm of z.
pub fn log(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
const r = cmath.abs(z);
diff --git a/std/math/complex/pow.zig b/std/math/complex/pow.zig
index 9174bb3626..a2480453fc 100644
--- a/std/math/complex/pow.zig
+++ b/std/math/complex/pow.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns z raised to the complex power of c.
pub fn pow(comptime T: type, z: T, c: T) T {
const p = cmath.log(z);
const q = c.mul(p);
diff --git a/std/math/complex/proj.zig b/std/math/complex/proj.zig
index aadcff6ff6..c8f2d9fc6d 100644
--- a/std/math/complex/proj.zig
+++ b/std/math/complex/proj.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the projection of z onto the riemann sphere.
pub fn proj(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
diff --git a/std/math/complex/sin.zig b/std/math/complex/sin.zig
index 049631f31e..9ddc3a7a80 100644
--- a/std/math/complex/sin.zig
+++ b/std/math/complex/sin.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the sine of z.
pub fn sin(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
const p = Complex(T).new(-z.im, z.re);
diff --git a/std/math/complex/sinh.zig b/std/math/complex/sinh.zig
index 0b656e5354..6286d8447f 100644
--- a/std/math/complex/sinh.zig
+++ b/std/math/complex/sinh.zig
@@ -1,3 +1,9 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinh.c
+
const std = @import("../../std.zig");
const testing = std.testing;
const math = std.math;
@@ -6,6 +12,7 @@ const Complex = cmath.Complex;
const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
+/// Returns the hyperbolic sine of z.
pub fn sinh(z: var) @typeOf(z) {
const T = @typeOf(z.re);
return switch (T) {
diff --git a/std/math/complex/sqrt.zig b/std/math/complex/sqrt.zig
index e935d0b238..36f4c28e29 100644
--- a/std/math/complex/sqrt.zig
+++ b/std/math/complex/sqrt.zig
@@ -1,9 +1,17 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/csqrtf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/csqrt.c
+
const std = @import("../../std.zig");
const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the square root of z. The real and imaginary parts of the result have the same sign
+/// as the imaginary part of z.
pub fn sqrt(z: var) @typeOf(z) {
const T = @typeOf(z.re);
diff --git a/std/math/complex/tan.zig b/std/math/complex/tan.zig
index 45e2873eb6..398b8295ca 100644
--- a/std/math/complex/tan.zig
+++ b/std/math/complex/tan.zig
@@ -4,6 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the tanget of z.
pub fn tan(z: var) Complex(@typeOf(z.re)) {
const T = @typeOf(z.re);
const q = Complex(T).new(-z.im, z.re);
diff --git a/std/math/complex/tanh.zig b/std/math/complex/tanh.zig
index de905ee3f6..5c14ec66f2 100644
--- a/std/math/complex/tanh.zig
+++ b/std/math/complex/tanh.zig
@@ -1,9 +1,16 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanh.c
+
const std = @import("../../std.zig");
const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
+/// Returns the hyperbolic tangent of z.
pub fn tanh(z: var) @typeOf(z) {
const T = @typeOf(z.re);
return switch (T) {
diff --git a/std/math/copysign.zig b/std/math/copysign.zig
index ff8140b3ab..e4d90c395e 100644
--- a/std/math/copysign.zig
+++ b/std/math/copysign.zig
@@ -1,8 +1,15 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/math/copysignf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/copysign.c
+
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns a value with the magnitude of x and the sign of y.
pub fn copysign(comptime T: type, x: T, y: T) T {
return switch (T) {
f16 => copysign16(x, y),
diff --git a/std/math/cos.zig b/std/math/cos.zig
index 9479482894..dc4aff59d6 100644
--- a/std/math/cos.zig
+++ b/std/math/cos.zig
@@ -1,18 +1,23 @@
-// Special Cases:
+// Ported from go, which is licensed under a BSD-3 license.
+// https://golang.org/LICENSE
//
-// - cos(+-inf) = nan
-// - cos(nan) = nan
+// https://golang.org/src/math/sin.go
const builtin = @import("builtin");
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the cosine of the radian value x.
+///
+/// Special Cases:
+/// - cos(+-inf) = nan
+/// - cos(nan) = nan
pub fn cos(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
- f32 => cos32(x),
- f64 => cos64(x),
+ f32 => cos_(f32, x),
+ f64 => cos_(f64, x),
else => @compileError("cos not implemented for " ++ @typeName(T)),
};
}
@@ -33,78 +38,24 @@ const C3 = 2.48015872888517045348E-5;
const C4 = -1.38888888888730564116E-3;
const C5 = 4.16666666666665929218E-2;
-// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
-//
-// This may have slight differences on some edge cases and may need to replaced if so.
-fn cos32(x_: f32) f32 {
- const pi4a = 7.85398125648498535156e-1;
- const pi4b = 3.77489470793079817668E-8;
- const pi4c = 2.69515142907905952645E-15;
- const m4pi = 1.273239544735162542821171882678754627704620361328125;
-
- var x = x_;
- if (math.isNan(x) or math.isInf(x)) {
- return math.nan(f32);
- }
-
- var sign = false;
- if (x < 0) {
- x = -x;
- }
-
- var y = math.floor(x * m4pi);
- var j = @floatToInt(i64, y);
+const pi4a = 7.85398125648498535156e-1;
+const pi4b = 3.77489470793079817668E-8;
+const pi4c = 2.69515142907905952645E-15;
+const m4pi = 1.273239544735162542821171882678754627704620361328125;
- if (j & 1 == 1) {
- j += 1;
- y += 1;
- }
-
- j &= 7;
- if (j > 3) {
- j -= 4;
- sign = !sign;
- }
- if (j > 1) {
- sign = !sign;
- }
-
- const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
- const w = z * z;
-
- const r = r: {
- if (j == 1 or j == 2) {
- break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
- } else {
- break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
- }
- };
-
- if (sign) {
- return -r;
- } else {
- return r;
- }
-}
-
-fn cos64(x_: f64) f64 {
- const pi4a = 7.85398125648498535156e-1;
- const pi4b = 3.77489470793079817668E-8;
- const pi4c = 2.69515142907905952645E-15;
- const m4pi = 1.273239544735162542821171882678754627704620361328125;
+fn cos_(comptime T: type, x_: T) T {
+ const I = @IntType(true, T.bit_count);
var x = x_;
if (math.isNan(x) or math.isInf(x)) {
- return math.nan(f64);
+ return math.nan(T);
}
var sign = false;
- if (x < 0) {
- x = -x;
- }
+ x = math.fabs(x);
var y = math.floor(x * m4pi);
- var j = @floatToInt(i64, y);
+ var j = @floatToInt(I, y);
if (j & 1 == 1) {
j += 1;
@@ -123,56 +74,51 @@ fn cos64(x_: f64) f64 {
const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
const w = z * z;
- const r = r: {
- if (j == 1 or j == 2) {
- break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
- } else {
- break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
- }
- };
+ const r = if (j == 1 or j == 2)
+ z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))))
+ else
+ 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
- if (sign) {
- return -r;
- } else {
- return r;
- }
+ return if (sign) -r else r;
}
test "math.cos" {
- expect(cos(f32(0.0)) == cos32(0.0));
- expect(cos(f64(0.0)) == cos64(0.0));
+ expect(cos(f32(0.0)) == cos_(f32, 0.0));
+ expect(cos(f64(0.0)) == cos_(f64, 0.0));
}
test "math.cos32" {
const epsilon = 0.000001;
- expect(math.approxEq(f32, cos32(0.0), 1.0, epsilon));
- expect(math.approxEq(f32, cos32(0.2), 0.980067, epsilon));
- expect(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon));
- expect(math.approxEq(f32, cos32(1.5), 0.070737, epsilon));
- expect(math.approxEq(f32, cos32(37.45), 0.969132, epsilon));
- expect(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));
+ expect(math.approxEq(f32, cos_(f32, 0.0), 1.0, epsilon));
+ expect(math.approxEq(f32, cos_(f32, 0.2), 0.980067, epsilon));
+ expect(math.approxEq(f32, cos_(f32, 0.8923), 0.627623, epsilon));
+ expect(math.approxEq(f32, cos_(f32, 1.5), 0.070737, epsilon));
+ expect(math.approxEq(f32, cos_(f32, -1.5), 0.070737, epsilon));
+ expect(math.approxEq(f32, cos_(f32, 37.45), 0.969132, epsilon));
+ expect(math.approxEq(f32, cos_(f32, 89.123), 0.400798, epsilon));
}
test "math.cos64" {
const epsilon = 0.000001;
- expect(math.approxEq(f64, cos64(0.0), 1.0, epsilon));
- expect(math.approxEq(f64, cos64(0.2), 0.980067, epsilon));
- expect(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon));
- expect(math.approxEq(f64, cos64(1.5), 0.070737, epsilon));
- expect(math.approxEq(f64, cos64(37.45), 0.969132, epsilon));
- expect(math.approxEq(f64, cos64(89.123), 0.40080, epsilon));
+ expect(math.approxEq(f64, cos_(f64, 0.0), 1.0, epsilon));
+ expect(math.approxEq(f64, cos_(f64, 0.2), 0.980067, epsilon));
+ expect(math.approxEq(f64, cos_(f64, 0.8923), 0.627623, epsilon));
+ expect(math.approxEq(f64, cos_(f64, 1.5), 0.070737, epsilon));
+ expect(math.approxEq(f64, cos_(f64, -1.5), 0.070737, epsilon));
+ expect(math.approxEq(f64, cos_(f64, 37.45), 0.969132, epsilon));
+ expect(math.approxEq(f64, cos_(f64, 89.123), 0.40080, epsilon));
}
test "math.cos32.special" {
- expect(math.isNan(cos32(math.inf(f32))));
- expect(math.isNan(cos32(-math.inf(f32))));
- expect(math.isNan(cos32(math.nan(f32))));
+ expect(math.isNan(cos_(f32, math.inf(f32))));
+ expect(math.isNan(cos_(f32, -math.inf(f32))));
+ expect(math.isNan(cos_(f32, math.nan(f32))));
}
test "math.cos64.special" {
- expect(math.isNan(cos64(math.inf(f64))));
- expect(math.isNan(cos64(-math.inf(f64))));
- expect(math.isNan(cos64(math.nan(f64))));
+ expect(math.isNan(cos_(f64, math.inf(f64))));
+ expect(math.isNan(cos_(f64, -math.inf(f64))));
+ expect(math.isNan(cos_(f64, math.nan(f64))));
}
diff --git a/std/math/cosh.zig b/std/math/cosh.zig
index eb3082e5fa..75c5c15ec1 100644
--- a/std/math/cosh.zig
+++ b/std/math/cosh.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - cosh(+-0) = 1
-// - cosh(+-inf) = +inf
-// - cosh(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/coshf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/cosh.c
const builtin = @import("builtin");
const std = @import("../std.zig");
@@ -11,6 +11,12 @@ const expo2 = @import("expo2.zig").expo2;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns the hyperbolic cosine of x.
+///
+/// Special Cases:
+/// - cosh(+-0) = 1
+/// - cosh(+-inf) = +inf
+/// - cosh(nan) = nan
pub fn cosh(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/exp.zig b/std/math/exp.zig
index aabccffd0b..ad058646a4 100644
--- a/std/math/exp.zig
+++ b/std/math/exp.zig
@@ -1,13 +1,19 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - exp(+inf) = +inf
-// - exp(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/expf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/exp.c
const std = @import("../std.zig");
const math = std.math;
const assert = std.debug.assert;
const builtin = @import("builtin");
+/// Returns e raised to the power of x (e^x).
+///
+/// Special Cases:
+/// - exp(+inf) = +inf
+/// - exp(nan) = nan
pub fn exp(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/exp2.zig b/std/math/exp2.zig
index 392d45bf68..07a39576b1 100644
--- a/std/math/exp2.zig
+++ b/std/math/exp2.zig
@@ -1,12 +1,18 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - exp2(+inf) = +inf
-// - exp2(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/exp2f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/exp2.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns 2 raised to the power of x (2^x).
+///
+/// Special Cases:
+/// - exp2(+inf) = +inf
+/// - exp2(nan) = nan
pub fn exp2(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/expm1.zig b/std/math/expm1.zig
index b83cc3e82e..5e347f86f6 100644
--- a/std/math/expm1.zig
+++ b/std/math/expm1.zig
@@ -1,14 +1,23 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - expm1(+inf) = +inf
-// - expm1(-inf) = -1
-// - expm1(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/expmf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/expm.c
+
+// TODO: Updated recently.
const builtin = @import("builtin");
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns e raised to the power of x, minus 1 (e^x - 1). This is more accurate than exp(e, x) - 1
+/// when x is near 0.
+///
+/// Special Cases:
+/// - expm1(+inf) = +inf
+/// - expm1(-inf) = -1
+/// - expm1(nan) = nan
pub fn expm1(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/expo2.zig b/std/math/expo2.zig
index 57e2bf34c9..c00098a5a7 100644
--- a/std/math/expo2.zig
+++ b/std/math/expo2.zig
@@ -1,5 +1,12 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/math/__expo2f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/__expo2.c
+
const math = @import("../math.zig");
+/// Returns exp(x) / 2 for x >= log(maxFloat(T)).
pub fn expo2(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/fabs.zig b/std/math/fabs.zig
index e30f788ae7..6469f38835 100644
--- a/std/math/fabs.zig
+++ b/std/math/fabs.zig
@@ -1,13 +1,19 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - fabs(+-inf) = +inf
-// - fabs(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/fabsf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/fabs.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns the absolute value of x.
+///
+/// Special Cases:
+/// - fabs(+-inf) = +inf
+/// - fabs(nan) = nan
pub fn fabs(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/floor.zig b/std/math/floor.zig
index ab45a8fee7..e5ff2b1fc1 100644
--- a/std/math/floor.zig
+++ b/std/math/floor.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - floor(+-0) = +-0
-// - floor(+-inf) = +-inf
-// - floor(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c
const builtin = @import("builtin");
const expect = std.testing.expect;
const std = @import("../std.zig");
const math = std.math;
+/// Returns the greatest integer value less than or equal to x.
+///
+/// Special Cases:
+/// - floor(+-0) = +-0
+/// - floor(+-inf) = +-inf
+/// - floor(nan) = nan
pub fn floor(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/fma.zig b/std/math/fma.zig
index a317bc96de..19c306fa2a 100644
--- a/std/math/fma.zig
+++ b/std/math/fma.zig
@@ -1,7 +1,14 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/math/fmaf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/fma.c
+
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns x * y + z with a single rounding error.
pub fn fma(comptime T: type, x: T, y: T, z: T) T {
return switch (T) {
f32 => fma32(x, y, z),
@@ -16,7 +23,7 @@ fn fma32(x: f32, y: f32, z: f32) f32 {
const u = @bitCast(u64, xy_z);
const e = (u >> 52) & 0x7FF;
- if ((u & 0x1FFFFFFF) != 0x10000000 or e == 0x7FF or xy_z - xy == z) {
+ if ((u & 0x1FFFFFFF) != 0x10000000 or e == 0x7FF or (xy_z - xy == z and xy_z - z == xy)) {
return @floatCast(f32, xy_z);
} else {
// TODO: Handle inexact case with double-rounding
@@ -24,6 +31,7 @@ fn fma32(x: f32, y: f32, z: f32) f32 {
}
}
+// NOTE: Upstream fma.c has been rewritten completely to raise fp exceptions more accurately.
fn fma64(x: f64, y: f64, z: f64) f64 {
if (!math.isFinite(x) or !math.isFinite(y)) {
return x * y + z;
diff --git a/std/math/frexp.zig b/std/math/frexp.zig
index 35eec315d9..2759cd6492 100644
--- a/std/math/frexp.zig
+++ b/std/math/frexp.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - frexp(+-0) = +-0, 0
-// - frexp(+-inf) = +-inf, 0
-// - frexp(nan) = nan, undefined
+// https://git.musl-libc.org/cgit/musl/tree/src/math/frexpf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/frexp.c
const std = @import("../std.zig");
const math = std.math;
@@ -17,6 +17,13 @@ fn frexp_result(comptime T: type) type {
pub const frexp32_result = frexp_result(f32);
pub const frexp64_result = frexp_result(f64);
+/// Breaks x into a normalized fraction and an integral power of two.
+/// f == frac * 2^exp, with |frac| in the interval [0.5, 1).
+///
+/// Special Cases:
+/// - frexp(+-0) = +-0, 0
+/// - frexp(+-inf) = +-inf, 0
+/// - frexp(nan) = nan, undefined
pub fn frexp(x: var) frexp_result(@typeOf(x)) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/hypot.zig b/std/math/hypot.zig
index fddbe7c068..c15da1495e 100644
--- a/std/math/hypot.zig
+++ b/std/math/hypot.zig
@@ -1,15 +1,21 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - hypot(+-inf, y) = +inf
-// - hypot(x, +-inf) = +inf
-// - hypot(nan, y) = nan
-// - hypot(x, nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/hypotf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/hypot.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns sqrt(x * x + y * y), avoiding unncessary overflow and underflow.
+///
+/// Special Cases:
+/// - hypot(+-inf, y) = +inf
+/// - hypot(x, +-inf) = +inf
+/// - hypot(nan, y) = nan
+/// - hypot(x, nan) = nan
pub fn hypot(comptime T: type, x: T, y: T) T {
return switch (T) {
f32 => hypot32(x, y),
diff --git a/std/math/ilogb.zig b/std/math/ilogb.zig
index 2dfd42a62c..fe4158a6dd 100644
--- a/std/math/ilogb.zig
+++ b/std/math/ilogb.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - ilogb(+-inf) = maxInt(i32)
-// - ilogb(0) = maxInt(i32)
-// - ilogb(nan) = maxInt(i32)
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ilogbf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ilogb.c
const std = @import("../std.zig");
const math = std.math;
@@ -10,6 +10,12 @@ const expect = std.testing.expect;
const maxInt = std.math.maxInt;
const minInt = std.math.minInt;
+/// Returns the binary exponent of x as an integer.
+///
+/// Special Cases:
+/// - ilogb(+-inf) = maxInt(i32)
+/// - ilogb(0) = maxInt(i32)
+/// - ilogb(nan) = maxInt(i32)
pub fn ilogb(x: var) i32 {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/inf.zig b/std/math/inf.zig
index e1bfbb197a..86ff245533 100644
--- a/std/math/inf.zig
+++ b/std/math/inf.zig
@@ -1,6 +1,7 @@
const std = @import("../std.zig");
const math = std.math;
+/// Returns value inf for the type T.
pub fn inf(comptime T: type) T {
return switch (T) {
f16 => math.inf_f16,
diff --git a/std/math/isfinite.zig b/std/math/isfinite.zig
index ee8a5ff590..99eba668f9 100644
--- a/std/math/isfinite.zig
+++ b/std/math/isfinite.zig
@@ -3,6 +3,7 @@ const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns whether x is a finite value.
pub fn isFinite(x: var) bool {
const T = @typeOf(x);
switch (T) {
diff --git a/std/math/isinf.zig b/std/math/isinf.zig
index 1b1759bd36..37934f4cf4 100644
--- a/std/math/isinf.zig
+++ b/std/math/isinf.zig
@@ -3,6 +3,7 @@ const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns whether x is an infinity, ignoring sign.
pub fn isInf(x: var) bool {
const T = @typeOf(x);
switch (T) {
@@ -28,6 +29,7 @@ pub fn isInf(x: var) bool {
}
}
+/// Returns whether x is an infinity with a positive sign.
pub fn isPositiveInf(x: var) bool {
const T = @typeOf(x);
switch (T) {
@@ -49,6 +51,7 @@ pub fn isPositiveInf(x: var) bool {
}
}
+/// Returns whether x is an infinity with a negative sign.
pub fn isNegativeInf(x: var) bool {
const T = @typeOf(x);
switch (T) {
diff --git a/std/math/isnan.zig b/std/math/isnan.zig
index 9e541bf0a2..cf8cd2e1c2 100644
--- a/std/math/isnan.zig
+++ b/std/math/isnan.zig
@@ -3,13 +3,15 @@ const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns whether x is a nan.
pub fn isNan(x: var) bool {
return x != x;
}
-/// Note: A signalling nan is identical to a standard nan right now but may have a different bit
-/// representation in the future when required.
+/// Returns whether x is a signalling nan.
pub fn isSignalNan(x: var) bool {
+ // Note: A signalling nan is identical to a standard nan right now but may have a different bit
+ // representation in the future when required.
return isNan(x);
}
diff --git a/std/math/isnormal.zig b/std/math/isnormal.zig
index cddcada1d3..f8611ef805 100644
--- a/std/math/isnormal.zig
+++ b/std/math/isnormal.zig
@@ -3,6 +3,7 @@ const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+// Returns whether x has a normalized representation (i.e. integer part of mantissa is 1).
pub fn isNormal(x: var) bool {
const T = @typeOf(x);
switch (T) {
diff --git a/std/math/ln.zig b/std/math/ln.zig
index 82b212f00f..c5d4c9ff25 100644
--- a/std/math/ln.zig
+++ b/std/math/ln.zig
@@ -1,9 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - ln(+inf) = +inf
-// - ln(0) = -inf
-// - ln(x) = nan if x < 0
-// - ln(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/lnf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ln.c
const std = @import("../std.zig");
const math = std.math;
@@ -11,6 +10,13 @@ const expect = std.testing.expect;
const builtin = @import("builtin");
const TypeId = builtin.TypeId;
+/// Returns the natural logarithm of x.
+///
+/// Special Cases:
+/// - ln(+inf) = +inf
+/// - ln(0) = -inf
+/// - ln(x) = nan if x < 0
+/// - ln(nan) = nan
pub fn ln(x: var) @typeOf(x) {
const T = @typeOf(x);
switch (@typeId(T)) {
diff --git a/std/math/log.zig b/std/math/log.zig
index 100dc2fb7f..77f3639fd2 100644
--- a/std/math/log.zig
+++ b/std/math/log.zig
@@ -1,9 +1,16 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/math/logf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log.c
+
const std = @import("../std.zig");
const math = std.math;
const builtin = @import("builtin");
const TypeId = builtin.TypeId;
const expect = std.testing.expect;
+/// Returns the logarithm of x for the provided base.
pub fn log(comptime T: type, base: T, x: T) T {
if (base == 2) {
return math.log2(x);
diff --git a/std/math/log10.zig b/std/math/log10.zig
index 7311778ddd..9b0bc3ac52 100644
--- a/std/math/log10.zig
+++ b/std/math/log10.zig
@@ -1,9 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - log10(+inf) = +inf
-// - log10(0) = -inf
-// - log10(x) = nan if x < 0
-// - log10(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log10f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log10.c
const std = @import("../std.zig");
const math = std.math;
@@ -12,6 +11,13 @@ const builtin = @import("builtin");
const TypeId = builtin.TypeId;
const maxInt = std.math.maxInt;
+/// Returns the base-10 logarithm of x.
+///
+/// Special Cases:
+/// - log10(+inf) = +inf
+/// - log10(0) = -inf
+/// - log10(x) = nan if x < 0
+/// - log10(nan) = nan
pub fn log10(x: var) @typeOf(x) {
const T = @typeOf(x);
switch (@typeId(T)) {
diff --git a/std/math/log1p.zig b/std/math/log1p.zig
index c9be1132be..bae6deb536 100644
--- a/std/math/log1p.zig
+++ b/std/math/log1p.zig
@@ -1,16 +1,22 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - log1p(+inf) = +inf
-// - log1p(+-0) = +-0
-// - log1p(-1) = -inf
-// - log1p(x) = nan if x < -1
-// - log1p(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log1pf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log1p.c
const builtin = @import("builtin");
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the natural logarithm of 1 + x with greater accuracy when x is near zero.
+///
+/// Special Cases:
+/// - log1p(+inf) = +inf
+/// - log1p(+-0) = +-0
+/// - log1p(-1) = -inf
+/// - log1p(x) = nan if x < -1
+/// - log1p(nan) = nan
pub fn log1p(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/log2.zig b/std/math/log2.zig
index e2dbf4105a..88450a7ffd 100644
--- a/std/math/log2.zig
+++ b/std/math/log2.zig
@@ -1,9 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - log2(+inf) = +inf
-// - log2(0) = -inf
-// - log2(x) = nan if x < 0
-// - log2(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log2f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log2.c
const std = @import("../std.zig");
const math = std.math;
@@ -12,6 +11,13 @@ const builtin = @import("builtin");
const TypeId = builtin.TypeId;
const maxInt = std.math.maxInt;
+/// Returns the base-2 logarithm of x.
+///
+/// Special Cases:
+/// - log2(+inf) = +inf
+/// - log2(0) = -inf
+/// - log2(x) = nan if x < 0
+/// - log2(nan) = nan
pub fn log2(x: var) @typeOf(x) {
const T = @typeOf(x);
switch (@typeId(T)) {
diff --git a/std/math/modf.zig b/std/math/modf.zig
index e5a4964e63..92194d4c75 100644
--- a/std/math/modf.zig
+++ b/std/math/modf.zig
@@ -1,7 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - modf(+-inf) = +-inf, nan
-// - modf(nan) = nan, nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/modff.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/modf.c
const std = @import("../std.zig");
const math = std.math;
@@ -17,6 +18,12 @@ fn modf_result(comptime T: type) type {
pub const modf32_result = modf_result(f32);
pub const modf64_result = modf_result(f64);
+/// Returns the integer and fractional floating-point numbers that sum to x. The sign of each
+/// result is the same as the sign of x.
+///
+/// Special Cases:
+/// - modf(+-inf) = +-inf, nan
+/// - modf(nan) = nan, nan
pub fn modf(x: var) modf_result(@typeOf(x)) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/nan.zig b/std/math/nan.zig
index 1a11a141d5..5a01a5b3bd 100644
--- a/std/math/nan.zig
+++ b/std/math/nan.zig
@@ -1,5 +1,6 @@
const math = @import("../math.zig");
+/// Returns the nan representation for type T.
pub fn nan(comptime T: type) T {
return switch (T) {
f16 => math.nan_f16,
@@ -10,9 +11,10 @@ pub fn nan(comptime T: type) T {
};
}
-// Note: A signalling nan is identical to a standard right now by may have a different bit
-// representation in the future when required.
+/// Returns the signalling nan representation for type T.
pub fn snan(comptime T: type) T {
+ // Note: A signalling nan is identical to a standard right now by may have a different bit
+ // representation in the future when required.
return switch (T) {
f16 => @bitCast(f16, math.nan_u16),
f32 => @bitCast(f32, math.nan_u32),
diff --git a/std/math/pow.zig b/std/math/pow.zig
index 81bb2d95d5..18c9f80634 100644
--- a/std/math/pow.zig
+++ b/std/math/pow.zig
@@ -1,32 +1,36 @@
-// Special Cases:
+// Ported from go, which is licensed under a BSD-3 license.
+// https://golang.org/LICENSE
//
-// pow(x, +-0) = 1 for any x
-// pow(1, y) = 1 for any y
-// pow(x, 1) = x for any x
-// pow(nan, y) = nan
-// pow(x, nan) = nan
-// pow(+-0, y) = +-inf for y an odd integer < 0
-// pow(+-0, -inf) = +inf
-// pow(+-0, +inf) = +0
-// pow(+-0, y) = +inf for finite y < 0 and not an odd integer
-// pow(+-0, y) = +-0 for y an odd integer > 0
-// pow(+-0, y) = +0 for finite y > 0 and not an odd integer
-// pow(-1, +-inf) = 1
-// pow(x, +inf) = +inf for |x| > 1
-// pow(x, -inf) = +0 for |x| > 1
-// pow(x, +inf) = +0 for |x| < 1
-// pow(x, -inf) = +inf for |x| < 1
-// pow(+inf, y) = +inf for y > 0
-// pow(+inf, y) = +0 for y < 0
-// pow(-inf, y) = pow(-0, -y)
-// pow(x, y) = nan for finite x < 0 and finite non-integer y
+// https://golang.org/src/math/pow.go
const builtin = @import("builtin");
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
-// This implementation is taken from the go stlib, musl is a bit more complex.
+/// Returns x raised to the power of y (x^y).
+///
+/// Special Cases:
+/// - pow(x, +-0) = 1 for any x
+/// - pow(1, y) = 1 for any y
+/// - pow(x, 1) = x for any x
+/// - pow(nan, y) = nan
+/// - pow(x, nan) = nan
+/// - pow(+-0, y) = +-inf for y an odd integer < 0
+/// - pow(+-0, -inf) = +inf
+/// - pow(+-0, +inf) = +0
+/// - pow(+-0, y) = +inf for finite y < 0 and not an odd integer
+/// - pow(+-0, y) = +-0 for y an odd integer > 0
+/// - pow(+-0, y) = +0 for finite y > 0 and not an odd integer
+/// - pow(-1, +-inf) = 1
+/// - pow(x, +inf) = +inf for |x| > 1
+/// - pow(x, -inf) = +0 for |x| > 1
+/// - pow(x, +inf) = +0 for |x| < 1
+/// - pow(x, -inf) = +inf for |x| < 1
+/// - pow(+inf, y) = +inf for y > 0
+/// - pow(+inf, y) = +0 for y < 0
+/// - pow(-inf, y) = pow(-0, -y)
+/// - pow(x, y) = nan for finite x < 0 and finite non-integer y
pub fn pow(comptime T: type, x: T, y: T) T {
if (@typeInfo(T) == builtin.TypeId.Int) {
return math.powi(T, x, y) catch unreachable;
@@ -53,15 +57,6 @@ pub fn pow(comptime T: type, x: T, y: T) T {
return x;
}
- // special case sqrt
- if (y == 0.5) {
- return math.sqrt(x);
- }
-
- if (y == -0.5) {
- return 1 / math.sqrt(x);
- }
-
if (x == 0) {
if (y < 0) {
// pow(+-0, y) = +- 0 for y an odd integer
@@ -112,14 +107,16 @@ pub fn pow(comptime T: type, x: T, y: T) T {
}
}
- var ay = y;
- var flip = false;
- if (ay < 0) {
- ay = -ay;
- flip = true;
+ // special case sqrt
+ if (y == 0.5) {
+ return math.sqrt(x);
+ }
+
+ if (y == -0.5) {
+ return 1 / math.sqrt(x);
}
- const r1 = math.modf(ay);
+ const r1 = math.modf(math.fabs(y));
var yi = r1.ipart;
var yf = r1.fpart;
@@ -148,8 +145,18 @@ pub fn pow(comptime T: type, x: T, y: T) T {
var xe = r2.exponent;
var x1 = r2.significand;
- var i = @floatToInt(i32, yi);
+ var i = @floatToInt(@IntType(true, T.bit_count), yi);
while (i != 0) : (i >>= 1) {
+ const overflow_shift = math.floatExponentBits(T) + 1;
+ if (xe < -(1 << overflow_shift) or (1 << overflow_shift) < xe) {
+ // catch xe before it overflows the left shift below
+ // Since i != 0 it has at least one bit still set, so ae will accumulate xe
+ // on at least one more iteration, ae += xe is a lower bound on ae
+ // the lower bound on ae exceeds the size of a float exp
+ // so the final call to Ldexp will produce under/overflow (0/Inf)
+ ae += xe;
+ break;
+ }
if (i & 1 == 1) {
a1 *= x1;
ae += xe;
@@ -163,7 +170,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
}
// a *= a1 * 2^ae
- if (flip) {
+ if (y < 0) {
a1 = 1 / a1;
ae = -ae;
}
@@ -202,6 +209,9 @@ test "math.pow.special" {
expect(pow(f32, 45, 1.0) == 45);
expect(pow(f32, -45, 1.0) == -45);
expect(math.isNan(pow(f32, math.nan(f32), 5.0)));
+ expect(math.isPositiveInf(pow(f32, -math.inf(f32), 0.5)));
+ expect(math.isPositiveInf(pow(f32, -0, -0.5)));
+ expect(pow(f32, -0, 0.5) == 0);
expect(math.isNan(pow(f32, 5.0, math.nan(f32))));
expect(math.isPositiveInf(pow(f32, 0.0, -1.0)));
//expect(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?
@@ -232,3 +242,11 @@ test "math.pow.special" {
expect(math.isNan(pow(f32, -1.0, 1.2)));
expect(math.isNan(pow(f32, -12.4, 78.5)));
}
+
+test "math.pow.overflow" {
+ expect(math.isPositiveInf(pow(f64, 2, 1 << 32)));
+ expect(pow(f64, 2, -(1 << 32)) == 0);
+ expect(math.isNegativeInf(pow(f64, -2, (1 << 32) + 1)));
+ expect(pow(f64, 0.5, 1 << 45) == 0);
+ expect(math.isPositiveInf(pow(f64, 0.5, -(1 << 45))));
+}
diff --git a/std/math/powi.zig b/std/math/powi.zig
index b7212efcbf..d80700e5cd 100644
--- a/std/math/powi.zig
+++ b/std/math/powi.zig
@@ -1,12 +1,7 @@
-// Special Cases:
+// Based on Rust, which is licensed under the MIT license.
+// https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/LICENSE-MIT
//
-// powi(x, +-0) = 1 for any x
-// powi(0, y) = 0 for any y
-// powi(1, y) = 1 for any y
-// powi(-1, y) = -1 for for y an odd integer
-// powi(-1, y) = 1 for for y an even integer
-// powi(x, y) = Overflow for for y >= @sizeOf(x) - 1 y > 0
-// powi(x, y) = Underflow for for y > @sizeOf(x) - 1 y < 0
+// https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/src/libcore/num/mod.rs#L3423
const builtin = @import("builtin");
const std = @import("../std.zig");
@@ -14,7 +9,16 @@ const math = std.math;
const assert = std.debug.assert;
const testing = std.testing;
-// This implementation is based on that from the rust stlib
+/// Returns the power of x raised by the integer y (x^y).
+///
+/// Special Cases:
+/// - powi(x, +-0) = 1 for any x
+/// - powi(0, y) = 0 for any y
+/// - powi(1, y) = 1 for any y
+/// - powi(-1, y) = -1 for y an odd integer
+/// - powi(-1, y) = 1 for y an even integer
+/// - powi(x, y) = Overflow for y >= @sizeOf(x) - 1 or y > 0
+/// - powi(x, y) = Underflow for y > @sizeOf(x) - 1 or y < 0
pub fn powi(comptime T: type, x: T, y: T) (error{
Overflow,
Underflow,
diff --git a/std/math/round.zig b/std/math/round.zig
index 39ff56ca79..0b80a46ce5 100644
--- a/std/math/round.zig
+++ b/std/math/round.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - round(+-0) = +-0
-// - round(+-inf) = +-inf
-// - round(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/roundf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/round.c
const builtin = @import("builtin");
const expect = std.testing.expect;
const std = @import("../std.zig");
const math = std.math;
+/// Returns x rounded to the nearest integer, rounding half away from zero.
+///
+/// Special Cases:
+/// - round(+-0) = +-0
+/// - round(+-inf) = +-inf
+/// - round(nan) = nan
pub fn round(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/scalbn.zig b/std/math/scalbn.zig
index d1338f5acb..d5716d621c 100644
--- a/std/math/scalbn.zig
+++ b/std/math/scalbn.zig
@@ -1,7 +1,14 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/math/scalbnf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/scalbn.c
+
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns x * 2^n.
pub fn scalbn(x: var, n: i32) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/signbit.zig b/std/math/signbit.zig
index 9727152b07..e5c5909292 100644
--- a/std/math/signbit.zig
+++ b/std/math/signbit.zig
@@ -2,6 +2,7 @@ const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns whether x is negative or negative 0.
pub fn signbit(x: var) bool {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/sin.zig b/std/math/sin.zig
index e25b8a292b..f21db4054e 100644
--- a/std/math/sin.zig
+++ b/std/math/sin.zig
@@ -1,19 +1,24 @@
-// Special Cases:
+// Ported from go, which is licensed under a BSD-3 license.
+// https://golang.org/LICENSE
//
-// - sin(+-0) = +-0
-// - sin(+-inf) = nan
-// - sin(nan) = nan
+// https://golang.org/src/math/sin.go
const builtin = @import("builtin");
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the sine of the radian value x.
+///
+/// Special Cases:
+/// - sin(+-0) = +-0
+/// - sin(+-inf) = nan
+/// - sin(nan) = nan
pub fn sin(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
- f32 => sin32(x),
- f64 => sin64(x),
+ f32 => sin_(T, x),
+ f64 => sin_(T, x),
else => @compileError("sin not implemented for " ++ @typeName(T)),
};
}
@@ -34,83 +39,27 @@ const C3 = 2.48015872888517045348E-5;
const C4 = -1.38888888888730564116E-3;
const C5 = 4.16666666666665929218E-2;
-// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
-//
-// This may have slight differences on some edge cases and may need to replaced if so.
-fn sin32(x_: f32) f32 {
- const pi4a = 7.85398125648498535156e-1;
- const pi4b = 3.77489470793079817668E-8;
- const pi4c = 2.69515142907905952645E-15;
- const m4pi = 1.273239544735162542821171882678754627704620361328125;
-
- var x = x_;
- if (x == 0 or math.isNan(x)) {
- return x;
- }
- if (math.isInf(x)) {
- return math.nan(f32);
- }
-
- var sign = false;
- if (x < 0) {
- x = -x;
- sign = true;
- }
-
- var y = math.floor(x * m4pi);
- var j = @floatToInt(i64, y);
-
- if (j & 1 == 1) {
- j += 1;
- y += 1;
- }
+const pi4a = 7.85398125648498535156e-1;
+const pi4b = 3.77489470793079817668E-8;
+const pi4c = 2.69515142907905952645E-15;
+const m4pi = 1.273239544735162542821171882678754627704620361328125;
- j &= 7;
- if (j > 3) {
- j -= 4;
- sign = !sign;
- }
-
- const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
- const w = z * z;
-
- const r = r: {
- if (j == 1 or j == 2) {
- break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
- } else {
- break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
- }
- };
-
- if (sign) {
- return -r;
- } else {
- return r;
- }
-}
-
-fn sin64(x_: f64) f64 {
- const pi4a = 7.85398125648498535156e-1;
- const pi4b = 3.77489470793079817668E-8;
- const pi4c = 2.69515142907905952645E-15;
- const m4pi = 1.273239544735162542821171882678754627704620361328125;
+fn sin_(comptime T: type, x_: T) T {
+ const I = @IntType(true, T.bit_count);
var x = x_;
if (x == 0 or math.isNan(x)) {
return x;
}
if (math.isInf(x)) {
- return math.nan(f64);
+ return math.nan(T);
}
- var sign = false;
- if (x < 0) {
- x = -x;
- sign = true;
- }
+ var sign = x < 0;
+ x = math.fabs(x);
var y = math.floor(x * m4pi);
- var j = @floatToInt(i64, y);
+ var j = @floatToInt(I, y);
if (j & 1 == 1) {
j += 1;
@@ -126,61 +75,56 @@ fn sin64(x_: f64) f64 {
const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
const w = z * z;
- const r = r: {
- if (j == 1 or j == 2) {
- break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
- } else {
- break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
- }
- };
+ const r = if (j == 1 or j == 2)
+ 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))))
+ else
+ z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
- if (sign) {
- return -r;
- } else {
- return r;
- }
+ return if (sign) -r else r;
}
test "math.sin" {
- expect(sin(f32(0.0)) == sin32(0.0));
- expect(sin(f64(0.0)) == sin64(0.0));
+ expect(sin(f32(0.0)) == sin_(f32, 0.0));
+ expect(sin(f64(0.0)) == sin_(f64, 0.0));
expect(comptime (math.sin(f64(2))) == math.sin(f64(2)));
}
test "math.sin32" {
const epsilon = 0.000001;
- expect(math.approxEq(f32, sin32(0.0), 0.0, epsilon));
- expect(math.approxEq(f32, sin32(0.2), 0.198669, epsilon));
- expect(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon));
- expect(math.approxEq(f32, sin32(1.5), 0.997495, epsilon));
- expect(math.approxEq(f32, sin32(37.45), -0.246544, epsilon));
- expect(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 0.2), 0.198669, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 0.8923), 0.778517, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 1.5), 0.997495, epsilon));
+ expect(math.approxEq(f32, sin_(f32, -1.5), -0.997495, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 37.45), -0.246544, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 89.123), 0.916166, epsilon));
}
test "math.sin64" {
const epsilon = 0.000001;
- expect(math.approxEq(f64, sin64(0.0), 0.0, epsilon));
- expect(math.approxEq(f64, sin64(0.2), 0.198669, epsilon));
- expect(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon));
- expect(math.approxEq(f64, sin64(1.5), 0.997495, epsilon));
- expect(math.approxEq(f64, sin64(37.45), -0.246543, epsilon));
- expect(math.approxEq(f64, sin64(89.123), 0.916166, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 0.2), 0.198669, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 0.8923), 0.778517, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 1.5), 0.997495, epsilon));
+ expect(math.approxEq(f64, sin_(f64, -1.5), -0.997495, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 37.45), -0.246543, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 89.123), 0.916166, epsilon));
}
test "math.sin32.special" {
- expect(sin32(0.0) == 0.0);
- expect(sin32(-0.0) == -0.0);
- expect(math.isNan(sin32(math.inf(f32))));
- expect(math.isNan(sin32(-math.inf(f32))));
- expect(math.isNan(sin32(math.nan(f32))));
+ expect(sin_(f32, 0.0) == 0.0);
+ expect(sin_(f32, -0.0) == -0.0);
+ expect(math.isNan(sin_(f32, math.inf(f32))));
+ expect(math.isNan(sin_(f32, -math.inf(f32))));
+ expect(math.isNan(sin_(f32, math.nan(f32))));
}
test "math.sin64.special" {
- expect(sin64(0.0) == 0.0);
- expect(sin64(-0.0) == -0.0);
- expect(math.isNan(sin64(math.inf(f64))));
- expect(math.isNan(sin64(-math.inf(f64))));
- expect(math.isNan(sin64(math.nan(f64))));
+ expect(sin_(f64, 0.0) == 0.0);
+ expect(sin_(f64, -0.0) == -0.0);
+ expect(math.isNan(sin_(f64, math.inf(f64))));
+ expect(math.isNan(sin_(f64, -math.inf(f64))));
+ expect(math.isNan(sin_(f64, math.nan(f64))));
}
diff --git a/std/math/sinh.zig b/std/math/sinh.zig
index cf4363c4a9..73ee65ea6f 100644
--- a/std/math/sinh.zig
+++ b/std/math/sinh.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - sinh(+-0) = +-0
-// - sinh(+-inf) = +-inf
-// - sinh(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/sinhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/sinh.c
const builtin = @import("builtin");
const std = @import("../std.zig");
@@ -11,6 +11,12 @@ const expect = std.testing.expect;
const expo2 = @import("expo2.zig").expo2;
const maxInt = std.math.maxInt;
+/// Returns the hyperbolic sine of x.
+///
+/// Special Cases:
+/// - sinh(+-0) = +-0
+/// - sinh(+-inf) = +-inf
+/// - sinh(nan) = nan
pub fn sinh(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/sqrt.zig b/std/math/sqrt.zig
index 9062f598a1..30af5915d4 100644
--- a/std/math/sqrt.zig
+++ b/std/math/sqrt.zig
@@ -1,10 +1,3 @@
-// Special Cases:
-//
-// - sqrt(+inf) = +inf
-// - sqrt(+-0) = +-0
-// - sqrt(x) = nan if x < 0
-// - sqrt(nan) = nan
-
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
@@ -12,6 +5,13 @@ const builtin = @import("builtin");
const TypeId = builtin.TypeId;
const maxInt = std.math.maxInt;
+/// Returns the square root of x.
+///
+/// Special Cases:
+/// - sqrt(+inf) = +inf
+/// - sqrt(+-0) = +-0
+/// - sqrt(x) = nan if x < 0
+/// - sqrt(nan) = nan
pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) {
const T = @typeOf(x);
switch (@typeId(T)) {
diff --git a/std/math/tan.zig b/std/math/tan.zig
index fc11ebdef7..e8259ee7ad 100644
--- a/std/math/tan.zig
+++ b/std/math/tan.zig
@@ -1,19 +1,24 @@
-// Special Cases:
+// Ported from go, which is licensed under a BSD-3 license.
+// https://golang.org/LICENSE
//
-// - tan(+-0) = +-0
-// - tan(+-inf) = nan
-// - tan(nan) = nan
+// https://golang.org/src/math/tan.go
const builtin = @import("builtin");
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
+/// Returns the tangent of the radian value x.
+///
+/// Special Cases:
+/// - tan(+-0) = +-0
+/// - tan(+-inf) = nan
+/// - tan(nan) = nan
pub fn tan(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
- f32 => tan32(x),
- f64 => tan64(x),
+ f32 => tan_(f32, x),
+ f64 => tan_(f64, x),
else => @compileError("tan not implemented for " ++ @typeName(T)),
};
}
@@ -27,80 +32,27 @@ const Tq2 = -1.32089234440210967447E6;
const Tq3 = 2.50083801823357915839E7;
const Tq4 = -5.38695755929454629881E7;
-// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
-//
-// This may have slight differences on some edge cases and may need to replaced if so.
-fn tan32(x_: f32) f32 {
- const pi4a = 7.85398125648498535156e-1;
- const pi4b = 3.77489470793079817668E-8;
- const pi4c = 2.69515142907905952645E-15;
- const m4pi = 1.273239544735162542821171882678754627704620361328125;
-
- var x = x_;
- if (x == 0 or math.isNan(x)) {
- return x;
- }
- if (math.isInf(x)) {
- return math.nan(f32);
- }
-
- var sign = false;
- if (x < 0) {
- x = -x;
- sign = true;
- }
-
- var y = math.floor(x * m4pi);
- var j = @floatToInt(i64, y);
-
- if (j & 1 == 1) {
- j += 1;
- y += 1;
- }
-
- const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
- const w = z * z;
-
- var r = r: {
- if (w > 1e-14) {
- break :r z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4));
- } else {
- break :r z;
- }
- };
-
- if (j & 2 == 2) {
- r = -1 / r;
- }
- if (sign) {
- r = -r;
- }
-
- return r;
-}
+const pi4a = 7.85398125648498535156e-1;
+const pi4b = 3.77489470793079817668E-8;
+const pi4c = 2.69515142907905952645E-15;
+const m4pi = 1.273239544735162542821171882678754627704620361328125;
-fn tan64(x_: f64) f64 {
- const pi4a = 7.85398125648498535156e-1;
- const pi4b = 3.77489470793079817668E-8;
- const pi4c = 2.69515142907905952645E-15;
- const m4pi = 1.273239544735162542821171882678754627704620361328125;
+fn tan_(comptime T: type, x_: T) T {
+ const I = @IntType(true, T.bit_count);
var x = x_;
if (x == 0 or math.isNan(x)) {
return x;
}
if (math.isInf(x)) {
- return math.nan(f64);
+ return math.nan(T);
}
- var sign = false;
- if (x < 0) {
- x = -x;
- sign = true;
- }
+ var sign = x < 0;
+ x = math.fabs(x);
var y = math.floor(x * m4pi);
- var j = @floatToInt(i64, y);
+ var j = @floatToInt(I, y);
if (j & 1 == 1) {
j += 1;
@@ -110,63 +62,57 @@ fn tan64(x_: f64) f64 {
const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
const w = z * z;
- var r = r: {
- if (w > 1e-14) {
- break :r z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4));
- } else {
- break :r z;
- }
- };
+ var r = if (w > 1e-14)
+ z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4))
+ else
+ z;
if (j & 2 == 2) {
r = -1 / r;
}
- if (sign) {
- r = -r;
- }
- return r;
+ return if (sign) -r else r;
}
test "math.tan" {
- expect(tan(f32(0.0)) == tan32(0.0));
- expect(tan(f64(0.0)) == tan64(0.0));
+ expect(tan(f32(0.0)) == tan_(f32, 0.0));
+ expect(tan(f64(0.0)) == tan_(f64, 0.0));
}
test "math.tan32" {
const epsilon = 0.000001;
- expect(math.approxEq(f32, tan32(0.0), 0.0, epsilon));
- expect(math.approxEq(f32, tan32(0.2), 0.202710, epsilon));
- expect(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon));
- expect(math.approxEq(f32, tan32(1.5), 14.101420, epsilon));
- expect(math.approxEq(f32, tan32(37.45), -0.254397, epsilon));
- expect(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));
+ expect(math.approxEq(f32, tan_(f32, 0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, tan_(f32, 0.2), 0.202710, epsilon));
+ expect(math.approxEq(f32, tan_(f32, 0.8923), 1.240422, epsilon));
+ expect(math.approxEq(f32, tan_(f32, 1.5), 14.101420, epsilon));
+ expect(math.approxEq(f32, tan_(f32, 37.45), -0.254397, epsilon));
+ expect(math.approxEq(f32, tan_(f32, 89.123), 2.285852, epsilon));
}
test "math.tan64" {
const epsilon = 0.000001;
- expect(math.approxEq(f64, tan64(0.0), 0.0, epsilon));
- expect(math.approxEq(f64, tan64(0.2), 0.202710, epsilon));
- expect(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon));
- expect(math.approxEq(f64, tan64(1.5), 14.101420, epsilon));
- expect(math.approxEq(f64, tan64(37.45), -0.254397, epsilon));
- expect(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon));
+ expect(math.approxEq(f64, tan_(f64, 0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, tan_(f64, 0.2), 0.202710, epsilon));
+ expect(math.approxEq(f64, tan_(f64, 0.8923), 1.240422, epsilon));
+ expect(math.approxEq(f64, tan_(f64, 1.5), 14.101420, epsilon));
+ expect(math.approxEq(f64, tan_(f64, 37.45), -0.254397, epsilon));
+ expect(math.approxEq(f64, tan_(f64, 89.123), 2.2858376, epsilon));
}
test "math.tan32.special" {
- expect(tan32(0.0) == 0.0);
- expect(tan32(-0.0) == -0.0);
- expect(math.isNan(tan32(math.inf(f32))));
- expect(math.isNan(tan32(-math.inf(f32))));
- expect(math.isNan(tan32(math.nan(f32))));
+ expect(tan_(f32, 0.0) == 0.0);
+ expect(tan_(f32, -0.0) == -0.0);
+ expect(math.isNan(tan_(f32, math.inf(f32))));
+ expect(math.isNan(tan_(f32, -math.inf(f32))));
+ expect(math.isNan(tan_(f32, math.nan(f32))));
}
test "math.tan64.special" {
- expect(tan64(0.0) == 0.0);
- expect(tan64(-0.0) == -0.0);
- expect(math.isNan(tan64(math.inf(f64))));
- expect(math.isNan(tan64(-math.inf(f64))));
- expect(math.isNan(tan64(math.nan(f64))));
+ expect(tan_(f64, 0.0) == 0.0);
+ expect(tan_(f64, -0.0) == -0.0);
+ expect(math.isNan(tan_(f64, math.inf(f64))));
+ expect(math.isNan(tan_(f64, -math.inf(f64))));
+ expect(math.isNan(tan_(f64, math.nan(f64))));
}
diff --git a/std/math/tanh.zig b/std/math/tanh.zig
index f88ecfdc9c..48d26d091e 100644
--- a/std/math/tanh.zig
+++ b/std/math/tanh.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - sinh(+-0) = +-0
-// - sinh(+-inf) = +-1
-// - sinh(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/tanhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/tanh.c
const builtin = @import("builtin");
const std = @import("../std.zig");
@@ -11,6 +11,12 @@ const expect = std.testing.expect;
const expo2 = @import("expo2.zig").expo2;
const maxInt = std.math.maxInt;
+/// Returns the hyperbolic tangent of x.
+///
+/// Special Cases:
+/// - sinh(+-0) = +-0
+/// - sinh(+-inf) = +-1
+/// - sinh(nan) = nan
pub fn tanh(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/math/trunc.zig b/std/math/trunc.zig
index 9449d0e7eb..219bcd4914 100644
--- a/std/math/trunc.zig
+++ b/std/math/trunc.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
//
-// - trunc(+-0) = +-0
-// - trunc(+-inf) = +-inf
-// - trunc(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/truncf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/trunc.c
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
const maxInt = std.math.maxInt;
+/// Returns the integer value of x.
+///
+/// Special Cases:
+/// - trunc(+-0) = +-0
+/// - trunc(+-inf) = +-inf
+/// - trunc(nan) = nan
pub fn trunc(x: var) @typeOf(x) {
const T = @typeOf(x);
return switch (T) {
diff --git a/std/mem.zig b/std/mem.zig
index 9bf68698c9..2407b56f07 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -34,39 +34,39 @@ pub const Allocator = struct {
/// The returned slice must have its pointer aligned at least to `new_alignment` bytes.
reallocFn: fn (
self: *Allocator,
- // Guaranteed to be the same as what was returned from most recent call to
- // `reallocFn` or `shrinkFn`.
- // If `old_mem.len == 0` then this is a new allocation and `new_byte_count`
- // is guaranteed to be >= 1.
+ /// Guaranteed to be the same as what was returned from most recent call to
+ /// `reallocFn` or `shrinkFn`.
+ /// If `old_mem.len == 0` then this is a new allocation and `new_byte_count`
+ /// is guaranteed to be >= 1.
old_mem: []u8,
- // If `old_mem.len == 0` then this is `undefined`, otherwise:
- // Guaranteed to be the same as what was returned from most recent call to
- // `reallocFn` or `shrinkFn`.
- // Guaranteed to be >= 1.
- // Guaranteed to be a power of 2.
+ /// If `old_mem.len == 0` then this is `undefined`, otherwise:
+ /// Guaranteed to be the same as what was returned from most recent call to
+ /// `reallocFn` or `shrinkFn`.
+ /// Guaranteed to be >= 1.
+ /// Guaranteed to be a power of 2.
old_alignment: u29,
- // If `new_byte_count` is 0 then this is a free and it is guaranteed that
- // `old_mem.len != 0`.
+ /// If `new_byte_count` is 0 then this is a free and it is guaranteed that
+ /// `old_mem.len != 0`.
new_byte_count: usize,
- // Guaranteed to be >= 1.
- // Guaranteed to be a power of 2.
- // Returned slice's pointer must have this alignment.
+ /// Guaranteed to be >= 1.
+ /// Guaranteed to be a power of 2.
+ /// Returned slice's pointer must have this alignment.
new_alignment: u29,
) Error![]u8,
/// This function deallocates memory. It must succeed.
shrinkFn: fn (
self: *Allocator,
- // Guaranteed to be the same as what was returned from most recent call to
- // `reallocFn` or `shrinkFn`.
+ /// Guaranteed to be the same as what was returned from most recent call to
+ /// `reallocFn` or `shrinkFn`.
old_mem: []u8,
- // Guaranteed to be the same as what was returned from most recent call to
- // `reallocFn` or `shrinkFn`.
+ /// Guaranteed to be the same as what was returned from most recent call to
+ /// `reallocFn` or `shrinkFn`.
old_alignment: u29,
- // Guaranteed to be less than or equal to `old_mem.len`.
+ /// Guaranteed to be less than or equal to `old_mem.len`.
new_byte_count: usize,
- // If `new_byte_count == 0` then this is `undefined`, otherwise:
- // Guaranteed to be less than or equal to `old_alignment`.
+ /// If `new_byte_count == 0` then this is `undefined`, otherwise:
+ /// Guaranteed to be less than or equal to `old_alignment`.
new_alignment: u29,
) []u8,
@@ -104,10 +104,7 @@ pub const Allocator = struct {
const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;
const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, alignment);
assert(byte_slice.len == byte_count);
- // This loop gets optimized out in ReleaseFast mode
- for (byte_slice) |*byte| {
- byte.* = undefined;
- }
+ @memset(byte_slice.ptr, undefined, byte_slice.len);
return @bytesToSlice(T, @alignCast(alignment, byte_slice));
}
@@ -153,10 +150,7 @@ pub const Allocator = struct {
const byte_slice = try self.reallocFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment);
assert(byte_slice.len == byte_count);
if (new_n > old_mem.len) {
- // This loop gets optimized out in ReleaseFast mode
- for (byte_slice[old_byte_slice.len..]) |*byte| {
- byte.* = undefined;
- }
+ @memset(byte_slice.ptr + old_byte_slice.len, undefined, byte_slice.len - old_byte_slice.len);
}
return @bytesToSlice(T, @alignCast(new_alignment, byte_slice));
}
diff --git a/std/os.zig b/std/os.zig
index d641cf29c9..fe97c1aa61 100644
--- a/std/os.zig
+++ b/std/os.zig
@@ -23,6 +23,7 @@ test "std.os" {
_ = @import("os/time.zig");
_ = @import("os/windows.zig");
_ = @import("os/uefi.zig");
+ _ = @import("os/wasi.zig");
_ = @import("os/get_app_data_dir.zig");
}
@@ -33,6 +34,7 @@ pub const freebsd = @import("os/freebsd.zig");
pub const netbsd = @import("os/netbsd.zig");
pub const zen = @import("os/zen.zig");
pub const uefi = @import("os/uefi.zig");
+pub const wasi = @import("os/wasi.zig");
pub const posix = switch (builtin.os) {
Os.linux => linux,
@@ -40,6 +42,7 @@ pub const posix = switch (builtin.os) {
Os.freebsd => freebsd,
Os.netbsd => netbsd,
Os.zen => zen,
+ Os.wasi => wasi,
else => @compileError("Unsupported OS"),
};
@@ -50,7 +53,11 @@ pub const path = @import("os/path.zig");
pub const File = @import("os/file.zig").File;
pub const time = @import("os/time.zig");
-pub const page_size = 4 * 1024;
+pub const page_size = switch (builtin.arch) {
+ .wasm32, .wasm64 => 64 * 1024,
+ else => 4 * 1024,
+};
+
pub const MAX_PATH_BYTES = switch (builtin.os) {
Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => posix.PATH_MAX,
// Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
@@ -139,6 +146,12 @@ pub fn getRandomBytes(buf: []u8) !void {
};
}
},
+ Os.wasi => {
+ const random_get_result = os.wasi.random_get(buf.ptr, buf.len);
+ if (random_get_result != os.wasi.ESUCCESS) {
+ return error.Unknown;
+ }
+ },
Os.zen => {
const randomness = []u8{ 42, 1, 7, 12, 22, 17, 99, 16, 26, 87, 41, 45 };
var i: usize = 0;
@@ -198,6 +211,12 @@ pub fn abort() noreturn {
}
windows.ExitProcess(3);
},
+ Os.wasi => {
+ _ = wasi.proc_raise(wasi.SIGABRT);
+ // TODO: Is SIGKILL even necessary?
+ _ = wasi.proc_raise(wasi.SIGKILL);
+ while (true) {}
+ },
Os.uefi => {
// TODO there's gotta be a better thing to do here than loop forever
while (true) {}
@@ -226,6 +245,9 @@ pub fn exit(status: u8) noreturn {
Os.windows => {
windows.ExitProcess(status);
},
+ Os.wasi => {
+ wasi.proc_exit(status);
+ },
else => @compileError("Unsupported OS"),
}
}
@@ -749,6 +771,37 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
try result.setMove(key, value);
}
+ } else if (builtin.os == Os.wasi) {
+ var environ_count: usize = undefined;
+ var environ_buf_size: usize = undefined;
+
+ const environ_sizes_get_ret = std.os.wasi.environ_sizes_get(&environ_count, &environ_buf_size);
+ if (environ_sizes_get_ret != os.wasi.ESUCCESS) {
+ return unexpectedErrorPosix(environ_sizes_get_ret);
+ }
+
+ // TODO: Verify that the documentation is incorrect
+ // https://github.com/WebAssembly/WASI/issues/27
+ var environ = try allocator.alloc(?[*]u8, environ_count + 1);
+ defer allocator.free(environ);
+ var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size);
+ defer allocator.free(environ_buf);
+
+ const environ_get_ret = std.os.wasi.environ_get(environ.ptr, environ_buf.ptr);
+ if (environ_get_ret != os.wasi.ESUCCESS) {
+ return unexpectedErrorPosix(environ_get_ret);
+ }
+
+ for (environ) |env| {
+ if (env) |ptr| {
+ const pair = mem.toSlice(u8, ptr);
+ var parts = mem.separate(pair, "=");
+ const key = parts.next().?;
+ const value = parts.next().?;
+ try result.set(key, value);
+ }
+ }
+ return result;
} else {
for (posix_environ_raw) |ptr| {
var line_i: usize = 0;
@@ -1083,13 +1136,14 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
defer in_file.close();
const mode = try in_file.mode();
+ const in_stream = &in_file.inStream().stream;
var atomic_file = try AtomicFile.init(dest_path, mode);
defer atomic_file.deinit();
var buf: [page_size]u8 = undefined;
while (true) {
- const amt = try in_file.readFull(buf[0..]);
+ const amt = try in_stream.readFull(buf[0..]);
try atomic_file.file.write(buf[0..amt]);
if (amt != buf.len) {
return atomic_file.finish();
@@ -2127,6 +2181,11 @@ pub const ArgIterator = struct {
inner: InnerType,
pub fn init() ArgIterator {
+ if (builtin.os == Os.wasi) {
+ // TODO: Figure out a compatible interface accomodating WASI
+ @compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead.");
+ }
+
return ArgIterator{ .inner = InnerType.init() };
}
@@ -2159,6 +2218,34 @@ pub fn args() ArgIterator {
/// Caller must call argsFree on result.
pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
+ if (builtin.os == Os.wasi) {
+ var count: usize = undefined;
+ var buf_size: usize = undefined;
+
+ const args_sizes_get_ret = os.wasi.args_sizes_get(&count, &buf_size);
+ if (args_sizes_get_ret != os.wasi.ESUCCESS) {
+ return unexpectedErrorPosix(args_sizes_get_ret);
+ }
+
+ var argv = try allocator.alloc([*]u8, count);
+ defer allocator.free(argv);
+
+ var argv_buf = try allocator.alloc(u8, buf_size);
+ const args_get_ret = os.wasi.args_get(argv.ptr, argv_buf.ptr);
+ if (args_get_ret != os.wasi.ESUCCESS) {
+ return unexpectedErrorPosix(args_get_ret);
+ }
+
+ var result_slice = try allocator.alloc([]u8, count);
+
+ var i: usize = 0;
+ while (i < count) : (i += 1) {
+ result_slice[i] = mem.toSlice(u8, argv[i]);
+ }
+
+ return result_slice;
+ }
+
// TODO refactor to only make 1 allocation.
var it = args();
var contents = try Buffer.initSize(allocator, 0);
@@ -2196,6 +2283,16 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
}
pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
+ if (builtin.os == Os.wasi) {
+ const last_item = args_alloc[args_alloc.len - 1];
+ const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated
+ const first_item_ptr = args_alloc[0].ptr;
+ const len = last_byte_addr - @ptrToInt(first_item_ptr);
+ allocator.free(first_item_ptr[0..len]);
+
+ return allocator.free(args_alloc);
+ }
+
var total_bytes: usize = 0;
for (args_alloc) |arg| {
total_bytes += @sizeOf([]u8) + arg.len;
@@ -3030,9 +3127,6 @@ pub const SpawnThreadError = error{
Unexpected,
};
-pub var linux_tls_phdr: ?*std.elf.Phdr = null;
-pub var linux_tls_img_src: [*]const u8 = undefined; // defined if linux_tls_phdr is
-
/// caller must call wait on the returned thread
/// fn startFn(@typeOf(context)) T
/// where T is u8, noreturn, void, or !void
@@ -3142,12 +3236,10 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
}
// Finally, the Thread Local Storage, if any.
if (!Thread.use_pthreads) {
- if (linux_tls_phdr) |tls_phdr| {
- l = mem.alignForward(l, tls_phdr.p_align);
+ if (linux.tls.tls_image) |tls_img| {
+ l = mem.alignForward(l, @alignOf(usize));
tls_start_offset = l;
- l += tls_phdr.p_memsz;
- // the fs register address
- l += @sizeOf(usize);
+ l += tls_img.alloc_size;
}
}
break :blk l;
@@ -3188,10 +3280,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID |
posix.CLONE_DETACHED;
var newtls: usize = undefined;
- if (linux_tls_phdr) |tls_phdr| {
- @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz);
- newtls = mmap_addr + mmap_len - @sizeOf(usize);
- @intToPtr(*usize, newtls).* = newtls;
+ if (linux.tls.tls_image) |tls_img| {
+ newtls = linux.tls.copyTLS(mmap_addr + tls_start_offset);
flags |= posix.CLONE_SETTLS;
}
const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
diff --git a/std/os/darwin.zig b/std/os/darwin.zig
index 9dc1ce1173..04122100f4 100644
--- a/std/os/darwin.zig
+++ b/std/os/darwin.zig
@@ -812,7 +812,7 @@ pub fn sigaction(sig: u5, noalias act: *const Sigaction, noalias oact: ?*Sigacti
.sa_mask = act.mask,
};
var coact: c.Sigaction = undefined;
- const result = errnoWrap(c.sigaction(sig, *cact, *coact));
+ const result = errnoWrap(c.sigaction(sig, &cact, &coact));
if (result != 0) {
return result;
}
diff --git a/std/os/file.zig b/std/os/file.zig
index c9a0e2b696..814e5e318c 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -235,7 +235,7 @@ pub const File = struct {
Unexpected,
};
- pub fn seekForward(self: File, amount: isize) SeekError!void {
+ pub fn seekForward(self: File, amount: i64) SeekError!void {
switch (builtin.os) {
Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);
@@ -266,7 +266,7 @@ pub const File = struct {
}
}
- pub fn seekTo(self: File, pos: usize) SeekError!void {
+ pub fn seekTo(self: File, pos: u64) SeekError!void {
switch (builtin.os) {
Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
const ipos = try math.cast(isize, pos);
@@ -301,13 +301,12 @@ pub const File = struct {
}
pub const GetSeekPosError = error{
- Overflow,
SystemResources,
Unseekable,
Unexpected,
};
- pub fn getPos(self: File) GetSeekPosError!usize {
+ pub fn getPos(self: File) GetSeekPosError!u64 {
switch (builtin.os) {
Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);
@@ -324,7 +323,7 @@ pub const File = struct {
else => os.unexpectedErrorPosix(err),
};
}
- return result;
+ return u64(result);
},
Os.windows => {
var pos: windows.LARGE_INTEGER = undefined;
@@ -336,17 +335,16 @@ pub const File = struct {
};
}
- assert(pos >= 0);
- return math.cast(usize, pos);
+ return @intCast(u64, pos);
},
else => @compileError("unsupported OS"),
}
}
- pub fn getEndPos(self: File) GetSeekPosError!usize {
+ pub fn getEndPos(self: File) GetSeekPosError!u64 {
if (is_posix) {
const stat = try os.posixFStat(self.handle);
- return @intCast(usize, stat.size);
+ return @intCast(u64, stat.size);
} else if (is_windows) {
var file_size: windows.LARGE_INTEGER = undefined;
if (windows.GetFileSizeEx(self.handle, &file_size) == 0) {
@@ -355,9 +353,7 @@ pub const File = struct {
else => os.unexpectedErrorWindows(err),
};
}
- if (file_size < 0)
- return error.Overflow;
- return math.cast(usize, @intCast(u64, file_size));
+ return @intCast(u64, file_size);
} else {
@compileError("TODO support getEndPos on this OS");
}
@@ -492,22 +488,22 @@ pub const File = struct {
pub const Stream = io.SeekableStream(SeekError, GetSeekPosError);
- pub fn seekToFn(seekable_stream: *Stream, pos: usize) SeekError!void {
+ pub fn seekToFn(seekable_stream: *Stream, pos: u64) SeekError!void {
const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
return self.file.seekTo(pos);
}
- pub fn seekForwardFn(seekable_stream: *Stream, amt: isize) SeekError!void {
+ pub fn seekForwardFn(seekable_stream: *Stream, amt: i64) SeekError!void {
const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
return self.file.seekForward(amt);
}
- pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!usize {
+ pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!u64 {
const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
return self.file.getEndPos();
}
- pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!usize {
+ pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!u64 {
const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
return self.file.getPos();
}
diff --git a/std/os/linux.zig b/std/os/linux.zig
index e7f822185b..1e121b81c8 100644
--- a/std/os/linux.zig
+++ b/std/os/linux.zig
@@ -2,7 +2,10 @@ const std = @import("../std.zig");
const assert = std.debug.assert;
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
+const elf = std.elf;
+pub const tls = @import("linux/tls.zig");
const vdso = @import("linux/vdso.zig");
+const dl = @import("../dynamic_library.zig");
pub use switch (builtin.arch) {
builtin.Arch.x86_64 => @import("linux/x86_64.zig"),
builtin.Arch.i386 => @import("linux/i386.zig"),
@@ -12,6 +15,7 @@ pub use switch (builtin.arch) {
pub use @import("linux/errno.zig");
pub const PATH_MAX = 4096;
+pub const IOV_MAX = 1024;
pub const STDIN_FILENO = 0;
pub const STDOUT_FILENO = 1;
@@ -955,10 +959,13 @@ pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
}
+var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
+
pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
if (VDSO_CGT_SYM.len != 0) {
- const f = @atomicLoad(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, builtin.AtomicOrder.Unordered);
- if (@ptrToInt(f) != 0) {
+ const ptr = @atomicLoad(?*const c_void, &vdso_clock_gettime, .Unordered);
+ if (ptr) |fn_ptr| {
+ const f = @ptrCast(@typeOf(clock_gettime), fn_ptr);
const rc = f(clk_id, tp);
switch (rc) {
0, @bitCast(usize, isize(-EINVAL)) => return rc,
@@ -968,13 +975,18 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
}
return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
}
-var vdso_clock_gettime = init_vdso_clock_gettime;
+
extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize {
- const addr = vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM);
- var f = @intToPtr(@typeOf(init_vdso_clock_gettime), addr);
- _ = @cmpxchgStrong(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, init_vdso_clock_gettime, f, builtin.AtomicOrder.Monotonic, builtin.AtomicOrder.Monotonic);
- if (@ptrToInt(f) == 0) return @bitCast(usize, isize(-ENOSYS));
- return f(clk, ts);
+ const ptr = @intToPtr(?*const c_void, vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM));
+ // Note that we may not have a VDSO at all, update the stub address anyway
+ // so that clock_gettime will fall back on the good old (and slow) syscall
+ _ = @cmpxchgStrong(?*const c_void, &vdso_clock_gettime, &init_vdso_clock_gettime, ptr, .Monotonic, .Monotonic);
+ // Call into the VDSO if available
+ if (ptr) |fn_ptr| {
+ const f = @ptrCast(@typeOf(clock_gettime), fn_ptr);
+ return f(clk, ts);
+ }
+ return @bitCast(usize, isize(-ENOSYS));
}
pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
@@ -1100,8 +1112,8 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
const NSIG = 65;
const sigset_t = [128 / @sizeOf(usize)]usize;
-const all_mask = []usize{maxInt(usize)};
-const app_mask = []usize{0xfffffffc7fffffff};
+const all_mask = []u32{ 0xffffffff, 0xffffffff };
+const app_mask = []u32{ 0xfffffffc, 0x7fffffff };
const k_sigaction = extern struct {
handler: extern fn (i32) void,
@@ -1193,6 +1205,16 @@ pub const iovec_const = extern struct {
iov_len: usize,
};
+pub const mmsghdr = extern struct {
+ msg_hdr: msghdr,
+ msg_len: u32,
+};
+
+pub const mmsghdr_const = extern struct {
+ msg_hdr: msghdr_const,
+ msg_len: u32,
+};
+
pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
}
@@ -1213,10 +1235,50 @@ pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noal
return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
}
-pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize {
+pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize {
return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
}
+pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize {
+ if (@typeInfo(usize).Int.bits > @typeInfo(@typeOf(mmsghdr(undefined).msg_len)).Int.bits) {
+ // workaround kernel brokenness:
+ // if adding up all iov_len overflows a i32 then split into multiple calls
+ // see https://www.openwall.com/lists/musl/2014/06/07/5
+ const kvlen = if (vlen > IOV_MAX) IOV_MAX else vlen; // matches kernel
+ var next_unsent: usize = 0;
+ for (msgvec[0..kvlen]) |*msg, i| {
+ var size: i32 = 0;
+ const msg_iovlen = @intCast(usize, msg.msg_hdr.msg_iovlen); // kernel side this is treated as unsigned
+ for (msg.msg_hdr.msg_iov[0..msg_iovlen]) |iov, j| {
+ if (iov.iov_len > std.math.maxInt(i32) or @addWithOverflow(i32, size, @intCast(i32, iov.iov_len), &size)) {
+ // batch-send all messages up to the current message
+ if (next_unsent < i) {
+ const batch_size = i - next_unsent;
+ const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
+ if (getErrno(r) != 0) return next_unsent;
+ if (r < batch_size) return next_unsent + r;
+ }
+ // send current message as own packet
+ const r = sendmsg(fd, &msg.msg_hdr, flags);
+ if (getErrno(r) != 0) return r;
+ // Linux limits the total bytes sent by sendmsg to INT_MAX, so this cast is safe.
+ msg.msg_len = @intCast(u32, r);
+ next_unsent = i + 1;
+ break;
+ }
+ }
+ }
+ if (next_unsent < kvlen or next_unsent == 0) { // want to make sure at least one syscall occurs (e.g. to trigger MSG_EOR)
+ const batch_size = kvlen - next_unsent;
+ const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
+ if (getErrno(r) != 0) return r;
+ return next_unsent + r;
+ }
+ return kvlen;
+ }
+ return syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(msgvec), vlen, flags);
+}
+
pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);
}
@@ -1339,17 +1401,25 @@ pub fn sched_getaffinity(pid: i32, set: []usize) usize {
return syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), set.len * @sizeOf(usize), @ptrToInt(set.ptr));
}
-pub const epoll_data = packed union {
+pub const epoll_data = extern union {
ptr: usize,
fd: i32,
@"u32": u32,
@"u64": u64,
};
-pub const epoll_event = packed struct {
- events: u32,
- data: epoll_data,
-};
+// On x86_64 the structure is packed so that it matches the definition of its
+// 32bit counterpart
+pub const epoll_event = if (builtin.arch != .x86_64)
+ extern struct {
+ events: u32,
+ data: epoll_data,
+ }
+else
+ packed struct {
+ events: u32,
+ data: epoll_data,
+ };
pub fn epoll_create() usize {
return epoll_create1(0);
@@ -1534,6 +1604,70 @@ pub const dirent64 = extern struct {
d_name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173
};
+pub const dl_phdr_info = extern struct {
+ dlpi_addr: usize,
+ dlpi_name: ?[*]const u8,
+ dlpi_phdr: [*]elf.Phdr,
+ dlpi_phnum: u16,
+};
+
+// XXX: This should be weak
+extern const __ehdr_start: elf.Ehdr = undefined;
+
+pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
+ if (builtin.link_libc) {
+ return std.c.dl_iterate_phdr(@ptrCast(std.c.dl_iterate_phdr_callback, callback), @ptrCast(?*c_void, data));
+ }
+
+ const elf_base = @ptrToInt(&__ehdr_start);
+ const n_phdr = __ehdr_start.e_phnum;
+ const phdrs = (@intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff))[0..n_phdr];
+
+ var it = dl.linkmap_iterator(phdrs) catch return 0;
+
+ // The executable has no dynamic link segment, create a single entry for
+ // the whole ELF image
+ if (it.end()) {
+ var info = dl_phdr_info{
+ .dlpi_addr = elf_base,
+ .dlpi_name = c"/proc/self/exe",
+ .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
+ .dlpi_phnum = __ehdr_start.e_phnum,
+ };
+
+ return callback(&info, @sizeOf(dl_phdr_info), data);
+ }
+
+ // Last return value from the callback function
+ var last_r: isize = 0;
+ while (it.next()) |entry| {
+ var dlpi_phdr: usize = undefined;
+ var dlpi_phnum: u16 = undefined;
+
+ if (entry.l_addr != 0) {
+ const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
+ dlpi_phdr = entry.l_addr + elf_header.e_phoff;
+ dlpi_phnum = elf_header.e_phnum;
+ } else {
+ // This is the running ELF image
+ dlpi_phdr = elf_base + __ehdr_start.e_phoff;
+ dlpi_phnum = __ehdr_start.e_phnum;
+ }
+
+ var info = dl_phdr_info{
+ .dlpi_addr = entry.l_addr,
+ .dlpi_name = entry.l_name,
+ .dlpi_phdr = @intToPtr([*]elf.Phdr, dlpi_phdr),
+ .dlpi_phnum = dlpi_phnum,
+ };
+
+ last_r = callback(&info, @sizeOf(dl_phdr_info), data);
+ if (last_r != 0) break;
+ }
+
+ return last_r;
+}
+
test "import" {
if (builtin.os == builtin.Os.linux) {
_ = @import("linux/test.zig");
diff --git a/std/os/linux/arm64.zig b/std/os/linux/arm64.zig
index ac2c18ee5f..4ae55765fb 100644
--- a/std/os/linux/arm64.zig
+++ b/std/os/linux/arm64.zig
@@ -2,6 +2,7 @@ const std = @import("../../std.zig");
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
const iovec = linux.iovec;
+const iovec_const = linux.iovec_const;
pub const SYS_io_setup = 0;
pub const SYS_io_destroy = 1;
@@ -415,12 +416,24 @@ pub fn syscall6(
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub const msghdr = extern struct {
- msg_name: *u8,
+ msg_name: ?*sockaddr,
msg_namelen: socklen_t,
- msg_iov: *iovec,
+ msg_iov: [*]iovec,
msg_iovlen: i32,
__pad1: i32,
- msg_control: *u8,
+ msg_control: ?*c_void,
+ msg_controllen: socklen_t,
+ __pad2: socklen_t,
+ msg_flags: i32,
+};
+
+pub const msghdr_const = extern struct {
+ msg_name: ?*const sockaddr,
+ msg_namelen: socklen_t,
+ msg_iov: [*]iovec_const,
+ msg_iovlen: i32,
+ __pad1: i32,
+ msg_control: ?*c_void,
msg_controllen: socklen_t,
__pad2: socklen_t,
msg_flags: i32,
diff --git a/std/os/linux/test.zig b/std/os/linux/test.zig
index 286748b70c..1949d00298 100644
--- a/std/os/linux/test.zig
+++ b/std/os/linux/test.zig
@@ -1,6 +1,8 @@
const std = @import("../../std.zig");
const builtin = @import("builtin");
const linux = std.os.linux;
+const mem = std.mem;
+const elf = std.elf;
const expect = std.testing.expect;
test "getpid" {
@@ -42,3 +44,42 @@ test "timer" {
// TODO implicit cast from *[N]T to [*]T
err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
}
+
+export fn iter_fn(info: *linux.dl_phdr_info, size: usize, data: ?*usize) i32 {
+ var counter = data.?;
+ // Count how many libraries are loaded
+ counter.* += usize(1);
+
+ // The image should contain at least a PT_LOAD segment
+ if (info.dlpi_phnum < 1) return -1;
+
+ // Quick & dirty validation of the phdr pointers, make sure we're not
+ // pointing to some random gibberish
+ var i: usize = 0;
+ var found_load = false;
+ while (i < info.dlpi_phnum) : (i += 1) {
+ const phdr = info.dlpi_phdr[i];
+
+ if (phdr.p_type != elf.PT_LOAD) continue;
+
+ // Find the ELF header
+ const elf_header = @intToPtr(*elf.Ehdr, phdr.p_vaddr - phdr.p_offset);
+ // Validate the magic
+ if (!mem.eql(u8, elf_header.e_ident[0..], "\x7fELF")) return -1;
+ // Consistency check
+ if (elf_header.e_phnum != info.dlpi_phnum) return -1;
+
+ found_load = true;
+ break;
+ }
+
+ if (!found_load) return -1;
+
+ return 42;
+}
+
+test "dl_iterate_phdr" {
+ var counter: usize = 0;
+ expect(linux.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
+ expect(counter != 0);
+}
diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig
new file mode 100644
index 0000000000..9c8d816f05
--- /dev/null
+++ b/std/os/linux/tls.zig
@@ -0,0 +1,247 @@
+const std = @import("std");
+const mem = std.mem;
+const posix = std.os.posix;
+const elf = std.elf;
+const builtin = @import("builtin");
+const assert = std.debug.assert;
+
+// This file implements the two TLS variants [1] used by ELF-based systems.
+//
+// The variant I has the following layout in memory:
+// -------------------------------------------------------
+// | DTV | Zig | DTV | Alignment | TLS |
+// | storage | thread data | pointer | | block |
+// ------------------------^------------------------------
+// `-- The thread pointer register points here
+//
+// In this case we allocate additional space for our control structure that's
+// placed _before_ the DTV pointer together with the DTV.
+//
+// NOTE: Some systems such as power64 or mips use this variant with a twist: the
+// alignment is not present and the tp and DTV addresses are offset by a
+// constant.
+//
+// On the other hand the variant II has the following layout in memory:
+// ---------------------------------------
+// | TLS | TCB | Zig | DTV |
+// | block | | thread data | storage |
+// --------^------------------------------
+// `-- The thread pointer register points here
+//
+// The structure of the TCB is not defined by the ABI so we reserve enough space
+// for a single pointer as some architectures such as i386 and x86_64 need a
+// pointer to the TCB block itself at the address pointed by the tp.
+//
+// In this case the control structure and DTV are placed one after another right
+// after the TLS block data.
+//
+// At the moment the DTV is very simple since we only support static TLS, all we
+// need is a two word vector to hold the number of entries (1) and the address
+// of the first TLS block.
+//
+// [1] https://www.akkadia.org/drepper/tls.pdf
+
+const TLSVariant = enum {
+ VariantI,
+ VariantII,
+};
+
+const tls_variant = switch (builtin.arch) {
+ .arm, .armeb, .aarch64, .aarch64_be => TLSVariant.VariantI,
+ .x86_64, .i386 => TLSVariant.VariantII,
+ else => @compileError("undefined tls_variant for this architecture"),
+};
+
+// Controls how many bytes are reserved for the Thread Control Block
+const tls_tcb_size = switch (builtin.arch) {
+ // ARM EABI mandates enough space for two pointers: the first one points to
+ // the DTV while the second one is unspecified but reserved
+ .arm, .armeb, .aarch64, .aarch64_be => 2 * @sizeOf(usize),
+ .i386, .x86_64 => @sizeOf(usize),
+ else => 0,
+};
+
+// Controls if the TCB should be aligned according to the TLS segment p_align
+const tls_tcb_align_size = switch (builtin.arch) {
+ .arm, .armeb, .aarch64, .aarch64_be => true,
+ else => false,
+};
+
+// Check if the architecture-specific parameters look correct
+comptime {
+ if (tls_tcb_align_size and tls_variant != TLSVariant.VariantI) {
+ @compileError("tls_tcb_align_size is only meaningful for variant I TLS");
+ }
+}
+
+// Some architectures add some offset to the tp and dtv addresses in order to
+// make the generated code more efficient
+
+const tls_tp_offset = switch (builtin.arch) {
+ else => 0,
+};
+
+const tls_dtv_offset = switch (builtin.arch) {
+ else => 0,
+};
+
+// Per-thread storage for Zig's use
+const CustomData = packed struct {
+};
+
+// Dynamic Thread Vector
+const DTV = packed struct {
+ entries: usize,
+ tls_block: [1]usize,
+};
+
+// Holds all the information about the process TLS image
+const TLSImage = struct {
+ data_src: []u8,
+ alloc_size: usize,
+ tcb_offset: usize,
+ dtv_offset: usize,
+ data_offset: usize,
+};
+
+pub var tls_image: ?TLSImage = null;
+
+pub fn setThreadPointer(addr: usize) void {
+ switch (builtin.arch) {
+ .x86_64 => {
+ const rc = std.os.linux.syscall2(std.os.linux.SYS_arch_prctl,
+ std.os.linux.ARCH_SET_FS, addr);
+ assert(rc == 0);
+ },
+ .aarch64 => {
+ asm volatile (
+ \\ msr tpidr_el0, %[addr]
+ : : [addr] "r" (addr)
+ );
+ },
+ else => @compileError("Unsupported architecture"),
+ }
+}
+
+pub fn initTLS() void {
+ var tls_phdr: ?*elf.Phdr = null;
+ var img_base: usize = 0;
+
+ const auxv = std.os.linux_elf_aux_maybe.?;
+ var at_phent: usize = undefined;
+ var at_phnum: usize = undefined;
+ var at_phdr: usize = undefined;
+
+ var i: usize = 0;
+ while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
+ switch (auxv[i].a_type) {
+ elf.AT_PHENT => at_phent = auxv[i].a_un.a_val,
+ elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
+ elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
+ else => continue,
+ }
+ }
+
+ // Sanity check
+ assert(at_phent == @sizeOf(elf.Phdr));
+
+ // Search the TLS section
+ const phdrs = (@intToPtr([*]elf.Phdr, at_phdr))[0..at_phnum];
+
+ for (phdrs) |*phdr| {
+ switch (phdr.p_type) {
+ elf.PT_PHDR => img_base = at_phdr - phdr.p_vaddr,
+ elf.PT_TLS => tls_phdr = phdr,
+ else => continue,
+ }
+ }
+
+ if (tls_phdr) |phdr| {
+ // Offsets into the allocated TLS area
+ var tcb_offset: usize = undefined;
+ var dtv_offset: usize = undefined;
+ var data_offset: usize = undefined;
+ var thread_data_offset: usize = undefined;
+ // Compute the total size of the ABI-specific data plus our own control
+ // structures
+ const alloc_size = switch (tls_variant) {
+ .VariantI => blk: {
+ var l: usize = 0;
+ dtv_offset = l;
+ l += @sizeOf(DTV);
+ thread_data_offset = l;
+ l += @sizeOf(CustomData);
+ l = mem.alignForward(l, phdr.p_align);
+ tcb_offset = l;
+ if (tls_tcb_align_size) {
+ l += mem.alignForward(tls_tcb_size, phdr.p_align);
+ } else {
+ l += tls_tcb_size;
+ }
+ data_offset = l;
+ l += phdr.p_memsz;
+ break :blk l;
+ },
+ .VariantII => blk: {
+ var l: usize = 0;
+ data_offset = l;
+ l += phdr.p_memsz;
+ l = mem.alignForward(l, phdr.p_align);
+ tcb_offset = l;
+ l += tls_tcb_size;
+ thread_data_offset = l;
+ l += @sizeOf(CustomData);
+ dtv_offset = l;
+ l += @sizeOf(DTV);
+ break :blk l;
+ }
+ };
+
+ tls_image = TLSImage{
+ .data_src = @intToPtr([*]u8, phdr.p_vaddr + img_base)[0..phdr.p_filesz],
+ .alloc_size = alloc_size,
+ .tcb_offset = tcb_offset,
+ .dtv_offset = dtv_offset,
+ .data_offset = data_offset,
+ };
+ }
+}
+
+pub fn copyTLS(addr: usize) usize {
+ const tls_img = tls_image.?;
+
+ // Be paranoid, clear the area we're going to use
+ @memset(@intToPtr([*]u8, addr), 0, tls_img.alloc_size);
+ // Prepare the DTV
+ const dtv = @intToPtr(*DTV, addr + tls_img.dtv_offset);
+ dtv.entries = 1;
+ dtv.tls_block[0] = addr + tls_img.data_offset + tls_dtv_offset;
+ // Set-up the TCB
+ const tcb_ptr = @intToPtr(*usize, addr + tls_img.tcb_offset);
+ if (tls_variant == TLSVariant.VariantI) {
+ tcb_ptr.* = addr + tls_img.dtv_offset;
+ } else {
+ tcb_ptr.* = addr + tls_img.tcb_offset;
+ }
+ // Copy the data
+ @memcpy(@intToPtr([*]u8, addr + tls_img.data_offset), tls_img.data_src.ptr, tls_img.data_src.len);
+
+ // Return the corrected (if needed) value for the tp register
+ return addr + tls_img.tcb_offset + tls_tp_offset;
+}
+
+var main_thread_tls_buffer: [256]u8 align(32) = undefined;
+
+pub fn allocateTLS(size: usize) usize {
+ // Small TLS allocation, use our local buffer
+ if (size < main_thread_tls_buffer.len) {
+ return @ptrToInt(&main_thread_tls_buffer);
+ }
+
+ const addr = posix.mmap(null, size, posix.PROT_READ | posix.PROT_WRITE,
+ posix.MAP_PRIVATE | posix.MAP_ANONYMOUS, -1, 0);
+
+ if (posix.getErrno(addr) != 0) @panic("out of memory");
+
+ return addr;
+}
diff --git a/std/os/linux/x86_64.zig b/std/os/linux/x86_64.zig
index d194cd4003..621783d572 100644
--- a/std/os/linux/x86_64.zig
+++ b/std/os/linux/x86_64.zig
@@ -1,7 +1,9 @@
const std = @import("../../std.zig");
const linux = std.os.linux;
+const sockaddr = linux.sockaddr;
const socklen_t = linux.socklen_t;
const iovec = linux.iovec;
+const iovec_const = linux.iovec_const;
pub const SYS_read = 0;
pub const SYS_write = 1;
@@ -386,6 +388,11 @@ pub const VDSO_CGT_VER = "LINUX_2.6";
pub const VDSO_GETCPU_SYM = "__vdso_getcpu";
pub const VDSO_GETCPU_VER = "LINUX_2.6";
+pub const ARCH_SET_GS = 0x1001;
+pub const ARCH_SET_FS = 0x1002;
+pub const ARCH_GET_FS = 0x1003;
+pub const ARCH_GET_GS = 0x1004;
+
pub fn syscall0(number: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
@@ -483,12 +490,24 @@ pub nakedcc fn restore_rt() void {
}
pub const msghdr = extern struct {
- msg_name: *u8,
+ msg_name: ?*sockaddr,
+ msg_namelen: socklen_t,
+ msg_iov: [*]iovec,
+ msg_iovlen: i32,
+ __pad1: i32,
+ msg_control: ?*c_void,
+ msg_controllen: socklen_t,
+ __pad2: socklen_t,
+ msg_flags: i32,
+};
+
+pub const msghdr_const = extern struct {
+ msg_name: ?*const sockaddr,
msg_namelen: socklen_t,
- msg_iov: *iovec,
+ msg_iov: [*]iovec_const,
msg_iovlen: i32,
__pad1: i32,
- msg_control: *u8,
+ msg_control: ?*c_void,
msg_controllen: socklen_t,
__pad2: socklen_t,
msg_flags: i32,
diff --git a/std/os/time.zig b/std/os/time.zig
index 66ceedb1b6..abb6412843 100644
--- a/std/os/time.zig
+++ b/std/os/time.zig
@@ -3,41 +3,44 @@ const builtin = @import("builtin");
const Os = builtin.Os;
const debug = std.debug;
const testing = std.testing;
+const math = std.math;
const windows = std.os.windows;
const linux = std.os.linux;
const darwin = std.os.darwin;
+const wasi = std.os.wasi;
const posix = std.os.posix;
pub const epoch = @import("epoch.zig");
-/// Sleep for the specified duration
+/// Spurious wakeups are possible and no precision of timing is guaranteed.
pub fn sleep(nanoseconds: u64) void {
switch (builtin.os) {
Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
const s = nanoseconds / ns_per_s;
const ns = nanoseconds % ns_per_s;
- posixSleep(@intCast(u63, s), @intCast(u63, ns));
+ posixSleep(s, ns);
},
Os.windows => {
const ns_per_ms = ns_per_s / ms_per_s;
const milliseconds = nanoseconds / ns_per_ms;
- windows.Sleep(@intCast(windows.DWORD, milliseconds));
+ const ms_that_will_fit = std.math.cast(windows.DWORD, milliseconds) catch std.math.maxInt(windows.DWORD);
+ windows.Sleep(ms_that_will_fit);
},
else => @compileError("Unsupported OS"),
}
}
-pub fn posixSleep(seconds: u63, nanoseconds: u63) void {
+/// Spurious wakeups are possible and no precision of timing is guaranteed.
+pub fn posixSleep(seconds: u64, nanoseconds: u64) void {
var req = posix.timespec{
- .tv_sec = seconds,
- .tv_nsec = nanoseconds,
+ .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize),
+ .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize),
};
var rem: posix.timespec = undefined;
while (true) {
const ret_val = posix.nanosleep(&req, &rem);
const err = posix.getErrno(ret_val);
- if (err == 0) return;
switch (err) {
posix.EFAULT => unreachable,
posix.EINVAL => {
@@ -49,6 +52,7 @@ pub fn posixSleep(seconds: u63, nanoseconds: u63) void {
req = rem;
continue;
},
+ // This prong handles success as well as unexpected errors.
else => return,
}
}
@@ -64,9 +68,21 @@ pub const milliTimestamp = switch (builtin.os) {
Os.windows => milliTimestampWindows,
Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix,
Os.macosx, Os.ios => milliTimestampDarwin,
+ Os.wasi => milliTimestampWasi,
else => @compileError("Unsupported OS"),
};
+fn milliTimestampWasi() u64 {
+ var ns: wasi.timestamp_t = undefined;
+
+ // TODO: Verify that precision is ignored
+ const err = wasi.clock_time_get(wasi.CLOCK_REALTIME, 1, &ns);
+ debug.assert(err == wasi.ESUCCESS);
+
+ const ns_per_ms = 1000;
+ return @divFloor(ns, ns_per_ms);
+}
+
fn milliTimestampWindows() u64 {
//FileTime has a granularity of 100 nanoseconds
// and uses the NTFS/Windows epoch
diff --git a/std/os/wasi.zig b/std/os/wasi.zig
new file mode 100644
index 0000000000..2118db9a2a
--- /dev/null
+++ b/std/os/wasi.zig
@@ -0,0 +1,42 @@
+pub use @import("wasi/core.zig");
+
+pub const STDIN_FILENO = 0;
+pub const STDOUT_FILENO = 1;
+pub const STDERR_FILENO = 2;
+
+pub fn getErrno(r: usize) usize {
+ const signed_r = @bitCast(isize, r);
+ return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0;
+}
+
+pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
+ var nwritten: usize = undefined;
+
+ const ciovs = ciovec_t{
+ .buf = buf,
+ .buf_len = count,
+ };
+
+ const err = fd_write(@bitCast(fd_t, isize(fd)), &ciovs, 1, &nwritten);
+ if (err == ESUCCESS) {
+ return nwritten;
+ } else {
+ return @bitCast(usize, -isize(err));
+ }
+}
+
+pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize {
+ var nread: usize = undefined;
+
+ const iovs = iovec_t{
+ .buf = buf,
+ .buf_len = nbyte,
+ };
+
+ const err = fd_read(@bitCast(fd_t, isize(fd)), &iovs, 1, &nread);
+ if (err == ESUCCESS) {
+ return nread;
+ } else {
+ return @bitCast(usize, -isize(err));
+ }
+}
diff --git a/std/os/wasi/core.zig b/std/os/wasi/core.zig
new file mode 100644
index 0000000000..f2bef73be9
--- /dev/null
+++ b/std/os/wasi/core.zig
@@ -0,0 +1,374 @@
+// Based on https://github.com/CraneStation/wasi-sysroot/blob/wasi/libc-bottom-half/headers/public/wasi/core.h
+// and https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md
+
+pub const advice_t = u8;
+pub const ADVICE_NORMAL: advice_t = 0;
+pub const ADVICE_SEQUENTIAL: advice_t = 1;
+pub const ADVICE_RANDOM: advice_t = 2;
+pub const ADVICE_WILLNEED: advice_t = 3;
+pub const ADVICE_DONTNEED: advice_t = 4;
+pub const ADVICE_NOREUSE: advice_t = 5;
+
+pub const ciovec_t = extern struct {
+ buf: [*]const u8,
+ buf_len: usize,
+};
+
+pub const clockid_t = u32;
+pub const CLOCK_REALTIME: clockid_t = 0;
+pub const CLOCK_MONOTONIC: clockid_t = 1;
+pub const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2;
+pub const CLOCK_THREAD_CPUTIME_ID: clockid_t = 3;
+
+pub const device_t = u64;
+
+pub const dircookie_t = u64;
+pub const DIRCOOKIE_START: dircookie_t = 0;
+
+pub const dirent_t = extern struct {
+ d_next: dircookie_t,
+ d_ino: inode_t,
+ d_namlen: u32,
+ d_type: filetype_t,
+};
+
+pub const errno_t = u16;
+pub const ESUCCESS: errno_t = 0;
+pub const E2BIG: errno_t = 1;
+pub const EACCES: errno_t = 2;
+pub const EADDRINUSE: errno_t = 3;
+pub const EADDRNOTAVAIL: errno_t = 4;
+pub const EAFNOSUPPORT: errno_t = 5;
+pub const EAGAIN: errno_t = 6;
+pub const EALREADY: errno_t = 7;
+pub const EBADF: errno_t = 8;
+pub const EBADMSG: errno_t = 9;
+pub const EBUSY: errno_t = 10;
+pub const ECANCELED: errno_t = 11;
+pub const ECHILD: errno_t = 12;
+pub const ECONNABORTED: errno_t = 13;
+pub const ECONNREFUSED: errno_t = 14;
+pub const ECONNRESET: errno_t = 15;
+pub const EDEADLK: errno_t = 16;
+pub const EDESTADDRREQ: errno_t = 17;
+pub const EDOM: errno_t = 18;
+pub const EDQUOT: errno_t = 19;
+pub const EEXIST: errno_t = 20;
+pub const EFAULT: errno_t = 21;
+pub const EFBIG: errno_t = 22;
+pub const EHOSTUNREACH: errno_t = 23;
+pub const EIDRM: errno_t = 24;
+pub const EILSEQ: errno_t = 25;
+pub const EINPROGRESS: errno_t = 26;
+pub const EINTR: errno_t = 27;
+pub const EINVAL: errno_t = 28;
+pub const EIO: errno_t = 29;
+pub const EISCONN: errno_t = 30;
+pub const EISDIR: errno_t = 31;
+pub const ELOOP: errno_t = 32;
+pub const EMFILE: errno_t = 33;
+pub const EMLINK: errno_t = 34;
+pub const EMSGSIZE: errno_t = 35;
+pub const EMULTIHOP: errno_t = 36;
+pub const ENAMETOOLONG: errno_t = 37;
+pub const ENETDOWN: errno_t = 38;
+pub const ENETRESET: errno_t = 39;
+pub const ENETUNREACH: errno_t = 40;
+pub const ENFILE: errno_t = 41;
+pub const ENOBUFS: errno_t = 42;
+pub const ENODEV: errno_t = 43;
+pub const ENOENT: errno_t = 44;
+pub const ENOEXEC: errno_t = 45;
+pub const ENOLCK: errno_t = 46;
+pub const ENOLINK: errno_t = 47;
+pub const ENOMEM: errno_t = 48;
+pub const ENOMSG: errno_t = 49;
+pub const ENOPROTOOPT: errno_t = 50;
+pub const ENOSPC: errno_t = 51;
+pub const ENOSYS: errno_t = 52;
+pub const ENOTCONN: errno_t = 53;
+pub const ENOTDIR: errno_t = 54;
+pub const ENOTEMPTY: errno_t = 55;
+pub const ENOTRECOVERABLE: errno_t = 56;
+pub const ENOTSOCK: errno_t = 57;
+pub const ENOTSUP: errno_t = 58;
+pub const ENOTTY: errno_t = 59;
+pub const ENXIO: errno_t = 60;
+pub const EOVERFLOW: errno_t = 61;
+pub const EOWNERDEAD: errno_t = 62;
+pub const EPERM: errno_t = 63;
+pub const EPIPE: errno_t = 64;
+pub const EPROTO: errno_t = 65;
+pub const EPROTONOSUPPORT: errno_t = 66;
+pub const EPROTOTYPE: errno_t = 67;
+pub const ERANGE: errno_t = 68;
+pub const EROFS: errno_t = 69;
+pub const ESPIPE: errno_t = 70;
+pub const ESRCH: errno_t = 71;
+pub const ESTALE: errno_t = 72;
+pub const ETIMEDOUT: errno_t = 73;
+pub const ETXTBSY: errno_t = 74;
+pub const EXDEV: errno_t = 75;
+pub const ENOTCAPABLE: errno_t = 76;
+
+pub const event_t = extern struct {
+ userdata: userdata_t,
+ @"error": errno_t,
+ @"type": eventtype_t,
+ u: extern union {
+ fd_readwrite: extern struct {
+ nbytes: filesize_t,
+ flags: eventrwflags_t,
+ },
+ },
+};
+
+pub const eventrwflags_t = u16;
+pub const EVENT_FD_READWRITE_HANGUP: eventrwflags_t = 0x0001;
+
+pub const eventtype_t = u8;
+pub const EVENTTYPE_CLOCK: eventtype_t = 0;
+pub const EVENTTYPE_FD_READ: eventtype_t = 1;
+pub const EVENTTYPE_FD_WRITE: eventtype_t = 2;
+
+pub const exitcode_t = u32;
+
+pub const fd_t = u32;
+
+pub const fdflags_t = u16;
+pub const FDFLAG_APPEND: fdflags_t = 0x0001;
+pub const FDFLAG_DSYNC: fdflags_t = 0x0002;
+pub const FDFLAG_NONBLOCK: fdflags_t = 0x0004;
+pub const FDFLAG_RSYNC: fdflags_t = 0x0008;
+pub const FDFLAG_SYNC: fdflags_t = 0x0010;
+
+const fdstat_t = extern struct {
+ fs_filetype: filetype_t,
+ fs_flags: fdflags_t,
+ fs_rights_base: rights_t,
+ fs_rights_inheriting: rights_t,
+};
+
+pub const filedelta_t = i64;
+
+pub const filesize_t = u64;
+
+pub const filestat_t = extern struct {
+ st_dev: device_t,
+ st_ino: inode_t,
+ st_filetype: filetype_t,
+ st_nlink: linkcount_t,
+ st_size: filesize_t,
+ st_atim: timestamp_t,
+ st_mtim: timestamp_t,
+ st_ctim: timestamp_t,
+};
+
+pub const filetype_t = u8;
+pub const FILETYPE_UNKNOWN: filetype_t = 0;
+pub const FILETYPE_BLOCK_DEVICE: filetype_t = 1;
+pub const FILETYPE_CHARACTER_DEVICE: filetype_t = 2;
+pub const FILETYPE_DIRECTORY: filetype_t = 3;
+pub const FILETYPE_REGULAR_FILE: filetype_t = 4;
+pub const FILETYPE_SOCKET_DGRAM: filetype_t = 5;
+pub const FILETYPE_SOCKET_STREAM: filetype_t = 6;
+pub const FILETYPE_SYMBOLIC_LINK: filetype_t = 7;
+
+pub const fstflags_t = u16;
+pub const FILESTAT_SET_ATIM: fstflags_t = 0x0001;
+pub const FILESTAT_SET_ATIM_NOW: fstflags_t = 0x0002;
+pub const FILESTAT_SET_MTIM: fstflags_t = 0x0004;
+pub const FILESTAT_SET_MTIM_NOW: fstflags_t = 0x0008;
+
+pub const inode_t = u64;
+
+pub const iovec_t = extern struct {
+ buf: [*]u8,
+ buf_len: usize,
+};
+
+pub const linkcount_t = u32;
+
+pub const lookupflags_t = u32;
+pub const LOOKUP_SYMLINK_FOLLOW: lookupflags_t = 0x00000001;
+
+pub const oflags_t = u16;
+pub const O_CREAT: oflags_t = 0x0001;
+pub const O_DIRECTORY: oflags_t = 0x0002;
+pub const O_EXCL: oflags_t = 0x0004;
+pub const O_TRUNC: oflags_t = 0x0008;
+
+pub const preopentype_t = u8;
+pub const PREOPENTYPE_DIR: preopentype_t = 0;
+
+pub const prestat_t = extern struct {
+ pr_type: preopentype_t,
+ u: extern union {
+ dir: extern struct {
+ pr_name_len: usize,
+ },
+ },
+};
+
+pub const riflags_t = u16;
+pub const SOCK_RECV_PEEK: riflags_t = 0x0001;
+pub const SOCK_RECV_WAITALL: riflags_t = 0x0002;
+
+pub const rights_t = u64;
+pub const RIGHT_FD_DATASYNC: rights_t = 0x0000000000000001;
+pub const RIGHT_FD_READ: rights_t = 0x0000000000000002;
+pub const RIGHT_FD_SEEK: rights_t = 0x0000000000000004;
+pub const RIGHT_FD_FDSTAT_SET_FLAGS: rights_t = 0x0000000000000008;
+pub const RIGHT_FD_SYNC: rights_t = 0x0000000000000010;
+pub const RIGHT_FD_TELL: rights_t = 0x0000000000000020;
+pub const RIGHT_FD_WRITE: rights_t = 0x0000000000000040;
+pub const RIGHT_FD_ADVISE: rights_t = 0x0000000000000080;
+pub const RIGHT_FD_ALLOCATE: rights_t = 0x0000000000000100;
+pub const RIGHT_PATH_CREATE_DIRECTORY: rights_t = 0x0000000000000200;
+pub const RIGHT_PATH_CREATE_FILE: rights_t = 0x0000000000000400;
+pub const RIGHT_PATH_LINK_SOURCE: rights_t = 0x0000000000000800;
+pub const RIGHT_PATH_LINK_TARGET: rights_t = 0x0000000000001000;
+pub const RIGHT_PATH_OPEN: rights_t = 0x0000000000002000;
+pub const RIGHT_FD_READDIR: rights_t = 0x0000000000004000;
+pub const RIGHT_PATH_READLINK: rights_t = 0x0000000000008000;
+pub const RIGHT_PATH_RENAME_SOURCE: rights_t = 0x0000000000010000;
+pub const RIGHT_PATH_RENAME_TARGET: rights_t = 0x0000000000020000;
+pub const RIGHT_PATH_FILESTAT_GET: rights_t = 0x0000000000040000;
+pub const RIGHT_PATH_FILESTAT_SET_SIZE: rights_t = 0x0000000000080000;
+pub const RIGHT_PATH_FILESTAT_SET_TIMES: rights_t = 0x0000000000100000;
+pub const RIGHT_FD_FILESTAT_GET: rights_t = 0x0000000000200000;
+pub const RIGHT_FD_FILESTAT_SET_SIZE: rights_t = 0x0000000000400000;
+pub const RIGHT_FD_FILESTAT_SET_TIMES: rights_t = 0x0000000000800000;
+pub const RIGHT_PATH_SYMLINK: rights_t = 0x0000000001000000;
+pub const RIGHT_PATH_REMOVE_DIRECTORY: rights_t = 0x0000000002000000;
+pub const RIGHT_PATH_UNLINK_FILE: rights_t = 0x0000000004000000;
+pub const RIGHT_POLL_FD_READWRITE: rights_t = 0x0000000008000000;
+pub const RIGHT_SOCK_SHUTDOWN: rights_t = 0x0000000010000000;
+
+pub const roflags_t = u16;
+pub const SOCK_RECV_DATA_TRUNCATED: roflags_t = 0x0001;
+
+pub const sdflags_t = u8;
+pub const SHUT_RD: sdflags_t = 0x01;
+pub const SHUT_WR: sdflags_t = 0x02;
+
+pub const siflags_t = u16;
+
+pub const signal_t = u8;
+pub const SIGHUP: signal_t = 1;
+pub const SIGINT: signal_t = 2;
+pub const SIGQUIT: signal_t = 3;
+pub const SIGILL: signal_t = 4;
+pub const SIGTRAP: signal_t = 5;
+pub const SIGABRT: signal_t = 6;
+pub const SIGBUS: signal_t = 7;
+pub const SIGFPE: signal_t = 8;
+pub const SIGKILL: signal_t = 9;
+pub const SIGUSR1: signal_t = 10;
+pub const SIGSEGV: signal_t = 11;
+pub const SIGUSR2: signal_t = 12;
+pub const SIGPIPE: signal_t = 13;
+pub const SIGALRM: signal_t = 14;
+pub const SIGTERM: signal_t = 15;
+pub const SIGCHLD: signal_t = 16;
+pub const SIGCONT: signal_t = 17;
+pub const SIGSTOP: signal_t = 18;
+pub const SIGTSTP: signal_t = 19;
+pub const SIGTTIN: signal_t = 20;
+pub const SIGTTOU: signal_t = 21;
+pub const SIGURG: signal_t = 22;
+pub const SIGXCPU: signal_t = 23;
+pub const SIGXFSZ: signal_t = 24;
+pub const SIGVTALRM: signal_t = 25;
+pub const SIGPROF: signal_t = 26;
+pub const SIGWINCH: signal_t = 27;
+pub const SIGPOLL: signal_t = 28;
+pub const SIGPWR: signal_t = 29;
+pub const SIGSYS: signal_t = 30;
+
+pub const subclockflags_t = u16;
+pub const SUBSCRIPTION_CLOCK_ABSTIME: subclockflags_t = 0x0001;
+
+pub const subscription_t = extern struct {
+ userdata: userdata_t,
+ @"type": eventtype_t,
+ u: extern union {
+ clock: extern struct {
+ identifier: userdata_t,
+ clock_id: clockid_t,
+ timeout: timestamp_t,
+ precision: timestamp_t,
+ flags: subclockflags_t,
+ },
+ fd_readwrite: extern struct {
+ fd: fd_t,
+ },
+ },
+};
+
+pub const timestamp_t = u64;
+
+pub const userdata_t = u64;
+
+pub const whence_t = u8;
+pub const WHENCE_CUR: whence_t = 0;
+pub const WHENCE_END: whence_t = 1;
+pub const WHENCE_SET: whence_t = 2;
+
+pub extern "wasi_unstable" fn args_get(argv: [*][*]u8, argv_buf: [*]u8) errno_t;
+pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
+
+pub extern "wasi_unstable" fn clock_res_get(clock_id: clockid_t, resolution: *timestamp_t) errno_t;
+pub extern "wasi_unstable" fn clock_time_get(clock_id: clockid_t, precision: timestamp_t, timestamp: *timestamp_t) errno_t;
+
+pub extern "wasi_unstable" fn environ_get(environ: [*]?[*]u8, environ_buf: [*]u8) errno_t;
+pub extern "wasi_unstable" fn environ_sizes_get(environ_count: *usize, environ_buf_size: *usize) errno_t;
+
+pub extern "wasi_unstable" fn fd_advise(fd: fd_t, offset: filesize_t, len: filesize_t, advice: advice_t) errno_t;
+pub extern "wasi_unstable" fn fd_allocate(fd: fd_t, offset: filesize_t, len: filesize_t) errno_t;
+pub extern "wasi_unstable" fn fd_close(fd: fd_t) errno_t;
+pub extern "wasi_unstable" fn fd_datasync(fd: fd_t) errno_t;
+pub extern "wasi_unstable" fn fd_pread(fd: fd_t, iovs: *const iovec_t, iovs_len: usize, offset: filesize_t, nread: *usize) errno_t;
+pub extern "wasi_unstable" fn fd_pwrite(fd: fd_t, iovs: *const ciovec_t, iovs_len: usize, offset: filesize_t, nwritten: *usize) errno_t;
+pub extern "wasi_unstable" fn fd_read(fd: fd_t, iovs: *const iovec_t, iovs_len: usize, nread: *usize) errno_t;
+pub extern "wasi_unstable" fn fd_readdir(fd: fd_t, buf: [*]u8, buf_len: usize, cookie: dircookie_t, bufused: *usize) errno_t;
+pub extern "wasi_unstable" fn fd_renumber(from: fd_t, to: fd_t) errno_t;
+pub extern "wasi_unstable" fn fd_seek(fd: fd_t, offset: filedelta_t, whence: whence_t, newoffset: *filesize_t) errno_t;
+pub extern "wasi_unstable" fn fd_sync(fd: fd_t) errno_t;
+pub extern "wasi_unstable" fn fd_tell(fd: fd_t, newoffset: *filesize_t) errno_t;
+pub extern "wasi_unstable" fn fd_write(fd: fd_t, iovs: *const ciovec_t, iovs_len: usize, nwritten: *usize) errno_t;
+
+pub extern "wasi_unstable" fn fd_fdstat_get(fd: fd_t, buf: *fdstat_t) errno_t;
+pub extern "wasi_unstable" fn fd_fdstat_set_flags(fd: fd_t, flags: fdflags_t) errno_t;
+pub extern "wasi_unstable" fn fd_fdstat_set_rights(fd: fd_t, fs_rights_base: rights_t, fs_rights_inheriting: rights_t) errno_t;
+
+pub extern "wasi_unstable" fn fd_filestat_get(fd: fd_t, buf: *filestat_t) errno_t;
+pub extern "wasi_unstable" fn fd_filestat_set_size(fd: fd_t, st_size: filesize_t) errno_t;
+pub extern "wasi_unstable" fn fd_filestat_set_times(fd: fd_t, st_atim: timestamp_t, st_mtim: timestamp_t, fstflags: fstflags_t) errno_t;
+
+pub extern "wasi_unstable" fn fd_prestat_get(fd: fd_t, buf: *prestat_t) errno_t;
+pub extern "wasi_unstable" fn fd_prestat_dir_name(fd: fd_t, path: [*]u8, path_len: usize) errno_t;
+
+pub extern "wasi_unstable" fn path_create_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;
+pub extern "wasi_unstable" fn path_filestat_get(fd: fd_t, flags: lookupflags_t, path: [*]const u8, path_len: usize, buf: *filestat_t) errno_t;
+pub extern "wasi_unstable" fn path_filestat_set_times(fd: fd_t, flags: lookupflags_t, path: [*]const u8, path_len: usize, st_atim: timestamp_t, st_mtim: timestamp_t, fstflags: fstflags_t) errno_t;
+pub extern "wasi_unstable" fn path_link(old_fd: fd_t, old_flags: lookupflags_t, old_path: [*]const u8, old_path_len: usize, new_fd: fd_t, new_path: [*]const u8, new_path_len: usize) errno_t;
+pub extern "wasi_unstable" fn path_open(dirfd: fd_t, dirflags: lookupflags_t, path: [*]const u8, path_len: usize, oflags: oflags_t, fs_rights_base: rights_t, fs_rights_inheriting: rights_t, fs_flags: fdflags_t, fd: *fd_t) errno_t;
+pub extern "wasi_unstable" fn path_readlink(fd: fd_t, path: [*]const u8, path_len: usize, buf: [*]u8, buf_len: usize, bufused: *usize) errno_t;
+pub extern "wasi_unstable" fn path_remove_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;
+pub extern "wasi_unstable" fn path_rename(old_fd: fd_t, old_path: [*]const u8, old_path_len: usize, new_fd: fd_t, new_path: [*]const u8, new_path_len: usize) errno_t;
+pub extern "wasi_unstable" fn path_symlink(old_path: [*]const u8, old_path_len: usize, fd: fd_t, new_path: [*]const u8, new_path_len: usize) errno_t;
+pub extern "wasi_unstable" fn path_unlink_file(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;
+
+pub extern "wasi_unstable" fn poll_oneoff(in: *const subscription_t, out: *event_t, nsubscriptions: usize, nevents: *usize) errno_t;
+
+pub extern "wasi_unstable" fn proc_exit(rval: exitcode_t) noreturn;
+pub extern "wasi_unstable" fn proc_raise(sig: signal_t) errno_t;
+
+pub extern "wasi_unstable" fn random_get(buf: [*]u8, buf_len: usize) errno_t;
+
+pub extern "wasi_unstable" fn sched_yield() errno_t;
+
+pub extern "wasi_unstable" fn sock_recv(sock: fd_t, ri_data: *const iovec_t, ri_data_len: usize, ri_flags: riflags_t, ro_datalen: *usize, ro_flags: *roflags_t) errno_t;
+pub extern "wasi_unstable" fn sock_send(sock: fd_t, si_data: *const ciovec_t, si_data_len: usize, si_flags: siflags_t, so_datalen: *usize) errno_t;
+pub extern "wasi_unstable" fn sock_shutdown(sock: fd_t, how: sdflags_t) errno_t;
diff --git a/std/os/windows.zig b/std/os/windows.zig
index 96274632ce..e134d87eae 100644
--- a/std/os/windows.zig
+++ b/std/os/windows.zig
@@ -239,6 +239,37 @@ pub const HEAP_CREATE_ENABLE_EXECUTE = 0x00040000;
pub const HEAP_GENERATE_EXCEPTIONS = 0x00000004;
pub const HEAP_NO_SERIALIZE = 0x00000001;
+// AllocationType values
+pub const MEM_COMMIT = 0x1000;
+pub const MEM_RESERVE = 0x2000;
+pub const MEM_RESET = 0x80000;
+pub const MEM_RESET_UNDO = 0x1000000;
+pub const MEM_LARGE_PAGES = 0x20000000;
+pub const MEM_PHYSICAL = 0x400000;
+pub const MEM_TOP_DOWN = 0x100000;
+pub const MEM_WRITE_WATCH = 0x200000;
+
+// Protect values
+pub const PAGE_EXECUTE = 0x10;
+pub const PAGE_EXECUTE_READ = 0x20;
+pub const PAGE_EXECUTE_READWRITE = 0x40;
+pub const PAGE_EXECUTE_WRITECOPY = 0x80;
+pub const PAGE_NOACCESS = 0x01;
+pub const PAGE_READONLY = 0x02;
+pub const PAGE_READWRITE = 0x04;
+pub const PAGE_WRITECOPY = 0x08;
+pub const PAGE_TARGETS_INVALID = 0x40000000;
+pub const PAGE_TARGETS_NO_UPDATE = 0x40000000; // Same as PAGE_TARGETS_INVALID
+pub const PAGE_GUARD = 0x100;
+pub const PAGE_NOCACHE = 0x200;
+pub const PAGE_WRITECOMBINE = 0x400;
+
+// FreeType values
+pub const MEM_COALESCE_PLACEHOLDERS = 0x1;
+pub const MEM_RESERVE_PLACEHOLDERS = 0x2;
+pub const MEM_DECOMMIT = 0x4000;
+pub const MEM_RELEASE = 0x8000;
+
pub const PTHREAD_START_ROUTINE = extern fn (LPVOID) DWORD;
pub const LPTHREAD_START_ROUTINE = PTHREAD_START_ROUTINE;
diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig
index 64a97ca87d..7e99f7eda9 100644
--- a/std/os/windows/kernel32.zig
+++ b/std/os/windows/kernel32.zig
@@ -116,6 +116,9 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem
pub extern "kernel32" stdcallcc fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*const c_void) BOOL;
+pub extern "kernel32" stdcallcc fn VirtualAlloc(lpAddress: ?LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD) ?LPVOID;
+pub extern "kernel32" stdcallcc fn VirtualFree(lpAddress: ?LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) BOOL;
+
pub extern "kernel32" stdcallcc fn MoveFileExW(
lpExistingFileName: [*]const u16,
lpNewFileName: [*]const u16,
diff --git a/std/packed_int_array.zig b/std/packed_int_array.zig
new file mode 100644
index 0000000000..d4ed68c6ee
--- /dev/null
+++ b/std/packed_int_array.zig
@@ -0,0 +1,649 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const debug = std.debug;
+const testing = std.testing;
+
+pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
+ //The general technique employed here is to cast bytes in the array to a container
+ // integer (having bits % 8 == 0) large enough to contain the number of bits we want,
+ // then we can retrieve or store the new value with a relative minimum of masking
+ // and shifting. In this worst case, this means that we'll need an integer that's
+ // actually 1 byte larger than the minimum required to store the bits, because it
+ // is possible that the bits start at the end of the first byte, continue through
+ // zero or more, then end in the beginning of the last. But, if we try to access
+ // a value in the very last byte of memory with that integer size, that extra byte
+ // will be out of bounds. Depending on the circumstances of the memory, that might
+ // mean the OS fatally kills the program. Thus, we use a larger container (MaxIo)
+ // most of the time, but a smaller container (MinIo) when touching the last byte
+ // of the memory.
+ const int_bits = comptime std.meta.bitCount(Int);
+
+ //in the best case, this is the number of bytes we need to touch
+ // to read or write a value, as bits
+ const min_io_bits = ((int_bits + 7) / 8) * 8;
+
+ //in the worst case, this is the number of bytes we need to touch
+ // to read or write a value, as bits
+ const max_io_bits = switch (int_bits) {
+ 0 => 0,
+ 1 => 8,
+ 2...9 => 16,
+ 10...65535 => ((int_bits / 8) + 2) * 8,
+ else => unreachable,
+ };
+
+ //we bitcast the desired Int type to an unsigned version of itself
+ // to avoid issues with shifting signed ints.
+ const UnInt = @IntType(false, int_bits);
+
+ //The maximum container int type
+ const MinIo = @IntType(false, min_io_bits);
+
+ //The minimum container int type
+ const MaxIo = @IntType(false, max_io_bits);
+
+ return struct {
+ pub fn get(bytes: []const u8, index: usize, bit_offset: u7) Int {
+ if (int_bits == 0) return 0;
+
+ const bit_index = (index * int_bits) + bit_offset;
+ const max_end_byte = (bit_index + max_io_bits) / 8;
+
+ //Using the larger container size will potentially read out of bounds
+ if (max_end_byte > bytes.len) return getBits(bytes, MinIo, bit_index);
+ return getBits(bytes, MaxIo, bit_index);
+ }
+
+ fn getBits(bytes: []const u8, comptime Container: type, bit_index: usize) Int {
+ const container_bits = comptime std.meta.bitCount(Container);
+ const Shift = std.math.Log2Int(Container);
+
+ const start_byte = bit_index / 8;
+ const head_keep_bits = bit_index - (start_byte * 8);
+ const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
+
+ //read bytes as container
+ const value_ptr = @ptrCast(*align(1) const Container, &bytes[start_byte]);
+ var value = value_ptr.*;
+
+ if (endian != builtin.endian) value = @bswap(Container, value);
+
+ switch (endian) {
+ .Big => {
+ value <<= @intCast(Shift, head_keep_bits);
+ value >>= @intCast(Shift, head_keep_bits);
+ value >>= @intCast(Shift, tail_keep_bits);
+ },
+ .Little => {
+ value <<= @intCast(Shift, tail_keep_bits);
+ value >>= @intCast(Shift, tail_keep_bits);
+ value >>= @intCast(Shift, head_keep_bits);
+ },
+ }
+
+ return @bitCast(Int, @truncate(UnInt, value));
+ }
+
+ pub fn set(bytes: []u8, index: usize, bit_offset: u3, int: Int) void {
+ if (int_bits == 0) return;
+
+ const bit_index = (index * int_bits) + bit_offset;
+ const max_end_byte = (bit_index + max_io_bits) / 8;
+
+ //Using the larger container size will potentially write out of bounds
+ if (max_end_byte > bytes.len) return setBits(bytes, MinIo, bit_index, int);
+ setBits(bytes, MaxIo, bit_index, int);
+ }
+
+ fn setBits(bytes: []u8, comptime Container: type, bit_index: usize, int: Int) void {
+ const container_bits = comptime std.meta.bitCount(Container);
+ const Shift = std.math.Log2Int(Container);
+
+ const start_byte = bit_index / 8;
+ const head_keep_bits = bit_index - (start_byte * 8);
+ const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
+ const keep_shift = switch (endian) {
+ .Big => @intCast(Shift, tail_keep_bits),
+ .Little => @intCast(Shift, head_keep_bits),
+ };
+
+ //position the bits where they need to be in the container
+ const value = @intCast(Container, @bitCast(UnInt, int)) << keep_shift;
+
+ //read existing bytes
+ const target_ptr = @ptrCast(*align(1) Container, &bytes[start_byte]);
+ var target = target_ptr.*;
+
+ if (endian != builtin.endian) target = @bswap(Container, target);
+
+ //zero the bits we want to replace in the existing bytes
+ const inv_mask = @intCast(Container, std.math.maxInt(UnInt)) << keep_shift;
+ const mask = ~inv_mask;
+ target &= mask;
+
+ //merge the new value
+ target |= value;
+
+ if (endian != builtin.endian) target = @bswap(Container, target);
+
+ //save it back
+ target_ptr.* = target;
+ }
+
+ fn slice(bytes: []u8, bit_offset: u3, start: usize, end: usize) PackedIntSliceEndian(Int, endian) {
+ debug.assert(end >= start);
+
+ const length = end - start;
+ const bit_index = (start * int_bits) + bit_offset;
+ const start_byte = bit_index / 8;
+ const end_byte = (bit_index + (length * int_bits) + 7) / 8;
+ const new_bytes = bytes[start_byte..end_byte];
+
+ if (length == 0) return PackedIntSliceEndian(Int, endian).init(new_bytes[0..0], 0);
+
+ var new_slice = PackedIntSliceEndian(Int, endian).init(new_bytes, length);
+ new_slice.bit_offset = @intCast(u3, (bit_index - (start_byte * 8)));
+ return new_slice;
+ }
+
+ fn sliceCast(bytes: []u8, comptime NewInt: type, comptime new_endian: builtin.Endian, bit_offset: u3, old_len: usize) PackedIntSliceEndian(NewInt, new_endian) {
+ const new_int_bits = comptime std.meta.bitCount(NewInt);
+ const New = PackedIntSliceEndian(NewInt, new_endian);
+
+ const total_bits = (old_len * int_bits);
+ const new_int_count = total_bits / new_int_bits;
+
+ debug.assert(total_bits == new_int_count * new_int_bits);
+
+ var new = New.init(bytes, new_int_count);
+ new.bit_offset = bit_offset;
+
+ return new;
+ }
+ };
+}
+
+///Creates a bit-packed array of integers of type Int. Bits
+/// are packed using native endianess and without storing any meta
+/// data. PackedIntArray(i3, 8) will occupy exactly 3 bytes of memory.
+pub fn PackedIntArray(comptime Int: type, comptime int_count: usize) type {
+ return PackedIntArrayEndian(Int, builtin.endian, int_count);
+}
+
+///Creates a bit-packed array of integers of type Int. Bits
+/// are packed using specified endianess and without storing any meta
+/// data.
+pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian, comptime int_count: usize) type {
+ const int_bits = comptime std.meta.bitCount(Int);
+ const total_bits = int_bits * int_count;
+ const total_bytes = (total_bits + 7) / 8;
+
+ const Io = PackedIntIo(Int, endian);
+
+ return struct {
+ const Self = @This();
+
+ bytes: [total_bytes]u8,
+
+ ///Returns the number of elements in the packed array
+ pub fn len(self: Self) usize {
+ return int_count;
+ }
+
+ ///Initialize a packed array using an unpacked array
+ /// or, more likely, an array literal.
+ pub fn init(ints: [int_count]Int) Self {
+ var self = Self(undefined);
+ for (ints) |int, i| self.set(i, int);
+ return self;
+ }
+
+ ///Return the Int stored at index
+ pub fn get(self: Self, index: usize) Int {
+ debug.assert(index < int_count);
+ return Io.get(self.bytes, index, 0);
+ }
+
+ ///Copy int into the array at index
+ pub fn set(self: *Self, index: usize, int: Int) void {
+ debug.assert(index < int_count);
+ return Io.set(&self.bytes, index, 0, int);
+ }
+
+ ///Create a PackedIntSlice of the array from given start to given end
+ pub fn slice(self: *Self, start: usize, end: usize) PackedIntSliceEndian(Int, endian) {
+ debug.assert(start < int_count);
+ debug.assert(end <= int_count);
+ return Io.slice(&self.bytes, 0, start, end);
+ }
+
+ ///Create a PackedIntSlice of the array using NewInt as the bit width integer.
+ /// NewInt's bit width must fit evenly within the array's Int's total bits.
+ pub fn sliceCast(self: *Self, comptime NewInt: type) PackedIntSlice(NewInt) {
+ return self.sliceCastEndian(NewInt, endian);
+ }
+
+ ///Create a PackedIntSlice of the array using NewInt as the bit width integer
+ /// and new_endian as the new endianess. NewInt's bit width must fit evenly within
+ /// the array's Int's total bits.
+ pub fn sliceCastEndian(self: *Self, comptime NewInt: type, comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian) {
+ return Io.sliceCast(&self.bytes, NewInt, new_endian, 0, int_count);
+ }
+ };
+}
+
+///Uses a slice as a bit-packed block of int_count integers of type Int.
+/// Bits are packed using native endianess and without storing any meta
+/// data.
+pub fn PackedIntSlice(comptime Int: type) type {
+ return PackedIntSliceEndian(Int, builtin.endian);
+}
+
+///Uses a slice as a bit-packed block of int_count integers of type Int.
+/// Bits are packed using specified endianess and without storing any meta
+/// data.
+pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian) type {
+ const int_bits = comptime std.meta.bitCount(Int);
+ const Io = PackedIntIo(Int, endian);
+
+ return struct {
+ const Self = @This();
+
+ bytes: []u8,
+ int_count: usize,
+ bit_offset: u3,
+
+ ///Returns the number of elements in the packed slice
+ pub fn len(self: Self) usize {
+ return self.int_count;
+ }
+
+ ///Calculates the number of bytes required to store a desired count
+ /// of Ints
+ pub fn bytesRequired(int_count: usize) usize {
+ const total_bits = int_bits * int_count;
+ const total_bytes = (total_bits + 7) / 8;
+ return total_bytes;
+ }
+
+ ///Initialize a packed slice using the memory at bytes, with int_count
+ /// elements. bytes must be large enough to accomodate the requested
+ /// count.
+ pub fn init(bytes: []u8, int_count: usize) Self {
+ debug.assert(bytes.len >= bytesRequired(int_count));
+
+ return Self{
+ .bytes = bytes,
+ .int_count = int_count,
+ .bit_offset = 0,
+ };
+ }
+
+ ///Return the Int stored at index
+ pub fn get(self: Self, index: usize) Int {
+ debug.assert(index < self.int_count);
+ return Io.get(self.bytes, index, self.bit_offset);
+ }
+
+ ///Copy int into the array at index
+ pub fn set(self: *Self, index: usize, int: Int) void {
+ debug.assert(index < self.int_count);
+ return Io.set(self.bytes, index, self.bit_offset, int);
+ }
+
+ ///Create a PackedIntSlice of this slice from given start to given end
+ pub fn slice(self: Self, start: usize, end: usize) PackedIntSliceEndian(Int, endian) {
+ debug.assert(start < self.int_count);
+ debug.assert(end <= self.int_count);
+ return Io.slice(self.bytes, self.bit_offset, start, end);
+ }
+
+ ///Create a PackedIntSlice of this slice using NewInt as the bit width integer.
+ /// NewInt's bit width must fit evenly within this slice's Int's total bits.
+ pub fn sliceCast(self: Self, comptime NewInt: type) PackedIntSliceEndian(NewInt, endian) {
+ return self.sliceCastEndian(NewInt, endian);
+ }
+
+ ///Create a PackedIntSlice of this slice using NewInt as the bit width integer
+ /// and new_endian as the new endianess. NewInt's bit width must fit evenly within
+ /// this slice's Int's total bits.
+ pub fn sliceCastEndian(self: Self, comptime NewInt: type, comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian) {
+ return Io.sliceCast(self.bytes, NewInt, new_endian, self.bit_offset, self.int_count);
+ }
+ };
+}
+
+test "PackedIntArray" {
+ @setEvalBranchQuota(10000);
+ const max_bits = 256;
+ const int_count = 19;
+
+ comptime var bits = 0;
+ inline while (bits <= 256) : (bits += 1) {
+ //alternate unsigned and signed
+ const even = bits % 2 == 0;
+ const I = @IntType(even, bits);
+
+ const PackedArray = PackedIntArray(I, int_count);
+ const expected_bytes = ((bits * int_count) + 7) / 8;
+ testing.expect(@sizeOf(PackedArray) == expected_bytes);
+
+ var data = PackedArray(undefined);
+
+ //write values, counting up
+ var i = usize(0);
+ var count = I(0);
+ while (i < data.len()) : (i += 1) {
+ data.set(i, count);
+ if (bits > 0) count +%= 1;
+ }
+
+ //read and verify values
+ i = 0;
+ count = 0;
+ while (i < data.len()) : (i += 1) {
+ const val = data.get(i);
+ testing.expect(val == count);
+ if (bits > 0) count +%= 1;
+ }
+ }
+}
+
+test "PackedIntArray init" {
+ const PackedArray = PackedIntArray(u3, 8);
+ var packed_array = PackedArray.init([]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
+ var i = usize(0);
+ while (i < packed_array.len()) : (i += 1) testing.expect(packed_array.get(i) == i);
+}
+
+test "PackedIntSlice" {
+ @setEvalBranchQuota(10000);
+ const max_bits = 256;
+ const int_count = 19;
+ const total_bits = max_bits * int_count;
+ const total_bytes = (total_bits + 7) / 8;
+
+ var buffer: [total_bytes]u8 = undefined;
+
+ comptime var bits = 0;
+ inline while (bits <= 256) : (bits += 1) {
+ //alternate unsigned and signed
+ const even = bits % 2 == 0;
+ const I = @IntType(even, bits);
+ const P = PackedIntSlice(I);
+
+ var data = P.init(&buffer, int_count);
+
+ //write values, counting up
+ var i = usize(0);
+ var count = I(0);
+ while (i < data.len()) : (i += 1) {
+ data.set(i, count);
+ if (bits > 0) count +%= 1;
+ }
+
+ //read and verify values
+ i = 0;
+ count = 0;
+ while (i < data.len()) : (i += 1) {
+ const val = data.get(i);
+ testing.expect(val == count);
+ if (bits > 0) count +%= 1;
+ }
+ }
+}
+
+test "PackedIntSlice of PackedInt(Array/Slice)" {
+ const max_bits = 16;
+ const int_count = 19;
+
+ comptime var bits = 0;
+ inline while (bits <= max_bits) : (bits += 1) {
+ const Int = @IntType(false, bits);
+
+ const PackedArray = PackedIntArray(Int, int_count);
+ var packed_array = PackedArray(undefined);
+
+ const limit = (1 << bits);
+
+ var i = usize(0);
+ while (i < packed_array.len()) : (i += 1) {
+ packed_array.set(i, @intCast(Int, i % limit));
+ }
+
+ //slice of array
+ var packed_slice = packed_array.slice(2, 5);
+ testing.expect(packed_slice.len() == 3);
+ const ps_bit_count = (bits * packed_slice.len()) + packed_slice.bit_offset;
+ const ps_expected_bytes = (ps_bit_count + 7) / 8;
+ testing.expect(packed_slice.bytes.len == ps_expected_bytes);
+ testing.expect(packed_slice.get(0) == 2 % limit);
+ testing.expect(packed_slice.get(1) == 3 % limit);
+ testing.expect(packed_slice.get(2) == 4 % limit);
+ packed_slice.set(1, 7 % limit);
+ testing.expect(packed_slice.get(1) == 7 % limit);
+
+ //write through slice
+ testing.expect(packed_array.get(3) == 7 % limit);
+
+ //slice of a slice
+ const packed_slice_two = packed_slice.slice(0, 3);
+ testing.expect(packed_slice_two.len() == 3);
+ const ps2_bit_count = (bits * packed_slice_two.len()) + packed_slice_two.bit_offset;
+ const ps2_expected_bytes = (ps2_bit_count + 7) / 8;
+ testing.expect(packed_slice_two.bytes.len == ps2_expected_bytes);
+ testing.expect(packed_slice_two.get(1) == 7 % limit);
+ testing.expect(packed_slice_two.get(2) == 4 % limit);
+
+ //size one case
+ const packed_slice_three = packed_slice_two.slice(1, 2);
+ testing.expect(packed_slice_three.len() == 1);
+ const ps3_bit_count = (bits * packed_slice_three.len()) + packed_slice_three.bit_offset;
+ const ps3_expected_bytes = (ps3_bit_count + 7) / 8;
+ testing.expect(packed_slice_three.bytes.len == ps3_expected_bytes);
+ testing.expect(packed_slice_three.get(0) == 7 % limit);
+
+ //empty slice case
+ const packed_slice_empty = packed_slice.slice(0, 0);
+ testing.expect(packed_slice_empty.len() == 0);
+ testing.expect(packed_slice_empty.bytes.len == 0);
+
+ //slicing at byte boundaries
+ const packed_slice_edge = packed_array.slice(8, 16);
+ testing.expect(packed_slice_edge.len() == 8);
+ const pse_bit_count = (bits * packed_slice_edge.len()) + packed_slice_edge.bit_offset;
+ const pse_expected_bytes = (pse_bit_count + 7) / 8;
+ testing.expect(packed_slice_edge.bytes.len == pse_expected_bytes);
+ testing.expect(packed_slice_edge.bit_offset == 0);
+ }
+}
+
+test "PackedIntSlice accumulating bit offsets" {
+ //bit_offset is u3, so standard debugging asserts should catch
+ // anything
+ {
+ const PackedArray = PackedIntArray(u3, 16);
+ var packed_array = PackedArray(undefined);
+
+ var packed_slice = packed_array.slice(0, packed_array.len());
+ var i = usize(0);
+ while (i < packed_array.len() - 1) : (i += 1) {
+ packed_slice = packed_slice.slice(1, packed_slice.len());
+ }
+ }
+ {
+ const PackedArray = PackedIntArray(u11, 88);
+ var packed_array = PackedArray(undefined);
+
+ var packed_slice = packed_array.slice(0, packed_array.len());
+ var i = usize(0);
+ while (i < packed_array.len() - 1) : (i += 1) {
+ packed_slice = packed_slice.slice(1, packed_slice.len());
+ }
+ }
+}
+
+//@NOTE: As I do not have a big endian system to test this on,
+// big endian values were not tested
+test "PackedInt(Array/Slice) sliceCast" {
+ const PackedArray = PackedIntArray(u1, 16);
+ var packed_array = PackedArray.init([]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
+ const packed_slice_cast_2 = packed_array.sliceCast(u2);
+ const packed_slice_cast_4 = packed_slice_cast_2.sliceCast(u4);
+ var packed_slice_cast_9 = packed_array.slice(0, (packed_array.len() / 9) * 9).sliceCast(u9);
+ const packed_slice_cast_3 = packed_slice_cast_9.sliceCast(u3);
+
+ var i = usize(0);
+ while (i < packed_slice_cast_2.len()) : (i += 1) {
+ const val = switch (builtin.endian) {
+ .Big => 0b01,
+ .Little => 0b10,
+ };
+ testing.expect(packed_slice_cast_2.get(i) == val);
+ }
+ i = 0;
+ while (i < packed_slice_cast_4.len()) : (i += 1) {
+ const val = switch (builtin.endian) {
+ .Big => 0b0101,
+ .Little => 0b1010,
+ };
+ testing.expect(packed_slice_cast_4.get(i) == val);
+ }
+ i = 0;
+ while (i < packed_slice_cast_9.len()) : (i += 1) {
+ const val = 0b010101010;
+ testing.expect(packed_slice_cast_9.get(i) == val);
+ packed_slice_cast_9.set(i, 0b111000111);
+ }
+ i = 0;
+ while (i < packed_slice_cast_3.len()) : (i += 1) {
+ const val = switch (builtin.endian) {
+ .Big => if (i % 2 == 0) u3(0b111) else u3(0b000),
+ .Little => if (i % 2 == 0) u3(0b111) else u3(0b000),
+ };
+ testing.expect(packed_slice_cast_3.get(i) == val);
+ }
+}
+
+test "PackedInt(Array/Slice)Endian" {
+ {
+ const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8);
+ var packed_array_be = PackedArrayBe.init([]u4{
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ });
+ testing.expect(packed_array_be.bytes[0] == 0b00000001);
+ testing.expect(packed_array_be.bytes[1] == 0b00100011);
+
+ var i = usize(0);
+ while (i < packed_array_be.len()) : (i += 1) {
+ testing.expect(packed_array_be.get(i) == i);
+ }
+
+ var packed_slice_le = packed_array_be.sliceCastEndian(u4, .Little);
+ i = 0;
+ while (i < packed_slice_le.len()) : (i += 1) {
+ const val = if (i % 2 == 0) i + 1 else i - 1;
+ testing.expect(packed_slice_le.get(i) == val);
+ }
+
+ var packed_slice_le_shift = packed_array_be.slice(1, 5).sliceCastEndian(u4, .Little);
+ i = 0;
+ while (i < packed_slice_le_shift.len()) : (i += 1) {
+ const val = if (i % 2 == 0) i else i + 2;
+ testing.expect(packed_slice_le_shift.get(i) == val);
+ }
+ }
+
+ {
+ const PackedArrayBe = PackedIntArrayEndian(u11, .Big, 8);
+ var packed_array_be = PackedArrayBe.init([]u11{
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ });
+ testing.expect(packed_array_be.bytes[0] == 0b00000000);
+ testing.expect(packed_array_be.bytes[1] == 0b00000000);
+ testing.expect(packed_array_be.bytes[2] == 0b00000100);
+ testing.expect(packed_array_be.bytes[3] == 0b00000001);
+ testing.expect(packed_array_be.bytes[4] == 0b00000000);
+
+ var i = usize(0);
+ while (i < packed_array_be.len()) : (i += 1) {
+ testing.expect(packed_array_be.get(i) == i);
+ }
+
+ var packed_slice_le = packed_array_be.sliceCastEndian(u11, .Little);
+ testing.expect(packed_slice_le.get(0) == 0b00000000000);
+ testing.expect(packed_slice_le.get(1) == 0b00010000000);
+ testing.expect(packed_slice_le.get(2) == 0b00000000100);
+ testing.expect(packed_slice_le.get(3) == 0b00000000000);
+ testing.expect(packed_slice_le.get(4) == 0b00010000011);
+ testing.expect(packed_slice_le.get(5) == 0b00000000010);
+ testing.expect(packed_slice_le.get(6) == 0b10000010000);
+ testing.expect(packed_slice_le.get(7) == 0b00000111001);
+
+ var packed_slice_le_shift = packed_array_be.slice(1, 5).sliceCastEndian(u11, .Little);
+ testing.expect(packed_slice_le_shift.get(0) == 0b00010000000);
+ testing.expect(packed_slice_le_shift.get(1) == 0b00000000100);
+ testing.expect(packed_slice_le_shift.get(2) == 0b00000000000);
+ testing.expect(packed_slice_le_shift.get(3) == 0b00010000011);
+ }
+}
+
+//@NOTE: Need to manually update this list as more posix os's get
+// added to DirectAllocator. Windows can be added too when DirectAllocator
+// switches to VirtualAlloc.
+
+//These tests prove we aren't accidentally accessing memory past
+// the end of the array/slice by placing it at the end of a page
+// and reading the last element. The assumption is that the page
+// after this one is not mapped and will cause a segfault if we
+// don't account for the bounds.
+test "PackedIntArray at end of available memory" {
+ switch (builtin.os) {
+ .linux, .macosx, .ios, .freebsd, .netbsd => {},
+ else => return,
+ }
+ const PackedArray = PackedIntArray(u3, 8);
+
+ const Padded = struct {
+ _: [std.os.page_size - @sizeOf(PackedArray)]u8,
+ p: PackedArray,
+ };
+
+ var da = std.heap.DirectAllocator.init();
+ const allocator = &da.allocator;
+
+ var pad = try allocator.create(Padded);
+ defer allocator.destroy(pad);
+ pad.p.set(7, std.math.maxInt(u3));
+}
+
+test "PackedIntSlice at end of available memory" {
+ switch (builtin.os) {
+ .linux, .macosx, .ios, .freebsd, .netbsd => {},
+ else => return,
+ }
+ const PackedSlice = PackedIntSlice(u11);
+
+ var da = std.heap.DirectAllocator.init();
+ const allocator = &da.allocator;
+
+ var page = try allocator.alloc(u8, std.os.page_size);
+ defer allocator.free(page);
+
+ var p = PackedSlice.init(page[std.os.page_size - 2 ..], 1);
+ p.set(0, std.math.maxInt(u11));
+}
diff --git a/std/pdb.zig b/std/pdb.zig
index 2b02a84871..043be2bcf4 100644
--- a/std/pdb.zig
+++ b/std/pdb.zig
@@ -588,7 +588,7 @@ const SuperBlock = packed struct {
const MsfStream = struct {
in_file: os.File,
- pos: usize,
+ pos: u64,
blocks: []u32,
block_size: u32,
@@ -598,7 +598,7 @@ const MsfStream = struct {
pub const Error = @typeOf(read).ReturnType.ErrorSet;
pub const Stream = io.InStream(Error);
- fn init(block_size: u32, block_count: u32, pos: usize, file: os.File, allocator: *mem.Allocator) !MsfStream {
+ fn init(block_size: u32, block_count: u32, pos: u64, file: os.File, allocator: *mem.Allocator) !MsfStream {
var stream = MsfStream{
.in_file = file,
.pos = 0,
@@ -660,23 +660,24 @@ const MsfStream = struct {
return size;
}
- fn seekForward(self: *MsfStream, len: usize) !void {
+ // XXX: The `len` parameter should be signed
+ fn seekForward(self: *MsfStream, len: u64) !void {
self.pos += len;
if (self.pos >= self.blocks.len * self.block_size)
return error.EOF;
}
- fn seekTo(self: *MsfStream, len: usize) !void {
+ fn seekTo(self: *MsfStream, len: u64) !void {
self.pos = len;
if (self.pos >= self.blocks.len * self.block_size)
return error.EOF;
}
- fn getSize(self: *const MsfStream) usize {
+ fn getSize(self: *const MsfStream) u64 {
return self.blocks.len * self.block_size;
}
- fn getFilePos(self: MsfStream) usize {
+ fn getFilePos(self: MsfStream) u64 {
const block_id = self.pos / self.block_size;
const block = self.blocks[block_id];
const offset = self.pos % self.block_size;
diff --git a/std/rand.zig b/std/rand.zig
index a2fdfed6fd..4a6563f65a 100644
--- a/std/rand.zig
+++ b/std/rand.zig
@@ -768,10 +768,10 @@ pub const Isaac64 = struct {
const x = self.m[base + m1];
self.a = mix +% self.m[base + m2];
- const y = self.a +% self.b +% self.m[(x >> 3) % self.m.len];
+ const y = self.a +% self.b +% self.m[@intCast(usize, (x >> 3) % self.m.len)];
self.m[base + m1] = y;
- self.b = x +% self.m[(y >> 11) % self.m.len];
+ self.b = x +% self.m[@intCast(usize, (y >> 11) % self.m.len)];
self.r[self.r.len - 1 - base - m1] = self.b;
}
diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig
index 32f913a5b0..e6505c836b 100644
--- a/std/special/bootstrap.zig
+++ b/std/special/bootstrap.zig
@@ -20,6 +20,10 @@ comptime {
}
nakedcc fn _start() noreturn {
+ if (builtin.os == builtin.Os.wasi) {
+ std.os.wasi.proc_exit(callMain());
+ }
+
switch (builtin.arch) {
builtin.Arch.x86_64 => {
argc_ptr = asm ("lea (%%rsp), %[argc]"
@@ -63,24 +67,19 @@ fn posixCallMainAndExit() noreturn {
var envp_count: usize = 0;
while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count];
+
if (builtin.os == builtin.Os.linux) {
- // Scan auxiliary vector.
+ // Find the beginning of the auxiliary vector
const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
std.os.linux_elf_aux_maybe = auxv;
- var i: usize = 0;
- var at_phdr: usize = 0;
- var at_phnum: usize = 0;
- var at_phent: usize = 0;
- while (auxv[i].a_un.a_val != 0) : (i += 1) {
- switch (auxv[i].a_type) {
- std.elf.AT_PAGESZ => assert(auxv[i].a_un.a_val == std.os.page_size),
- std.elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
- std.elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
- std.elf.AT_PHENT => at_phent = auxv[i].a_un.a_val,
- else => {},
- }
+ // Initialize the TLS area
+ std.os.linux.tls.initTLS();
+
+ if (std.os.linux.tls.tls_image) |tls_img| {
+ const tls_addr = std.os.linux.tls.allocateTLS(tls_img.alloc_size);
+ const tp = std.os.linux.tls.copyTLS(tls_addr);
+ std.os.linux.tls.setThreadPointer(tp);
}
- if (!builtin.single_threaded) linuxInitializeThreadLocalStorage(at_phdr, at_phnum, at_phent);
}
std.os.posix.exit(callMainWithArgs(argc, argv, envp));
@@ -136,50 +135,3 @@ inline fn callMain() u8 {
const main_thread_tls_align = 32;
var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64;
-
-fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent: usize) void {
- var phdr_addr = at_phdr;
- var n = at_phnum;
- var base: usize = 0;
- while (n != 0) : ({
- n -= 1;
- phdr_addr += at_phent;
- }) {
- const phdr = @intToPtr(*std.elf.Phdr, phdr_addr);
- // TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917
- switch (phdr.p_type) {
- std.elf.PT_PHDR => base = at_phdr - phdr.p_vaddr,
- std.elf.PT_TLS => std.os.linux_tls_phdr = phdr,
- else => continue,
- }
- }
- const tls_phdr = std.os.linux_tls_phdr orelse return;
- std.os.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr);
- const end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz;
- const max_end_addr = @ptrToInt(&main_thread_tls_bytes) + main_thread_tls_bytes.len;
- assert(max_end_addr >= end_addr + @sizeOf(usize)); // not enough preallocated Thread Local Storage
- assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough
- @memcpy(&main_thread_tls_bytes, std.os.linux_tls_img_src, tls_phdr.p_filesz);
- const end_ptr = @intToPtr(*usize, end_addr);
- end_ptr.* = end_addr;
- linuxSetThreadArea(end_addr);
-}
-
-fn linuxSetThreadArea(addr: usize) void {
- switch (builtin.arch) {
- builtin.Arch.x86_64 => {
- const ARCH_SET_FS = 0x1002;
- const rc = std.os.linux.syscall2(std.os.linux.SYS_arch_prctl, ARCH_SET_FS, addr);
- // acrh_prctl is documented to never fail
- assert(rc == 0);
- },
- builtin.Arch.aarch64 => {
- asm volatile (
- \\ msr tpidr_el0,x0
- \\ mov w0,#0
- \\ ret
- );
- },
- else => @compileError("Unsupported architecture"),
- }
-}
diff --git a/std/special/build_runner.zig b/std/special/build_runner.zig
index 56cfe3bcb5..dfc3838577 100644
--- a/std/special/build_runner.zig
+++ b/std/special/build_runner.zig
@@ -94,6 +94,16 @@ pub fn main() !void {
return usageAndErr(&builder, false, try stderr_stream);
});
builder.addSearchPrefix(search_prefix);
+ } else if (mem.eql(u8, arg, "--override-std-dir")) {
+ builder.override_std_dir = try unwrapArg(arg_it.next(allocator) orelse {
+ warn("Expected argument after --override-std-dir\n\n");
+ return usageAndErr(&builder, false, try stderr_stream);
+ });
+ } else if (mem.eql(u8, arg, "--override-lib-dir")) {
+ builder.override_lib_dir = try unwrapArg(arg_it.next(allocator) orelse {
+ warn("Expected argument after --override-lib-dir\n\n");
+ return usageAndErr(&builder, false, try stderr_stream);
+ });
} else if (mem.eql(u8, arg, "--verbose-tokenize")) {
builder.verbose_tokenize = true;
} else if (mem.eql(u8, arg, "--verbose-ast")) {
@@ -187,15 +197,17 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
try out_stream.write(
\\
\\Advanced Options:
- \\ --build-file [file] Override path to build.zig
- \\ --cache-dir [path] Override path to zig cache directory
- \\ --verbose-tokenize Enable compiler debug output for tokenization
- \\ --verbose-ast Enable compiler debug output for parsing into an AST
- \\ --verbose-link Enable compiler debug output for linking
- \\ --verbose-ir Enable compiler debug output for Zig IR
- \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
- \\ --verbose-cimport Enable compiler debug output for C imports
- \\ --verbose-cc Enable compiler debug output for C compilation
+ \\ --build-file [file] Override path to build.zig
+ \\ --cache-dir [path] Override path to zig cache directory
+ \\ --override-std-dir [arg] Override path to Zig standard library
+ \\ --override-lib-dir [arg] Override path to Zig lib directory
+ \\ --verbose-tokenize Enable compiler debug output for tokenization
+ \\ --verbose-ast Enable compiler debug output for parsing into an AST
+ \\ --verbose-link Enable compiler debug output for linking
+ \\ --verbose-ir Enable compiler debug output for Zig IR
+ \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
+ \\ --verbose-cimport Enable compiler debug output for C imports
+ \\ --verbose-cc Enable compiler debug output for C compilation
\\
);
}
diff --git a/std/special/compiler_rt.zig b/std/special/compiler_rt.zig
index e8d522eea1..b4df7aea5f 100644
--- a/std/special/compiler_rt.zig
+++ b/std/special/compiler_rt.zig
@@ -5,20 +5,47 @@ comptime {
const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak;
const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong;
+ switch (builtin.arch) {
+ .i386, .x86_64 => @export("__zig_probe_stack", @import("compiler_rt/stack_probe.zig").zig_probe_stack, linkage),
+ else => {},
+ }
+
+ @export("__lesf2", @import("compiler_rt/comparesf2.zig").__lesf2, linkage);
+ @export("__ledf2", @import("compiler_rt/comparedf2.zig").__ledf2, linkage);
@export("__letf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
+
+ @export("__gesf2", @import("compiler_rt/comparesf2.zig").__gesf2, linkage);
+ @export("__gedf2", @import("compiler_rt/comparedf2.zig").__gedf2, linkage);
@export("__getf2", @import("compiler_rt/comparetf2.zig").__getf2, linkage);
if (!is_test) {
// only create these aliases when not testing
+ @export("__cmpsf2", @import("compiler_rt/comparesf2.zig").__lesf2, linkage);
+ @export("__cmpdf2", @import("compiler_rt/comparedf2.zig").__ledf2, linkage);
@export("__cmptf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
+
+ @export("__eqsf2", @import("compiler_rt/comparesf2.zig").__eqsf2, linkage);
+ @export("__eqdf2", @import("compiler_rt/comparedf2.zig").__eqdf2, linkage);
@export("__eqtf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
+
+ @export("__ltsf2", @import("compiler_rt/comparesf2.zig").__ltsf2, linkage);
+ @export("__ltdf2", @import("compiler_rt/comparedf2.zig").__ltdf2, linkage);
@export("__lttf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
+
+ @export("__nesf2", @import("compiler_rt/comparesf2.zig").__nesf2, linkage);
+ @export("__nedf2", @import("compiler_rt/comparedf2.zig").__nedf2, linkage);
@export("__netf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
+
+ @export("__gtsf2", @import("compiler_rt/comparesf2.zig").__gtsf2, linkage);
+ @export("__gtdf2", @import("compiler_rt/comparedf2.zig").__gtdf2, linkage);
@export("__gttf2", @import("compiler_rt/comparetf2.zig").__getf2, linkage);
+
@export("__gnu_h2f_ieee", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage);
@export("__gnu_f2h_ieee", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage);
}
+ @export("__unordsf2", @import("compiler_rt/comparesf2.zig").__unordsf2, linkage);
+ @export("__unorddf2", @import("compiler_rt/comparedf2.zig").__unorddf2, linkage);
@export("__unordtf2", @import("compiler_rt/comparetf2.zig").__unordtf2, linkage);
@export("__addsf3", @import("compiler_rt/addXf3.zig").__addsf3, linkage);
@@ -35,6 +62,17 @@ comptime {
@export("__divsf3", @import("compiler_rt/divsf3.zig").__divsf3, linkage);
@export("__divdf3", @import("compiler_rt/divdf3.zig").__divdf3, linkage);
+ @export("__ashlti3", @import("compiler_rt/ashlti3.zig").__ashlti3, linkage);
+ @export("__lshrti3", @import("compiler_rt/lshrti3.zig").__lshrti3, linkage);
+ @export("__ashrti3", @import("compiler_rt/ashrti3.zig").__ashrti3, linkage);
+
+ @export("__floatsidf", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage);
+ @export("__floatsisf", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage);
+ @export("__floatdidf", @import("compiler_rt/floatdidf.zig").__floatdidf, linkage);
+ @export("__floatsitf", @import("compiler_rt/floatsiXf.zig").__floatsitf, linkage);
+ @export("__floatunsidf", @import("compiler_rt/floatunsidf.zig").__floatunsidf, linkage);
+ @export("__floatundidf", @import("compiler_rt/floatundidf.zig").__floatundidf, linkage);
+
@export("__floattitf", @import("compiler_rt/floattitf.zig").__floattitf, linkage);
@export("__floattidf", @import("compiler_rt/floattidf.zig").__floattidf, linkage);
@export("__floattisf", @import("compiler_rt/floattisf.zig").__floattisf, linkage);
@@ -55,6 +93,10 @@ comptime {
@export("__trunctfdf2", @import("compiler_rt/truncXfYf2.zig").__trunctfdf2, linkage);
@export("__trunctfsf2", @import("compiler_rt/truncXfYf2.zig").__trunctfsf2, linkage);
+ @export("__truncdfsf2", @import("compiler_rt/truncXfYf2.zig").__truncdfsf2, linkage);
+
+ @export("__extendsfdf2", @import("compiler_rt/extendXfYf2.zig").__extendsfdf2, linkage);
+
@export("__fixunssfsi", @import("compiler_rt/fixunssfsi.zig").__fixunssfsi, linkage);
@export("__fixunssfdi", @import("compiler_rt/fixunssfdi.zig").__fixunssfdi, linkage);
@export("__fixunssfti", @import("compiler_rt/fixunssfti.zig").__fixunssfti, linkage);
@@ -80,18 +122,33 @@ comptime {
@export("__udivmoddi4", @import("compiler_rt/udivmoddi4.zig").__udivmoddi4, linkage);
@export("__popcountdi2", @import("compiler_rt/popcountdi2.zig").__popcountdi2, linkage);
+ @export("__divmoddi4", __divmoddi4, linkage);
+ @export("__divsi3", __divsi3, linkage);
+ @export("__divdi3", __divdi3, linkage);
@export("__udivsi3", __udivsi3, linkage);
@export("__udivdi3", __udivdi3, linkage);
+ @export("__modsi3", __modsi3, linkage);
+ @export("__moddi3", __moddi3, linkage);
+ @export("__umodsi3", __umodsi3, linkage);
@export("__umoddi3", __umoddi3, linkage);
+ @export("__divmodsi4", __divmodsi4, linkage);
@export("__udivmodsi4", __udivmodsi4, linkage);
@export("__negsf2", @import("compiler_rt/negXf2.zig").__negsf2, linkage);
@export("__negdf2", @import("compiler_rt/negXf2.zig").__negdf2, linkage);
if (is_arm_arch and !is_arm_64) {
+ @export("__aeabi_unwind_cpp_pr0", __aeabi_unwind_cpp_pr0, strong_linkage);
+ @export("__aeabi_unwind_cpp_pr1", __aeabi_unwind_cpp_pr1, linkage);
+ @export("__aeabi_unwind_cpp_pr2", __aeabi_unwind_cpp_pr2, linkage);
+
+ @export("__aeabi_ldivmod", __aeabi_ldivmod, linkage);
@export("__aeabi_uldivmod", __aeabi_uldivmod, linkage);
- @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);
+
+ @export("__aeabi_idiv", __divsi3, linkage);
+ @export("__aeabi_idivmod", __aeabi_idivmod, linkage);
@export("__aeabi_uidiv", __udivsi3, linkage);
+ @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);
@export("__aeabi_memcpy", __aeabi_memcpy, linkage);
@export("__aeabi_memcpy4", __aeabi_memcpy, linkage);
@@ -113,6 +170,12 @@ comptime {
@export("__aeabi_memcmp4", __aeabi_memcmp, linkage);
@export("__aeabi_memcmp8", __aeabi_memcmp, linkage);
+ @export("__aeabi_f2d", @import("compiler_rt/extendXfYf2.zig").__extendsfdf2, linkage);
+ @export("__aeabi_i2d", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage);
+ @export("__aeabi_l2d", @import("compiler_rt/floatdidf.zig").__floatdidf, linkage);
+ @export("__aeabi_ui2d", @import("compiler_rt/floatunsidf.zig").__floatunsidf, linkage);
+ @export("__aeabi_ul2d", @import("compiler_rt/floatundidf.zig").__floatundidf, linkage);
+
@export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage);
@export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage);
@@ -132,6 +195,9 @@ comptime {
@export("__aeabi_h2f", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage);
@export("__aeabi_f2h", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage);
+ @export("__aeabi_i2f", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage);
+ @export("__aeabi_d2f", @import("compiler_rt/truncXfYf2.zig").__truncdfsf2, linkage);
+
@export("__aeabi_fadd", @import("compiler_rt/addXf3.zig").__addsf3, linkage);
@export("__aeabi_dadd", @import("compiler_rt/addXf3.zig").__adddf3, linkage);
@export("__aeabi_fsub", @import("compiler_rt/addXf3.zig").__subsf3, linkage);
@@ -144,26 +210,41 @@ comptime {
@export("__aeabi_fdiv", @import("compiler_rt/divsf3.zig").__divsf3, linkage);
@export("__aeabi_ddiv", @import("compiler_rt/divdf3.zig").__divdf3, linkage);
+
+ @export("__aeabi_fcmpeq", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpeq, linkage);
+ @export("__aeabi_fcmplt", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmplt, linkage);
+ @export("__aeabi_fcmple", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmple, linkage);
+ @export("__aeabi_fcmpge", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpge, linkage);
+ @export("__aeabi_fcmpgt", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpgt, linkage);
+ @export("__aeabi_fcmpun", @import("compiler_rt/comparesf2.zig").__unordsf2, linkage);
+
+ @export("__aeabi_dcmpeq", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpeq, linkage);
+ @export("__aeabi_dcmplt", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmplt, linkage);
+ @export("__aeabi_dcmple", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmple, linkage);
+ @export("__aeabi_dcmpge", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpge, linkage);
+ @export("__aeabi_dcmpgt", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpgt, linkage);
+ @export("__aeabi_dcmpun", @import("compiler_rt/comparedf2.zig").__unorddf2, linkage);
}
if (builtin.os == builtin.Os.windows) {
+ if (!builtin.link_libc) {
+ @export("_chkstk", @import("compiler_rt/stack_probe.zig")._chkstk, strong_linkage);
+ @export("__chkstk", @import("compiler_rt/stack_probe.zig").__chkstk, strong_linkage);
+ @export("___chkstk", @import("compiler_rt/stack_probe.zig").___chkstk, strong_linkage);
+ @export("__chkstk_ms", @import("compiler_rt/stack_probe.zig").__chkstk_ms, strong_linkage);
+ @export("___chkstk_ms", @import("compiler_rt/stack_probe.zig").___chkstk_ms, strong_linkage);
+ }
+
switch (builtin.arch) {
builtin.Arch.i386 => {
- if (!builtin.link_libc) {
- @export("_chkstk", _chkstk, strong_linkage);
- @export("__chkstk_ms", __chkstk_ms, linkage);
- }
@export("_aulldiv", @import("compiler_rt/aulldiv.zig")._aulldiv, strong_linkage);
@export("_aullrem", @import("compiler_rt/aullrem.zig")._aullrem, strong_linkage);
},
builtin.Arch.x86_64 => {
- if (!builtin.link_libc) {
- @export("__chkstk", __chkstk, strong_linkage);
- @export("___chkstk_ms", ___chkstk_ms, linkage);
- }
+ // The "ti" functions must use @Vector(2, u64) parameter types to adhere to the ABI
+ // that LLVM expects compiler-rt to have.
@export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage);
@export("__modti3", @import("compiler_rt/modti3.zig").__modti3_windows_x86_64, linkage);
@export("__multi3", @import("compiler_rt/multi3.zig").__multi3_windows_x86_64, linkage);
- @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4_windows_x86_64, linkage);
@export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64, linkage);
@export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64, linkage);
@export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64, linkage);
@@ -174,11 +255,12 @@ comptime {
@export("__divti3", @import("compiler_rt/divti3.zig").__divti3, linkage);
@export("__modti3", @import("compiler_rt/modti3.zig").__modti3, linkage);
@export("__multi3", @import("compiler_rt/multi3.zig").__multi3, linkage);
- @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4, linkage);
@export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3, linkage);
@export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4, linkage);
@export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3, linkage);
}
+ @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4, linkage);
+ @export("__mulodi4", @import("compiler_rt/mulodi4.zig").__mulodi4, linkage);
}
const std = @import("std");
@@ -198,15 +280,49 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
}
}
-pub fn setXmm0(comptime T: type, value: T) void {
- comptime assert(builtin.arch == builtin.Arch.x86_64);
- const aligned_value: T align(16) = value;
- asm volatile (
- \\movaps (%[ptr]), %%xmm0
- :
- : [ptr] "r" (&aligned_value)
- : "xmm0"
- );
+extern fn __aeabi_unwind_cpp_pr0() void {
+ unreachable;
+}
+extern fn __aeabi_unwind_cpp_pr1() void {
+ unreachable;
+}
+extern fn __aeabi_unwind_cpp_pr2() void {
+ unreachable;
+}
+
+extern fn __divmoddi4(a: i64, b: i64, rem: *i64) i64 {
+ @setRuntimeSafety(is_test);
+
+ const d = __divdi3(a, b);
+ rem.* = a -% (d *% b);
+ return d;
+}
+
+extern fn __divdi3(a: i64, b: i64) i64 {
+ @setRuntimeSafety(is_test);
+
+ // Set aside the sign of the quotient.
+ const sign = @bitCast(u64, (a ^ b) >> 63);
+ // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
+ const abs_a = (a ^ (a >> 63)) -% (a >> 63);
+ const abs_b = (b ^ (b >> 63)) -% (b >> 63);
+ // Unsigned division
+ const res = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), null);
+ // Apply sign of quotient to result and return.
+ return @bitCast(i64, (res ^ sign) -% sign);
+}
+
+extern fn __moddi3(a: i64, b: i64) i64 {
+ @setRuntimeSafety(is_test);
+
+ // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
+ const abs_a = (a ^ (a >> 63)) -% (a >> 63);
+ const abs_b = (b ^ (b >> 63)) -% (b >> 63);
+ // Unsigned division
+ var r: u64 = undefined;
+ _ = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), &r);
+ // Apply the sign of the dividend and return.
+ return (@bitCast(i64, r) ^ (a >> 63)) -% (a >> 63);
}
extern fn __udivdi3(a: u64, b: u64) u64 {
@@ -222,14 +338,35 @@ extern fn __umoddi3(a: u64, b: u64) u64 {
return r;
}
-const AeabiUlDivModResult = extern struct {
- quot: u64,
- rem: u64,
-};
-extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult {
+extern fn __aeabi_uidivmod(n: u32, d: u32) extern struct{q: u32, r: u32} {
+ @setRuntimeSafety(is_test);
+
+ var result: @typeOf(__aeabi_uidivmod).ReturnType = undefined;
+ result.q = __udivmodsi4(n, d, &result.r);
+ return result;
+}
+
+extern fn __aeabi_uldivmod(n: u64, d: u64) extern struct{q: u64, r: u64} {
+ @setRuntimeSafety(is_test);
+
+ var result: @typeOf(__aeabi_uldivmod).ReturnType = undefined;
+ result.q = __udivmoddi4(n, d, &result.r);
+ return result;
+}
+
+extern fn __aeabi_idivmod(n: i32, d: i32) extern struct{q: i32, r: i32} {
+ @setRuntimeSafety(is_test);
+
+ var result: @typeOf(__aeabi_idivmod).ReturnType = undefined;
+ result.q = __divmodsi4(n, d, &result.r);
+ return result;
+}
+
+extern fn __aeabi_ldivmod(n: i64, d: i64) extern struct{q: i64, r:i64} {
@setRuntimeSafety(is_test);
- var result: AeabiUlDivModResult = undefined;
- result.quot = __udivmoddi4(numerator, denominator, &result.rem);
+
+ var result: @typeOf(__aeabi_ldivmod).ReturnType = undefined;
+ result.q = __divmoddi4(n, d, &result.r);
return result;
}
@@ -253,29 +390,74 @@ const is_arm_arch = switch (builtin.arch) {
const is_arm_32 = is_arm_arch and !is_arm_64;
-const use_thumb_1 = is_arm_32 and switch (builtin.arch.arm) {
- builtin.Arch.Arm32.v6,
- builtin.Arch.Arm32.v6m,
- builtin.Arch.Arm32.v6k,
- builtin.Arch.Arm32.v6t2,
- => true,
- else => false,
-};
+const use_thumb_1 = usesThumb1(builtin.arch);
+
+fn usesThumb1(arch: builtin.Arch) bool {
+ return switch (arch) {
+ .arm => switch (arch.arm) {
+ .v6m => true,
+ else => false,
+ },
+ .armeb => switch (arch.armeb) {
+ .v6m => true,
+ else => false,
+ },
+ .thumb => switch (arch.thumb) {
+ .v5,
+ .v5te,
+ .v4t,
+ .v6,
+ .v6m,
+ .v6k,
+ => true,
+ else => false,
+ },
+ .thumbeb => switch (arch.thumbeb) {
+ .v5,
+ .v5te,
+ .v4t,
+ .v6,
+ .v6m,
+ .v6k,
+ => true,
+ else => false,
+ },
+ else => false,
+ };
+}
-nakedcc fn __aeabi_uidivmod() void {
- @setRuntimeSafety(false);
- asm volatile (
- \\ push { lr }
- \\ sub sp, sp, #4
- \\ mov r2, sp
- \\ bl __udivmodsi4
- \\ ldr r1, [sp]
- \\ add sp, sp, #4
- \\ pop { pc }
- :
- :
- : "r2", "r1"
- );
+test "usesThumb1" {
+ testing.expect(usesThumb1(builtin.Arch{ .arm = .v6m }));
+ testing.expect(!usesThumb1(builtin.Arch{ .arm = .v5 }));
+ //etc.
+
+ testing.expect(usesThumb1(builtin.Arch{ .armeb = .v6m }));
+ testing.expect(!usesThumb1(builtin.Arch{ .armeb = .v5 }));
+ //etc.
+
+ testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5 }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5te }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumb = .v4t }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6 }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6k }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6m }));
+ testing.expect(!usesThumb1(builtin.Arch{ .thumb = .v6t2 }));
+ //etc.
+
+ testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v5 }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v5te }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v4t }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6 }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6k }));
+ testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6m }));
+ testing.expect(!usesThumb1(builtin.Arch{ .thumbeb = .v6t2 }));
+ //etc.
+
+ testing.expect(!usesThumb1(builtin.Arch{ .aarch64 = .v8 }));
+ testing.expect(!usesThumb1(builtin.Arch{ .aarch64_be = .v8 }));
+ testing.expect(!usesThumb1(builtin.Arch.x86_64));
+ testing.expect(!usesThumb1(builtin.Arch.riscv32));
+ //etc.
}
nakedcc fn __aeabi_memcpy() noreturn {
@@ -368,107 +550,12 @@ nakedcc fn __aeabi_memcmp() noreturn {
unreachable;
}
-// _chkstk (_alloca) routine - probe stack between %esp and (%esp-%eax) in 4k increments,
-// then decrement %esp by %eax. Preserves all registers except %esp and flags.
-// This routine is windows specific
-// http://msdn.microsoft.com/en-us/library/ms648426.aspx
-nakedcc fn _chkstk() align(4) void {
- @setRuntimeSafety(false);
-
- asm volatile (
- \\ push %%ecx
- \\ push %%eax
- \\ cmp $0x1000,%%eax
- \\ lea 12(%%esp),%%ecx
- \\ jb 1f
- \\ 2:
- \\ sub $0x1000,%%ecx
- \\ test %%ecx,(%%ecx)
- \\ sub $0x1000,%%eax
- \\ cmp $0x1000,%%eax
- \\ ja 2b
- \\ 1:
- \\ sub %%eax,%%ecx
- \\ test %%ecx,(%%ecx)
- \\ pop %%eax
- \\ pop %%ecx
- \\ ret
- );
-}
-
-nakedcc fn __chkstk() align(4) void {
- @setRuntimeSafety(false);
-
- asm volatile (
- \\ push %%rcx
- \\ push %%rax
- \\ cmp $0x1000,%%rax
- \\ lea 24(%%rsp),%%rcx
- \\ jb 1f
- \\2:
- \\ sub $0x1000,%%rcx
- \\ test %%rcx,(%%rcx)
- \\ sub $0x1000,%%rax
- \\ cmp $0x1000,%%rax
- \\ ja 2b
- \\1:
- \\ sub %%rax,%%rcx
- \\ test %%rcx,(%%rcx)
- \\ pop %%rax
- \\ pop %%rcx
- \\ ret
- );
-}
-
-// _chkstk routine
-// This routine is windows specific
-// http://msdn.microsoft.com/en-us/library/ms648426.aspx
-nakedcc fn __chkstk_ms() align(4) void {
- @setRuntimeSafety(false);
-
- asm volatile (
- \\ push %%ecx
- \\ push %%eax
- \\ cmp $0x1000,%%eax
- \\ lea 12(%%esp),%%ecx
- \\ jb 1f
- \\ 2:
- \\ sub $0x1000,%%ecx
- \\ test %%ecx,(%%ecx)
- \\ sub $0x1000,%%eax
- \\ cmp $0x1000,%%eax
- \\ ja 2b
- \\ 1:
- \\ sub %%eax,%%ecx
- \\ test %%ecx,(%%ecx)
- \\ pop %%eax
- \\ pop %%ecx
- \\ ret
- );
-}
-
-nakedcc fn ___chkstk_ms() align(4) void {
- @setRuntimeSafety(false);
+extern fn __divmodsi4(a: i32, b: i32, rem: *i32) i32 {
+ @setRuntimeSafety(is_test);
- asm volatile (
- \\ push %%rcx
- \\ push %%rax
- \\ cmp $0x1000,%%rax
- \\ lea 24(%%rsp),%%rcx
- \\ jb 1f
- \\2:
- \\ sub $0x1000,%%rcx
- \\ test %%rcx,(%%rcx)
- \\ sub $0x1000,%%rax
- \\ cmp $0x1000,%%rax
- \\ ja 2b
- \\1:
- \\ sub %%rax,%%rcx
- \\ test %%rcx,(%%rcx)
- \\ pop %%rax
- \\ pop %%rcx
- \\ ret
- );
+ const d = __divsi3(a, b);
+ rem.* = a -% (d * b);
+ return d;
}
extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {
@@ -479,6 +566,20 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {
return d;
}
+extern fn __divsi3(n: i32, d: i32) i32 {
+ @setRuntimeSafety(is_test);
+
+ // Set aside the sign of the quotient.
+ const sign = @bitCast(u32, (n ^ d) >> 31);
+ // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
+ const abs_n = (n ^ (n >> 31)) -% (n >> 31);
+ const abs_d = (d ^ (d >> 31)) -% (d >> 31);
+ // abs(a) / abs(b)
+ const res = @bitCast(u32, abs_n) / @bitCast(u32, abs_d);
+ // Apply sign of quotient to result and return.
+ return @bitCast(i32, (res ^ sign) -% sign);
+}
+
extern fn __udivsi3(n: u32, d: u32) u32 {
@setRuntimeSafety(is_test);
@@ -520,6 +621,18 @@ extern fn __udivsi3(n: u32, d: u32) u32 {
return q;
}
+extern fn __modsi3(n: i32, d: i32) i32 {
+ @setRuntimeSafety(is_test);
+
+ return n -% __divsi3(n, d) *% d;
+}
+
+extern fn __umodsi3(n: u32, d: u32) u32 {
+ @setRuntimeSafety(is_test);
+
+ return n -% __udivsi3(n, d) *% d;
+}
+
test "test_umoddi3" {
test_one_umoddi3(0, 1, 0);
test_one_umoddi3(2, 1, 0);
@@ -1206,3 +1319,279 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void {
const q: u32 = __udivsi3(a, b);
testing.expect(q == expected_q);
}
+
+test "test_divsi3" {
+ const cases = [][3]i32{
+ []i32{ 0, 1, 0 },
+ []i32{ 0, -1, 0 },
+ []i32{ 2, 1, 2 },
+ []i32{ 2, -1, -2 },
+ []i32{ -2, 1, -2 },
+ []i32{ -2, -1, 2 },
+
+ []i32{ @bitCast(i32, u32(0x80000000)), 1, @bitCast(i32, u32(0x80000000)) },
+ []i32{ @bitCast(i32, u32(0x80000000)), -1, @bitCast(i32, u32(0x80000000)) },
+ []i32{ @bitCast(i32, u32(0x80000000)), -2, 0x40000000 },
+ []i32{ @bitCast(i32, u32(0x80000000)), 2, @bitCast(i32, u32(0xC0000000)) },
+ };
+
+ for (cases) |case| {
+ test_one_divsi3(case[0], case[1], case[2]);
+ }
+}
+
+fn test_one_divsi3(a: i32, b: i32, expected_q: i32) void {
+ const q: i32 = __divsi3(a, b);
+ testing.expect(q == expected_q);
+}
+
+test "test_divmodsi4" {
+ const cases = [][4]i32{
+ []i32{ 0, 1, 0, 0 },
+ []i32{ 0, -1, 0, 0 },
+ []i32{ 2, 1, 2, 0 },
+ []i32{ 2, -1, -2, 0 },
+ []i32{ -2, 1, -2, 0 },
+ []i32{ -2, -1, 2, 0 },
+ []i32{ 7, 5, 1, 2 },
+ []i32{ -7, 5, -1, -2 },
+ []i32{ 19, 5, 3, 4 },
+ []i32{ 19, -5, -3, 4 },
+
+ []i32{ @bitCast(i32, u32(0x80000000)), 8, @bitCast(i32, u32(0xf0000000)), 0 },
+ []i32{ @bitCast(i32, u32(0x80000007)), 8, @bitCast(i32, u32(0xf0000001)), -1 },
+ };
+
+ for (cases) |case| {
+ test_one_divmodsi4(case[0], case[1], case[2], case[3]);
+ }
+}
+
+fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) void {
+ var r: i32 = undefined;
+ const q: i32 = __divmodsi4(a, b, &r);
+ testing.expect(q == expected_q and r == expected_r);
+}
+
+test "test_divdi3" {
+ const cases = [][3]i64{
+ []i64{ 0, 1, 0 },
+ []i64{ 0, -1, 0 },
+ []i64{ 2, 1, 2 },
+ []i64{ 2, -1, -2 },
+ []i64{ -2, 1, -2 },
+ []i64{ -2, -1, 2 },
+
+ []i64{ @bitCast(i64, u64(0x8000000000000000)), 1, @bitCast(i64, u64(0x8000000000000000)) },
+ []i64{ @bitCast(i64, u64(0x8000000000000000)), -1, @bitCast(i64, u64(0x8000000000000000)) },
+ []i64{ @bitCast(i64, u64(0x8000000000000000)), -2, 0x4000000000000000 },
+ []i64{ @bitCast(i64, u64(0x8000000000000000)), 2, @bitCast(i64, u64(0xC000000000000000)) },
+ };
+
+ for (cases) |case| {
+ test_one_divdi3(case[0], case[1], case[2]);
+ }
+}
+
+fn test_one_divdi3(a: i64, b: i64, expected_q: i64) void {
+ const q: i64 = __divdi3(a, b);
+ testing.expect(q == expected_q);
+}
+
+test "test_moddi3" {
+ const cases = [][3]i64{
+ []i64{ 0, 1, 0 },
+ []i64{ 0, -1, 0 },
+ []i64{ 5, 3, 2 },
+ []i64{ 5, -3, 2 },
+ []i64{ -5, 3, -2 },
+ []i64{ -5, -3, -2 },
+
+ []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), 1, 0 },
+ []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), -1, 0 },
+ []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), 2, 0 },
+ []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), -2, 0 },
+ []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), 3, -2 },
+ []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), -3, -2 },
+ };
+
+ for (cases) |case| {
+ test_one_moddi3(case[0], case[1], case[2]);
+ }
+}
+
+fn test_one_moddi3(a: i64, b: i64, expected_r: i64) void {
+ const r: i64 = __moddi3(a, b);
+ testing.expect(r == expected_r);
+}
+
+test "test_modsi3" {
+ const cases = [][3]i32{
+ []i32{ 0, 1, 0 },
+ []i32{ 0, -1, 0 },
+ []i32{ 5, 3, 2 },
+ []i32{ 5, -3, 2 },
+ []i32{ -5, 3, -2 },
+ []i32{ -5, -3, -2 },
+ []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 1, 0x0 },
+ []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 2, 0x0 },
+ []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -2, 0x0 },
+ []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 3, -2 },
+ []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -3, -2 },
+ };
+
+ for (cases) |case| {
+ test_one_modsi3(case[0], case[1], case[2]);
+ }
+}
+
+fn test_one_modsi3(a: i32, b: i32, expected_r: i32) void {
+ const r: i32 = __modsi3(a, b);
+ testing.expect(r == expected_r);
+}
+
+test "test_umodsi3" {
+ const cases = [][3]u32{
+ []u32{ 0x00000000, 0x00000001, 0x00000000 },
+ []u32{ 0x00000000, 0x00000002, 0x00000000 },
+ []u32{ 0x00000000, 0x00000003, 0x00000000 },
+ []u32{ 0x00000000, 0x00000010, 0x00000000 },
+ []u32{ 0x00000000, 0x078644FA, 0x00000000 },
+ []u32{ 0x00000000, 0x0747AE14, 0x00000000 },
+ []u32{ 0x00000000, 0x7FFFFFFF, 0x00000000 },
+ []u32{ 0x00000000, 0x80000000, 0x00000000 },
+ []u32{ 0x00000000, 0xFFFFFFFD, 0x00000000 },
+ []u32{ 0x00000000, 0xFFFFFFFE, 0x00000000 },
+ []u32{ 0x00000000, 0xFFFFFFFF, 0x00000000 },
+ []u32{ 0x00000001, 0x00000001, 0x00000000 },
+ []u32{ 0x00000001, 0x00000002, 0x00000001 },
+ []u32{ 0x00000001, 0x00000003, 0x00000001 },
+ []u32{ 0x00000001, 0x00000010, 0x00000001 },
+ []u32{ 0x00000001, 0x078644FA, 0x00000001 },
+ []u32{ 0x00000001, 0x0747AE14, 0x00000001 },
+ []u32{ 0x00000001, 0x7FFFFFFF, 0x00000001 },
+ []u32{ 0x00000001, 0x80000000, 0x00000001 },
+ []u32{ 0x00000001, 0xFFFFFFFD, 0x00000001 },
+ []u32{ 0x00000001, 0xFFFFFFFE, 0x00000001 },
+ []u32{ 0x00000001, 0xFFFFFFFF, 0x00000001 },
+ []u32{ 0x00000002, 0x00000001, 0x00000000 },
+ []u32{ 0x00000002, 0x00000002, 0x00000000 },
+ []u32{ 0x00000002, 0x00000003, 0x00000002 },
+ []u32{ 0x00000002, 0x00000010, 0x00000002 },
+ []u32{ 0x00000002, 0x078644FA, 0x00000002 },
+ []u32{ 0x00000002, 0x0747AE14, 0x00000002 },
+ []u32{ 0x00000002, 0x7FFFFFFF, 0x00000002 },
+ []u32{ 0x00000002, 0x80000000, 0x00000002 },
+ []u32{ 0x00000002, 0xFFFFFFFD, 0x00000002 },
+ []u32{ 0x00000002, 0xFFFFFFFE, 0x00000002 },
+ []u32{ 0x00000002, 0xFFFFFFFF, 0x00000002 },
+ []u32{ 0x00000003, 0x00000001, 0x00000000 },
+ []u32{ 0x00000003, 0x00000002, 0x00000001 },
+ []u32{ 0x00000003, 0x00000003, 0x00000000 },
+ []u32{ 0x00000003, 0x00000010, 0x00000003 },
+ []u32{ 0x00000003, 0x078644FA, 0x00000003 },
+ []u32{ 0x00000003, 0x0747AE14, 0x00000003 },
+ []u32{ 0x00000003, 0x7FFFFFFF, 0x00000003 },
+ []u32{ 0x00000003, 0x80000000, 0x00000003 },
+ []u32{ 0x00000003, 0xFFFFFFFD, 0x00000003 },
+ []u32{ 0x00000003, 0xFFFFFFFE, 0x00000003 },
+ []u32{ 0x00000003, 0xFFFFFFFF, 0x00000003 },
+ []u32{ 0x00000010, 0x00000001, 0x00000000 },
+ []u32{ 0x00000010, 0x00000002, 0x00000000 },
+ []u32{ 0x00000010, 0x00000003, 0x00000001 },
+ []u32{ 0x00000010, 0x00000010, 0x00000000 },
+ []u32{ 0x00000010, 0x078644FA, 0x00000010 },
+ []u32{ 0x00000010, 0x0747AE14, 0x00000010 },
+ []u32{ 0x00000010, 0x7FFFFFFF, 0x00000010 },
+ []u32{ 0x00000010, 0x80000000, 0x00000010 },
+ []u32{ 0x00000010, 0xFFFFFFFD, 0x00000010 },
+ []u32{ 0x00000010, 0xFFFFFFFE, 0x00000010 },
+ []u32{ 0x00000010, 0xFFFFFFFF, 0x00000010 },
+ []u32{ 0x078644FA, 0x00000001, 0x00000000 },
+ []u32{ 0x078644FA, 0x00000002, 0x00000000 },
+ []u32{ 0x078644FA, 0x00000003, 0x00000000 },
+ []u32{ 0x078644FA, 0x00000010, 0x0000000A },
+ []u32{ 0x078644FA, 0x078644FA, 0x00000000 },
+ []u32{ 0x078644FA, 0x0747AE14, 0x003E96E6 },
+ []u32{ 0x078644FA, 0x7FFFFFFF, 0x078644FA },
+ []u32{ 0x078644FA, 0x80000000, 0x078644FA },
+ []u32{ 0x078644FA, 0xFFFFFFFD, 0x078644FA },
+ []u32{ 0x078644FA, 0xFFFFFFFE, 0x078644FA },
+ []u32{ 0x078644FA, 0xFFFFFFFF, 0x078644FA },
+ []u32{ 0x0747AE14, 0x00000001, 0x00000000 },
+ []u32{ 0x0747AE14, 0x00000002, 0x00000000 },
+ []u32{ 0x0747AE14, 0x00000003, 0x00000002 },
+ []u32{ 0x0747AE14, 0x00000010, 0x00000004 },
+ []u32{ 0x0747AE14, 0x078644FA, 0x0747AE14 },
+ []u32{ 0x0747AE14, 0x0747AE14, 0x00000000 },
+ []u32{ 0x0747AE14, 0x7FFFFFFF, 0x0747AE14 },
+ []u32{ 0x0747AE14, 0x80000000, 0x0747AE14 },
+ []u32{ 0x0747AE14, 0xFFFFFFFD, 0x0747AE14 },
+ []u32{ 0x0747AE14, 0xFFFFFFFE, 0x0747AE14 },
+ []u32{ 0x0747AE14, 0xFFFFFFFF, 0x0747AE14 },
+ []u32{ 0x7FFFFFFF, 0x00000001, 0x00000000 },
+ []u32{ 0x7FFFFFFF, 0x00000002, 0x00000001 },
+ []u32{ 0x7FFFFFFF, 0x00000003, 0x00000001 },
+ []u32{ 0x7FFFFFFF, 0x00000010, 0x0000000F },
+ []u32{ 0x7FFFFFFF, 0x078644FA, 0x00156B65 },
+ []u32{ 0x7FFFFFFF, 0x0747AE14, 0x043D70AB },
+ []u32{ 0x7FFFFFFF, 0x7FFFFFFF, 0x00000000 },
+ []u32{ 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF },
+ []u32{ 0x7FFFFFFF, 0xFFFFFFFD, 0x7FFFFFFF },
+ []u32{ 0x7FFFFFFF, 0xFFFFFFFE, 0x7FFFFFFF },
+ []u32{ 0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF },
+ []u32{ 0x80000000, 0x00000001, 0x00000000 },
+ []u32{ 0x80000000, 0x00000002, 0x00000000 },
+ []u32{ 0x80000000, 0x00000003, 0x00000002 },
+ []u32{ 0x80000000, 0x00000010, 0x00000000 },
+ []u32{ 0x80000000, 0x078644FA, 0x00156B66 },
+ []u32{ 0x80000000, 0x0747AE14, 0x043D70AC },
+ []u32{ 0x80000000, 0x7FFFFFFF, 0x00000001 },
+ []u32{ 0x80000000, 0x80000000, 0x00000000 },
+ []u32{ 0x80000000, 0xFFFFFFFD, 0x80000000 },
+ []u32{ 0x80000000, 0xFFFFFFFE, 0x80000000 },
+ []u32{ 0x80000000, 0xFFFFFFFF, 0x80000000 },
+ []u32{ 0xFFFFFFFD, 0x00000001, 0x00000000 },
+ []u32{ 0xFFFFFFFD, 0x00000002, 0x00000001 },
+ []u32{ 0xFFFFFFFD, 0x00000003, 0x00000001 },
+ []u32{ 0xFFFFFFFD, 0x00000010, 0x0000000D },
+ []u32{ 0xFFFFFFFD, 0x078644FA, 0x002AD6C9 },
+ []u32{ 0xFFFFFFFD, 0x0747AE14, 0x01333341 },
+ []u32{ 0xFFFFFFFD, 0x7FFFFFFF, 0x7FFFFFFE },
+ []u32{ 0xFFFFFFFD, 0x80000000, 0x7FFFFFFD },
+ []u32{ 0xFFFFFFFD, 0xFFFFFFFD, 0x00000000 },
+ []u32{ 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFD },
+ []u32{ 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFD },
+ []u32{ 0xFFFFFFFE, 0x00000001, 0x00000000 },
+ []u32{ 0xFFFFFFFE, 0x00000002, 0x00000000 },
+ []u32{ 0xFFFFFFFE, 0x00000003, 0x00000002 },
+ []u32{ 0xFFFFFFFE, 0x00000010, 0x0000000E },
+ []u32{ 0xFFFFFFFE, 0x078644FA, 0x002AD6CA },
+ []u32{ 0xFFFFFFFE, 0x0747AE14, 0x01333342 },
+ []u32{ 0xFFFFFFFE, 0x7FFFFFFF, 0x00000000 },
+ []u32{ 0xFFFFFFFE, 0x80000000, 0x7FFFFFFE },
+ []u32{ 0xFFFFFFFE, 0xFFFFFFFD, 0x00000001 },
+ []u32{ 0xFFFFFFFE, 0xFFFFFFFE, 0x00000000 },
+ []u32{ 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFE },
+ []u32{ 0xFFFFFFFF, 0x00000001, 0x00000000 },
+ []u32{ 0xFFFFFFFF, 0x00000002, 0x00000001 },
+ []u32{ 0xFFFFFFFF, 0x00000003, 0x00000000 },
+ []u32{ 0xFFFFFFFF, 0x00000010, 0x0000000F },
+ []u32{ 0xFFFFFFFF, 0x078644FA, 0x002AD6CB },
+ []u32{ 0xFFFFFFFF, 0x0747AE14, 0x01333343 },
+ []u32{ 0xFFFFFFFF, 0x7FFFFFFF, 0x00000001 },
+ []u32{ 0xFFFFFFFF, 0x80000000, 0x7FFFFFFF },
+ []u32{ 0xFFFFFFFF, 0xFFFFFFFD, 0x00000002 },
+ []u32{ 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001 },
+ []u32{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 },
+ };
+
+ for (cases) |case| {
+ test_one_umodsi3(case[0], case[1], case[2]);
+ }
+}
+
+fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) void {
+ const r: u32 = __umodsi3(a, b);
+ testing.expect(r == expected_r);
+}
diff --git a/std/special/compiler_rt/addXf3.zig b/std/special/compiler_rt/addXf3.zig
index 3a70461eca..5852f3e50d 100644
--- a/std/special/compiler_rt/addXf3.zig
+++ b/std/special/compiler_rt/addXf3.zig
@@ -78,8 +78,8 @@ fn addXf3(comptime T: type, a: T, b: T) T {
const infRep = @bitCast(Z, std.math.inf(T));
// Detect if a or b is zero, infinity, or NaN.
- if (aAbs - Z(1) >= infRep - Z(1) or
- bAbs - Z(1) >= infRep - Z(1))
+ if (aAbs -% Z(1) >= infRep - Z(1) or
+ bAbs -% Z(1) >= infRep - Z(1))
{
// NaN + anything = qNaN
if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
diff --git a/std/special/compiler_rt/arm/aeabi_dcmp.zig b/std/special/compiler_rt/arm/aeabi_dcmp.zig
new file mode 100644
index 0000000000..a51d9854ce
--- /dev/null
+++ b/std/special/compiler_rt/arm/aeabi_dcmp.zig
@@ -0,0 +1,108 @@
+// Ported from:
+//
+// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_dcmp.S
+
+const compiler_rt_armhf_target = false; // TODO
+
+const ConditionalOperator = enum {
+ Eq,
+ Lt,
+ Le,
+ Ge,
+ Gt,
+};
+
+pub nakedcc fn __aeabi_dcmpeq() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_dcmp(.Eq);
+ unreachable;
+}
+
+pub nakedcc fn __aeabi_dcmplt() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_dcmp(.Lt);
+ unreachable;
+}
+
+pub nakedcc fn __aeabi_dcmple() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_dcmp(.Le);
+ unreachable;
+}
+
+pub nakedcc fn __aeabi_dcmpge() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_dcmp(.Ge);
+ unreachable;
+}
+
+pub nakedcc fn __aeabi_dcmpgt() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_dcmp(.Gt);
+ unreachable;
+}
+
+inline fn convert_dcmp_args_to_df2_args() void {
+ asm volatile (
+ \\ vmov d0, r0, r1
+ \\ vmov d1, r2, r3
+ );
+}
+
+inline fn aeabi_dcmp(comptime cond: ConditionalOperator) void {
+ @setRuntimeSafety(false);
+ asm volatile (
+ \\ push { r4, lr }
+ );
+
+ if (compiler_rt_armhf_target) {
+ convert_dcmp_args_to_df2_args();
+ }
+
+ switch (cond) {
+ .Eq => asm volatile (
+ \\ bl __eqdf2
+ \\ cmp r0, #0
+ \\ beq 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ .Lt => asm volatile (
+ \\ bl __ltdf2
+ \\ cmp r0, #0
+ \\ blt 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ .Le => asm volatile (
+ \\ bl __ledf2
+ \\ cmp r0, #0
+ \\ ble 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ .Ge => asm volatile (
+ \\ bl __ltdf2
+ \\ cmp r0, #0
+ \\ bge 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ .Gt => asm volatile (
+ \\ bl __gtdf2
+ \\ cmp r0, #0
+ \\ bgt 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ }
+ asm volatile (
+ \\ movs r0, #1
+ \\ pop { r4, pc }
+ );
+}
diff --git a/std/special/compiler_rt/arm/aeabi_fcmp.zig b/std/special/compiler_rt/arm/aeabi_fcmp.zig
new file mode 100644
index 0000000000..f82dd25270
--- /dev/null
+++ b/std/special/compiler_rt/arm/aeabi_fcmp.zig
@@ -0,0 +1,108 @@
+// Ported from:
+//
+// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_fcmp.S
+
+const compiler_rt_armhf_target = false; // TODO
+
+const ConditionalOperator = enum {
+ Eq,
+ Lt,
+ Le,
+ Ge,
+ Gt,
+};
+
+pub nakedcc fn __aeabi_fcmpeq() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_fcmp(.Eq);
+ unreachable;
+}
+
+pub nakedcc fn __aeabi_fcmplt() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_fcmp(.Lt);
+ unreachable;
+}
+
+pub nakedcc fn __aeabi_fcmple() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_fcmp(.Le);
+ unreachable;
+}
+
+pub nakedcc fn __aeabi_fcmpge() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_fcmp(.Ge);
+ unreachable;
+}
+
+pub nakedcc fn __aeabi_fcmpgt() noreturn {
+ @setRuntimeSafety(false);
+ aeabi_fcmp(.Gt);
+ unreachable;
+}
+
+inline fn convert_fcmp_args_to_sf2_args() void {
+ asm volatile (
+ \\ vmov s0, r0
+ \\ vmov s1, r1
+ );
+}
+
+inline fn aeabi_fcmp(comptime cond: ConditionalOperator) void {
+ @setRuntimeSafety(false);
+ asm volatile (
+ \\ push { r4, lr }
+ );
+
+ if (compiler_rt_armhf_target) {
+ convert_fcmp_args_to_sf2_args();
+ }
+
+ switch (cond) {
+ .Eq => asm volatile (
+ \\ bl __eqsf2
+ \\ cmp r0, #0
+ \\ beq 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ .Lt => asm volatile (
+ \\ bl __ltsf2
+ \\ cmp r0, #0
+ \\ blt 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ .Le => asm volatile (
+ \\ bl __lesf2
+ \\ cmp r0, #0
+ \\ ble 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ .Ge => asm volatile (
+ \\ bl __ltsf2
+ \\ cmp r0, #0
+ \\ bge 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ .Gt => asm volatile (
+ \\ bl __gtsf2
+ \\ cmp r0, #0
+ \\ bgt 1f
+ \\ movs r0, #0
+ \\ pop { r4, pc }
+ \\ 1:
+ ),
+ }
+ asm volatile (
+ \\ movs r0, #1
+ \\ pop { r4, pc }
+ );
+}
diff --git a/std/special/compiler_rt/ashlti3.zig b/std/special/compiler_rt/ashlti3.zig
new file mode 100644
index 0000000000..65b23f22e5
--- /dev/null
+++ b/std/special/compiler_rt/ashlti3.zig
@@ -0,0 +1,41 @@
+const builtin = @import("builtin");
+const compiler_rt = @import("../compiler_rt.zig");
+
+pub extern fn __ashlti3(a: i128, b: i32) i128 {
+ var input = twords{ .all = a };
+ var result: twords = undefined;
+
+ if (b > 63) {
+ // 64 <= b < 128
+ result.s.low = 0;
+ result.s.high = input.s.low << @intCast(u6, b - 64);
+ } else {
+ // 0 <= b < 64
+ if (b == 0) return a;
+ result.s.low = input.s.low << @intCast(u6, b);
+ result.s.high = input.s.low >> @intCast(u6, 64 - b);
+ result.s.high |= input.s.high << @intCast(u6, b);
+ }
+
+ return result.all;
+}
+
+const twords = extern union {
+ all: i128,
+ s: S,
+
+ const S = if (builtin.endian == builtin.Endian.Little)
+ struct {
+ low: u64,
+ high: u64,
+ }
+ else
+ struct {
+ high: u64,
+ low: u64,
+ };
+};
+
+test "import ashlti3" {
+ _ = @import("ashlti3_test.zig");
+}
diff --git a/std/special/compiler_rt/ashlti3_test.zig b/std/special/compiler_rt/ashlti3_test.zig
new file mode 100644
index 0000000000..4ba21c138e
--- /dev/null
+++ b/std/special/compiler_rt/ashlti3_test.zig
@@ -0,0 +1,46 @@
+const __ashlti3 = @import("ashlti3.zig").__ashlti3;
+const testing = @import("std").testing;
+
+fn test__ashlti3(a: i128, b: i32, expected: i128) void {
+ const x = __ashlti3(a, b);
+ testing.expect(x == expected);
+}
+
+test "ashlti3" {
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 0, @bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 1, @bitCast(i128, @intCast(u128, 0xFDB97530ECA8642BFDB97530ECA8642A)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 2, @bitCast(i128, @intCast(u128, 0xFB72EA61D950C857FB72EA61D950C854)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 3, @bitCast(i128, @intCast(u128, 0xF6E5D4C3B2A190AFF6E5D4C3B2A190A8)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 4, @bitCast(i128, @intCast(u128, 0xEDCBA9876543215FEDCBA98765432150)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 28, @bitCast(i128, @intCast(u128, 0x876543215FEDCBA98765432150000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 29, @bitCast(i128, @intCast(u128, 0x0ECA8642BFDB97530ECA8642A0000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 30, @bitCast(i128, @intCast(u128, 0x1D950C857FB72EA61D950C8540000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 31, @bitCast(i128, @intCast(u128, 0x3B2A190AFF6E5D4C3B2A190A80000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 32, @bitCast(i128, @intCast(u128, 0x76543215FEDCBA987654321500000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 33, @bitCast(i128, @intCast(u128, 0xECA8642BFDB97530ECA8642A00000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 34, @bitCast(i128, @intCast(u128, 0xD950C857FB72EA61D950C85400000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 35, @bitCast(i128, @intCast(u128, 0xB2A190AFF6E5D4C3B2A190A800000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 36, @bitCast(i128, @intCast(u128, 0x6543215FEDCBA9876543215000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 60, @bitCast(i128, @intCast(u128, 0x5FEDCBA9876543215000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 61, @bitCast(i128, @intCast(u128, 0xBFDB97530ECA8642A000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 62, @bitCast(i128, @intCast(u128, 0x7FB72EA61D950C854000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 63, @bitCast(i128, @intCast(u128, 0xFF6E5D4C3B2A190A8000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 64, @bitCast(i128, @intCast(u128, 0xFEDCBA98765432150000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 65, @bitCast(i128, @intCast(u128, 0xFDB97530ECA8642A0000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 66, @bitCast(i128, @intCast(u128, 0xFB72EA61D950C8540000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 67, @bitCast(i128, @intCast(u128, 0xF6E5D4C3B2A190A80000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 68, @bitCast(i128, @intCast(u128, 0xEDCBA987654321500000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 92, @bitCast(i128, @intCast(u128, 0x87654321500000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 93, @bitCast(i128, @intCast(u128, 0x0ECA8642A00000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 94, @bitCast(i128, @intCast(u128, 0x1D950C85400000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 95, @bitCast(i128, @intCast(u128, 0x3B2A190A800000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 96, @bitCast(i128, @intCast(u128, 0x76543215000000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 97, @bitCast(i128, @intCast(u128, 0xECA8642A000000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 98, @bitCast(i128, @intCast(u128, 0xD950C854000000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 99, @bitCast(i128, @intCast(u128, 0xB2A190A8000000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 100, @bitCast(i128, @intCast(u128, 0x65432150000000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 124, @bitCast(i128, @intCast(u128, 0x50000000000000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 125, @bitCast(i128, @intCast(u128, 0xA0000000000000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 126, @bitCast(i128, @intCast(u128, 0x40000000000000000000000000000000)));
+ test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 127, @bitCast(i128, @intCast(u128, 0x80000000000000000000000000000000)));
+}
diff --git a/std/special/compiler_rt/ashrti3.zig b/std/special/compiler_rt/ashrti3.zig
new file mode 100644
index 0000000000..40ee89c3c4
--- /dev/null
+++ b/std/special/compiler_rt/ashrti3.zig
@@ -0,0 +1,42 @@
+const builtin = @import("builtin");
+const compiler_rt = @import("../compiler_rt.zig");
+
+pub extern fn __ashrti3(a: i128, b: i32) i128 {
+ var input = twords{ .all = a };
+ var result: twords = undefined;
+
+ if (b > 63) {
+ // 64 <= b < 128
+ result.s.low = input.s.high >> @intCast(u6, b - 64);
+ result.s.high = input.s.high >> 63;
+ } else {
+ // 0 <= b < 64
+ if (b == 0) return a;
+ result.s.low = input.s.high << @intCast(u6, 64 - b);
+ // Avoid sign-extension here
+ result.s.low |= @bitCast(i64, @bitCast(u64, input.s.low) >> @intCast(u6, b));
+ result.s.high = input.s.high >> @intCast(u6, b);
+ }
+
+ return result.all;
+}
+
+const twords = extern union {
+ all: i128,
+ s: S,
+
+ const S = if (builtin.endian == builtin.Endian.Little)
+ struct {
+ low: i64,
+ high: i64,
+ }
+ else
+ struct {
+ high: i64,
+ low: i64,
+ };
+};
+
+test "import ashrti3" {
+ _ = @import("ashrti3_test.zig");
+}
diff --git a/std/special/compiler_rt/ashrti3_test.zig b/std/special/compiler_rt/ashrti3_test.zig
new file mode 100644
index 0000000000..04ae5abd82
--- /dev/null
+++ b/std/special/compiler_rt/ashrti3_test.zig
@@ -0,0 +1,58 @@
+const __ashrti3 = @import("ashrti3.zig").__ashrti3;
+const testing = @import("std").testing;
+
+fn test__ashrti3(a: i128, b: i32, expected: i128) void {
+ const x = __ashrti3(a, b);
+ // @import("std").debug.warn("got 0x{x}\nexp 0x{x}\n", @truncate(u64,
+// @bitCast(u128, x) >> 64), @truncate(u64, @bitCast(u128, expected)) >> 64);
+ testing.expect(x == expected);
+}
+
+test "ashrti3" {
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 0, @bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 1, @bitCast(i128, @intCast(u128, 0xFF6E5D4C3B2A190AFF6E5D4C3B2A190A)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 2, @bitCast(i128, @intCast(u128, 0xFFB72EA61D950C857FB72EA61D950C85)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 3, @bitCast(i128, @intCast(u128, 0xFFDB97530ECA8642BFDB97530ECA8642)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 4, @bitCast(i128, @intCast(u128, 0xFFEDCBA9876543215FEDCBA987654321)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 28, @bitCast(i128, @intCast(u128, 0xFFFFFFFFEDCBA9876543215FEDCBA987)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 29, @bitCast(i128, @intCast(u128, 0xFFFFFFFFF6E5D4C3B2A190AFF6E5D4C3)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 30, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFB72EA61D950C857FB72EA61)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 31, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFDB97530ECA8642BFDB97530)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 32, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFEDCBA9876543215FEDCBA98)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 33, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFF6E5D4C3B2A190AFF6E5D4C)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 34, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFB72EA61D950C857FB72EA6)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 35, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFDB97530ECA8642BFDB9753)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 36, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFEDCBA9876543215FEDCBA9)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 60, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFEDCBA9876543215F)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 61, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFF6E5D4C3B2A190AF)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 62, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFB72EA61D950C857)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 63, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFDB97530ECA8642B)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 64, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFEDCBA9876543215)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 65, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFF6E5D4C3B2A190A)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 66, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFB72EA61D950C85)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 67, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFDB97530ECA8642)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 68, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFEDCBA987654321)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 92, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFEDCBA987)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 93, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFF6E5D4C3)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 94, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFB72EA61)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 95, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFDB97530)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 96, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFEDCBA98)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 97, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFF6E5D4C)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 98, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFB72EA6)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 99, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFDB9753)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 100, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFEDCBA9)));
+
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 124, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 125, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 126, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)));
+ test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 127, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)));
+}
diff --git a/std/special/compiler_rt/comparedf2.zig b/std/special/compiler_rt/comparedf2.zig
new file mode 100644
index 0000000000..f97e2474be
--- /dev/null
+++ b/std/special/compiler_rt/comparedf2.zig
@@ -0,0 +1,122 @@
+// Ported from:
+//
+// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparedf2.c
+
+const std = @import("std");
+const builtin = @import("builtin");
+const is_test = builtin.is_test;
+
+const fp_t = f64;
+const rep_t = u64;
+const srep_t = i64;
+
+const typeWidth = rep_t.bit_count;
+const significandBits = std.math.floatMantissaBits(fp_t);
+const exponentBits = std.math.floatExponentBits(fp_t);
+const signBit = (rep_t(1) << (significandBits + exponentBits));
+const absMask = signBit - 1;
+const implicitBit = rep_t(1) << significandBits;
+const significandMask = implicitBit - 1;
+const exponentMask = absMask ^ significandMask;
+const infRep = @bitCast(rep_t, std.math.inf(fp_t));
+
+// TODO https://github.com/ziglang/zig/issues/641
+// and then make the return types of some of these functions the enum instead of c_int
+const LE_LESS = c_int(-1);
+const LE_EQUAL = c_int(0);
+const LE_GREATER = c_int(1);
+const LE_UNORDERED = c_int(1);
+
+pub extern fn __ledf2(a: fp_t, b: fp_t) c_int {
+ @setRuntimeSafety(is_test);
+ const aInt: srep_t = @bitCast(srep_t, a);
+ const bInt: srep_t = @bitCast(srep_t, b);
+ const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
+ const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
+
+ // If either a or b is NaN, they are unordered.
+ if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED;
+
+ // If a and b are both zeros, they are equal.
+ if ((aAbs | bAbs) == 0) return LE_EQUAL;
+
+ // If at least one of a and b is positive, we get the same result comparing
+ // a and b as signed integers as we would with a fp_ting-point compare.
+ if ((aInt & bInt) >= 0) {
+ if (aInt < bInt) {
+ return LE_LESS;
+ } else if (aInt == bInt) {
+ return LE_EQUAL;
+ } else return LE_GREATER;
+ }
+
+ // Otherwise, both are negative, so we need to flip the sense of the
+ // comparison to get the correct result. (This assumes a twos- or ones-
+ // complement integer representation; if integers are represented in a
+ // sign-magnitude representation, then this flip is incorrect).
+ else {
+ if (aInt > bInt) {
+ return LE_LESS;
+ } else if (aInt == bInt) {
+ return LE_EQUAL;
+ } else return LE_GREATER;
+ }
+}
+
+// TODO https://github.com/ziglang/zig/issues/641
+// and then make the return types of some of these functions the enum instead of c_int
+const GE_LESS = c_int(-1);
+const GE_EQUAL = c_int(0);
+const GE_GREATER = c_int(1);
+const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED
+
+pub extern fn __gedf2(a: fp_t, b: fp_t) c_int {
+ @setRuntimeSafety(is_test);
+ const aInt: srep_t = @bitCast(srep_t, a);
+ const bInt: srep_t = @bitCast(srep_t, b);
+ const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
+ const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
+
+ if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
+ if ((aAbs | bAbs) == 0) return GE_EQUAL;
+ if ((aInt & bInt) >= 0) {
+ if (aInt < bInt) {
+ return GE_LESS;
+ } else if (aInt == bInt) {
+ return GE_EQUAL;
+ } else return GE_GREATER;
+ } else {
+ if (aInt > bInt) {
+ return GE_LESS;
+ } else if (aInt == bInt) {
+ return GE_EQUAL;
+ } else return GE_GREATER;
+ }
+}
+
+pub extern fn __unorddf2(a: fp_t, b: fp_t) c_int {
+ @setRuntimeSafety(is_test);
+ const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
+ const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
+ return @boolToInt(aAbs > infRep or bAbs > infRep);
+}
+
+pub extern fn __eqdf2(a: fp_t, b: fp_t) c_int {
+ return __ledf2(a, b);
+}
+
+pub extern fn __ltdf2(a: fp_t, b: fp_t) c_int {
+ return __ledf2(a, b);
+}
+
+pub extern fn __nedf2(a: fp_t, b: fp_t) c_int {
+ return __ledf2(a, b);
+}
+
+pub extern fn __gtdf2(a: fp_t, b: fp_t) c_int {
+ return __gedf2(a, b);
+}
+
+test "import comparedf2" {
+ _ = @import("comparedf2_test.zig");
+}
diff --git a/std/special/compiler_rt/comparedf2_test.zig b/std/special/compiler_rt/comparedf2_test.zig
new file mode 100644
index 0000000000..9c08389994
--- /dev/null
+++ b/std/special/compiler_rt/comparedf2_test.zig
@@ -0,0 +1,101 @@
+// Ported from:
+//
+// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/comparedf2_test.c
+
+const std = @import("std");
+const builtin = @import("builtin");
+const is_test = builtin.is_test;
+
+const comparedf2 = @import("comparedf2.zig");
+
+const TestVector = struct {
+ a: f64,
+ b: f64,
+ eqReference: c_int,
+ geReference: c_int,
+ gtReference: c_int,
+ leReference: c_int,
+ ltReference: c_int,
+ neReference: c_int,
+ unReference: c_int,
+};
+
+fn test__cmpdf2(vector: TestVector) bool {
+ if (comparedf2.__eqdf2(vector.a, vector.b) != vector.eqReference) {
+ return false;
+ }
+ if (comparedf2.__gedf2(vector.a, vector.b) != vector.geReference) {
+ return false;
+ }
+ if (comparedf2.__gtdf2(vector.a, vector.b) != vector.gtReference) {
+ return false;
+ }
+ if (comparedf2.__ledf2(vector.a, vector.b) != vector.leReference) {
+ return false;
+ }
+ if (comparedf2.__ltdf2(vector.a, vector.b) != vector.ltReference) {
+ return false;
+ }
+ if (comparedf2.__nedf2(vector.a, vector.b) != vector.neReference) {
+ return false;
+ }
+ if (comparedf2.__unorddf2(vector.a, vector.b) != vector.unReference) {
+ return false;
+ }
+ return true;
+}
+
+const arguments = []f64{
+ std.math.nan(f64),
+ -std.math.inf(f64),
+ -0x1.fffffffffffffp1023,
+ -0x1.0000000000001p0 - 0x1.0000000000000p0,
+ -0x1.fffffffffffffp-1,
+ -0x1.0000000000000p-1022,
+ -0x0.fffffffffffffp-1022,
+ -0x0.0000000000001p-1022,
+ -0.0,
+ 0.0,
+ 0x0.0000000000001p-1022,
+ 0x0.fffffffffffffp-1022,
+ 0x1.0000000000000p-1022,
+ 0x1.fffffffffffffp-1,
+ 0x1.0000000000000p0,
+ 0x1.0000000000001p0,
+ 0x1.fffffffffffffp1023,
+ std.math.inf(f64),
+};
+
+fn generateVector(comptime a: f64, comptime b: f64) TestVector {
+ const leResult = if (a < b) -1 else if (a == b) 0 else 1;
+ const geResult = if (a > b) 1 else if (a == b) 0 else -1;
+ const unResult = if (a != a or b != b) 1 else 0;
+ return TestVector{
+ .a = a,
+ .b = b,
+ .eqReference = leResult,
+ .geReference = geResult,
+ .gtReference = geResult,
+ .leReference = leResult,
+ .ltReference = leResult,
+ .neReference = leResult,
+ .unReference = unResult,
+ };
+}
+
+const test_vectors = init: {
+ @setEvalBranchQuota(10000);
+ var vectors: [arguments.len * arguments.len]TestVector = undefined;
+ for (arguments[0..]) |arg_i, i| {
+ for (arguments[0..]) |arg_j, j| {
+ vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j);
+ }
+ }
+ break :init vectors;
+};
+
+test "compare f64" {
+ for (test_vectors) |vector, i| {
+ std.testing.expect(test__cmpdf2(vector));
+ }
+}
diff --git a/std/special/compiler_rt/comparesf2.zig b/std/special/compiler_rt/comparesf2.zig
new file mode 100644
index 0000000000..e99e0bb3dd
--- /dev/null
+++ b/std/special/compiler_rt/comparesf2.zig
@@ -0,0 +1,122 @@
+// Ported from:
+//
+// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c
+
+const std = @import("std");
+const builtin = @import("builtin");
+const is_test = builtin.is_test;
+
+const fp_t = f32;
+const rep_t = u32;
+const srep_t = i32;
+
+const typeWidth = rep_t.bit_count;
+const significandBits = std.math.floatMantissaBits(fp_t);
+const exponentBits = std.math.floatExponentBits(fp_t);
+const signBit = (rep_t(1) << (significandBits + exponentBits));
+const absMask = signBit - 1;
+const implicitBit = rep_t(1) << significandBits;
+const significandMask = implicitBit - 1;
+const exponentMask = absMask ^ significandMask;
+const infRep = @bitCast(rep_t, std.math.inf(fp_t));
+
+// TODO https://github.com/ziglang/zig/issues/641
+// and then make the return types of some of these functions the enum instead of c_int
+const LE_LESS = c_int(-1);
+const LE_EQUAL = c_int(0);
+const LE_GREATER = c_int(1);
+const LE_UNORDERED = c_int(1);
+
+pub extern fn __lesf2(a: fp_t, b: fp_t) c_int {
+ @setRuntimeSafety(is_test);
+ const aInt: srep_t = @bitCast(srep_t, a);
+ const bInt: srep_t = @bitCast(srep_t, b);
+ const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
+ const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
+
+ // If either a or b is NaN, they are unordered.
+ if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED;
+
+ // If a and b are both zeros, they are equal.
+ if ((aAbs | bAbs) == 0) return LE_EQUAL;
+
+ // If at least one of a and b is positive, we get the same result comparing
+ // a and b as signed integers as we would with a fp_ting-point compare.
+ if ((aInt & bInt) >= 0) {
+ if (aInt < bInt) {
+ return LE_LESS;
+ } else if (aInt == bInt) {
+ return LE_EQUAL;
+ } else return LE_GREATER;
+ }
+
+ // Otherwise, both are negative, so we need to flip the sense of the
+ // comparison to get the correct result. (This assumes a twos- or ones-
+ // complement integer representation; if integers are represented in a
+ // sign-magnitude representation, then this flip is incorrect).
+ else {
+ if (aInt > bInt) {
+ return LE_LESS;
+ } else if (aInt == bInt) {
+ return LE_EQUAL;
+ } else return LE_GREATER;
+ }
+}
+
+// TODO https://github.com/ziglang/zig/issues/641
+// and then make the return types of some of these functions the enum instead of c_int
+const GE_LESS = c_int(-1);
+const GE_EQUAL = c_int(0);
+const GE_GREATER = c_int(1);
+const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED
+
+pub extern fn __gesf2(a: fp_t, b: fp_t) c_int {
+ @setRuntimeSafety(is_test);
+ const aInt: srep_t = @bitCast(srep_t, a);
+ const bInt: srep_t = @bitCast(srep_t, b);
+ const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
+ const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
+
+ if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
+ if ((aAbs | bAbs) == 0) return GE_EQUAL;
+ if ((aInt & bInt) >= 0) {
+ if (aInt < bInt) {
+ return GE_LESS;
+ } else if (aInt == bInt) {
+ return GE_EQUAL;
+ } else return GE_GREATER;
+ } else {
+ if (aInt > bInt) {
+ return GE_LESS;
+ } else if (aInt == bInt) {
+ return GE_EQUAL;
+ } else return GE_GREATER;
+ }
+}
+
+pub extern fn __unordsf2(a: fp_t, b: fp_t) c_int {
+ @setRuntimeSafety(is_test);
+ const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
+ const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
+ return @boolToInt(aAbs > infRep or bAbs > infRep);
+}
+
+pub extern fn __eqsf2(a: fp_t, b: fp_t) c_int {
+ return __lesf2(a, b);
+}
+
+pub extern fn __ltsf2(a: fp_t, b: fp_t) c_int {
+ return __lesf2(a, b);
+}
+
+pub extern fn __nesf2(a: fp_t, b: fp_t) c_int {
+ return __lesf2(a, b);
+}
+
+pub extern fn __gtsf2(a: fp_t, b: fp_t) c_int {
+ return __gesf2(a, b);
+}
+
+test "import comparesf2" {
+ _ = @import("comparesf2_test.zig");
+}
diff --git a/std/special/compiler_rt/comparesf2_test.zig b/std/special/compiler_rt/comparesf2_test.zig
new file mode 100644
index 0000000000..e460634fad
--- /dev/null
+++ b/std/special/compiler_rt/comparesf2_test.zig
@@ -0,0 +1,101 @@
+// Ported from:
+//
+// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/comparesf2_test.c
+
+const std = @import("std");
+const builtin = @import("builtin");
+const is_test = builtin.is_test;
+
+const comparesf2 = @import("comparesf2.zig");
+
+const TestVector = struct {
+ a: f32,
+ b: f32,
+ eqReference: c_int,
+ geReference: c_int,
+ gtReference: c_int,
+ leReference: c_int,
+ ltReference: c_int,
+ neReference: c_int,
+ unReference: c_int,
+};
+
+fn test__cmpsf2(vector: TestVector) bool {
+ if (comparesf2.__eqsf2(vector.a, vector.b) != vector.eqReference) {
+ return false;
+ }
+ if (comparesf2.__gesf2(vector.a, vector.b) != vector.geReference) {
+ return false;
+ }
+ if (comparesf2.__gtsf2(vector.a, vector.b) != vector.gtReference) {
+ return false;
+ }
+ if (comparesf2.__lesf2(vector.a, vector.b) != vector.leReference) {
+ return false;
+ }
+ if (comparesf2.__ltsf2(vector.a, vector.b) != vector.ltReference) {
+ return false;
+ }
+ if (comparesf2.__nesf2(vector.a, vector.b) != vector.neReference) {
+ return false;
+ }
+ if (comparesf2.__unordsf2(vector.a, vector.b) != vector.unReference) {
+ return false;
+ }
+ return true;
+}
+
+const arguments = []f32{
+ std.math.nan(f32),
+ -std.math.inf(f32),
+ -0x1.fffffep127,
+ -0x1.000002p0 - 0x1.000000p0,
+ -0x1.fffffep-1,
+ -0x1.000000p-126,
+ -0x0.fffffep-126,
+ -0x0.000002p-126,
+ -0.0,
+ 0.0,
+ 0x0.000002p-126,
+ 0x0.fffffep-126,
+ 0x1.000000p-126,
+ 0x1.fffffep-1,
+ 0x1.000000p0,
+ 0x1.000002p0,
+ 0x1.fffffep127,
+ std.math.inf(f32),
+};
+
+fn generateVector(comptime a: f32, comptime b: f32) TestVector {
+ const leResult = if (a < b) -1 else if (a == b) 0 else 1;
+ const geResult = if (a > b) 1 else if (a == b) 0 else -1;
+ const unResult = if (a != a or b != b) 1 else 0;
+ return TestVector{
+ .a = a,
+ .b = b,
+ .eqReference = leResult,
+ .geReference = geResult,
+ .gtReference = geResult,
+ .leReference = leResult,
+ .ltReference = leResult,
+ .neReference = leResult,
+ .unReference = unResult,
+ };
+}
+
+const test_vectors = init: {
+ @setEvalBranchQuota(10000);
+ var vectors: [arguments.len * arguments.len]TestVector = undefined;
+ for (arguments[0..]) |arg_i, i| {
+ for (arguments[0..]) |arg_j, j| {
+ vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j);
+ }
+ }
+ break :init vectors;
+};
+
+test "compare f32" {
+ for (test_vectors) |vector, i| {
+ std.testing.expect(test__cmpsf2(vector));
+ }
+}
diff --git a/std/special/compiler_rt/divti3.zig b/std/special/compiler_rt/divti3.zig
index e89a1ada5c..d5b2778a34 100644
--- a/std/special/compiler_rt/divti3.zig
+++ b/std/special/compiler_rt/divti3.zig
@@ -16,9 +16,9 @@ pub extern fn __divti3(a: i128, b: i128) i128 {
return (@bitCast(i128, r) ^ s) -% s;
}
-pub extern fn __divti3_windows_x86_64(a: *const i128, b: *const i128) void {
- @setRuntimeSafety(builtin.is_test);
- compiler_rt.setXmm0(i128, __divti3(a.*, b.*));
+const v128 = @Vector(2, u64);
+pub extern fn __divti3_windows_x86_64(a: v128, b: v128) v128 {
+ return @bitCast(v128, @inlineCall(__divti3, @bitCast(i128, a), @bitCast(i128, b)));
}
test "import divti3" {
diff --git a/std/special/compiler_rt/extendXfYf2.zig b/std/special/compiler_rt/extendXfYf2.zig
index 099e27b74a..42559784bb 100644
--- a/std/special/compiler_rt/extendXfYf2.zig
+++ b/std/special/compiler_rt/extendXfYf2.zig
@@ -2,21 +2,27 @@ const std = @import("std");
const builtin = @import("builtin");
const is_test = builtin.is_test;
+pub extern fn __extendsfdf2(a: f32) f64 {
+ return @inlineCall(extendXfYf2, f64, f32, @bitCast(u32, a));
+}
+
pub extern fn __extenddftf2(a: f64) f128 {
- return extendXfYf2(f128, f64, a);
+ return @inlineCall(extendXfYf2, f128, f64, @bitCast(u64, a));
}
pub extern fn __extendsftf2(a: f32) f128 {
- return extendXfYf2(f128, f32, a);
+ return @inlineCall(extendXfYf2, f128, f32, @bitCast(u32, a));
}
pub extern fn __extendhfsf2(a: u16) f32 {
- return extendXfYf2(f32, f16, @bitCast(f16, a));
+ return @inlineCall(extendXfYf2, f32, f16, a);
}
const CHAR_BIT = 8;
-inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
+fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: @IntType(false, @typeInfo(src_t).Float.bits)) dst_t {
+ @setRuntimeSafety(builtin.is_test);
+
const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);
const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits);
const srcSigBits = std.math.floatMantissaBits(src_t);
diff --git a/std/special/compiler_rt/floatdidf.zig b/std/special/compiler_rt/floatdidf.zig
new file mode 100644
index 0000000000..1610136413
--- /dev/null
+++ b/std/special/compiler_rt/floatdidf.zig
@@ -0,0 +1,22 @@
+const builtin = @import("builtin");
+const std = @import("std");
+
+const twop52: f64 = 0x1.0p52;
+const twop32: f64 = 0x1.0p32;
+
+pub extern fn __floatdidf(a: i64) f64 {
+ @setRuntimeSafety(builtin.is_test);
+
+ if (a == 0) return 0;
+
+ var low = @bitCast(i64, twop52);
+ const high = @intToFloat(f64, @truncate(i32, a >> 32)) * twop32;
+
+ low |= @bitCast(i64, a & 0xFFFFFFFF);
+
+ return (high - twop52) + @bitCast(f64, low);
+}
+
+test "import floatdidf" {
+ _ = @import("floatdidf_test.zig");
+}
diff --git a/std/special/compiler_rt/floatdidf_test.zig b/std/special/compiler_rt/floatdidf_test.zig
new file mode 100644
index 0000000000..c854183809
--- /dev/null
+++ b/std/special/compiler_rt/floatdidf_test.zig
@@ -0,0 +1,53 @@
+const __floatdidf = @import("floatdidf.zig").__floatdidf;
+const testing = @import("std").testing;
+
+fn test__floatdidf(a: i64, expected: f64) void {
+ const r = __floatdidf(a);
+ testing.expect(r == expected);
+}
+
+test "floatdidf" {
+ test__floatdidf(0, 0.0);
+ test__floatdidf(1, 1.0);
+ test__floatdidf(2, 2.0);
+ test__floatdidf(20, 20.0);
+ test__floatdidf(-1, -1.0);
+ test__floatdidf(-2, -2.0);
+ test__floatdidf(-20, -20.0);
+ test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
+ test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
+ test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
+ test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
+ test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);
+ test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000800)), -0x1.FFFFFFFFFFFFEp+62);
+ test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);
+ test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000001000)), -0x1.FFFFFFFFFFFFCp+62);
+ test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000000)), -0x1.000000p+63);
+ test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000001)), -0x1.000000p+63);
+ test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
+ test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
+ test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
+ test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
+ test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
+ test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
+ test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
+ test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
+ test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
+ test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
+ test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
+ test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
+ test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
+ test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
+ test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
+ test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
+ test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
+}
diff --git a/std/special/compiler_rt/floatsiXf.zig b/std/special/compiler_rt/floatsiXf.zig
new file mode 100644
index 0000000000..83b3940c1e
--- /dev/null
+++ b/std/special/compiler_rt/floatsiXf.zig
@@ -0,0 +1,109 @@
+const builtin = @import("builtin");
+const std = @import("std");
+const maxInt = std.math.maxInt;
+
+fn floatsiXf(comptime T: type, a: i32) T {
+ @setRuntimeSafety(builtin.is_test);
+
+ const Z = @IntType(false, T.bit_count);
+ const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1));
+
+ if (a == 0) {
+ return T(0.0);
+ }
+
+ const significandBits = std.math.floatMantissaBits(T);
+ const exponentBits = std.math.floatExponentBits(T);
+ const exponentBias = ((1 << exponentBits - 1) - 1);
+
+ const implicitBit = Z(1) << significandBits;
+ const signBit = Z(1 << Z.bit_count - 1);
+
+ const sign = a >> 31;
+ // Take absolute value of a via abs(x) = (x^(x >> 31)) - (x >> 31).
+ const abs_a = (a ^ sign) -% sign;
+ // The exponent is the width of abs(a)
+ const exp = Z(31 - @clz(abs_a));
+
+ const sign_bit = if (sign < 0) signBit else 0;
+
+ var mantissa: Z = undefined;
+ // Shift a into the significand field and clear the implicit bit.
+ if (exp <= significandBits) {
+ // No rounding needed
+ const shift = @intCast(S, significandBits - exp);
+ mantissa = @intCast(Z, @bitCast(u32, abs_a)) << shift ^ implicitBit;
+ } else {
+ const shift = @intCast(S, exp - significandBits);
+ // Round to the nearest number after truncation
+ mantissa = @intCast(Z, @bitCast(u32, abs_a)) >> shift ^ implicitBit;
+ // Align to the left and check if the truncated part is halfway over
+ const round = @bitCast(u32, abs_a) << @intCast(u5, 31 - shift);
+ mantissa += @boolToInt(round > 0x80000000);
+ // Tie to even
+ mantissa += mantissa & 1;
+ }
+
+ // Use the addition instead of a or since we may have a carry from the
+ // mantissa to the exponent
+ var result = mantissa;
+ result += (exp + exponentBias) << significandBits;
+ result += sign_bit;
+
+ return @bitCast(T, result);
+}
+
+pub extern fn __floatsisf(arg: i32) f32 {
+ @setRuntimeSafety(builtin.is_test);
+ return @inlineCall(floatsiXf, f32, arg);
+}
+
+pub extern fn __floatsidf(arg: i32) f64 {
+ @setRuntimeSafety(builtin.is_test);
+ return @inlineCall(floatsiXf, f64, arg);
+}
+
+pub extern fn __floatsitf(arg: i32) f128 {
+ @setRuntimeSafety(builtin.is_test);
+ return @inlineCall(floatsiXf, f128, arg);
+}
+
+fn test_one_floatsitf(a: i32, expected: u128) void {
+ const r = __floatsitf(a);
+ std.testing.expect(@bitCast(u128, r) == expected);
+}
+
+fn test_one_floatsidf(a: i32, expected: u64) void {
+ const r = __floatsidf(a);
+ std.testing.expect(@bitCast(u64, r) == expected);
+}
+
+fn test_one_floatsisf(a: i32, expected: u32) void {
+ const r = __floatsisf(a);
+ std.testing.expect(@bitCast(u32, r) == expected);
+}
+
+test "floatsidf" {
+ test_one_floatsidf(0, 0x0000000000000000);
+ test_one_floatsidf(1, 0x3ff0000000000000);
+ test_one_floatsidf(-1, 0xbff0000000000000);
+ test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000);
+ test_one_floatsidf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc1e0000000000000);
+}
+
+test "floatsisf" {
+ test_one_floatsisf(0, 0x00000000);
+ test_one_floatsisf(1, 0x3f800000);
+ test_one_floatsisf(-1, 0xbf800000);
+ test_one_floatsisf(0x7FFFFFFF, 0x4f000000);
+ test_one_floatsisf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xcf000000);
+}
+
+test "floatsitf" {
+ test_one_floatsitf(0, 0);
+ test_one_floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000);
+ test_one_floatsitf(0x12345678, 0x401b2345678000000000000000000000);
+ test_one_floatsitf(-0x12345678, 0xc01b2345678000000000000000000000);
+ test_one_floatsitf(@bitCast(i32, @intCast(u32, 0xffffffff)), 0xbfff0000000000000000000000000000);
+ test_one_floatsitf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc01e0000000000000000000000000000);
+}
diff --git a/std/special/compiler_rt/floatundidf.zig b/std/special/compiler_rt/floatundidf.zig
new file mode 100644
index 0000000000..68759a2acd
--- /dev/null
+++ b/std/special/compiler_rt/floatundidf.zig
@@ -0,0 +1,24 @@
+const builtin = @import("builtin");
+const std = @import("std");
+
+const twop52: f64 = 0x1.0p52;
+const twop84: f64 = 0x1.0p84;
+const twop84_plus_twop52: f64 = 0x1.00000001p84;
+
+pub extern fn __floatundidf(a: u64) f64 {
+ @setRuntimeSafety(builtin.is_test);
+
+ if (a == 0) return 0;
+
+ var high = @bitCast(u64, twop84);
+ var low = @bitCast(u64, twop52);
+
+ high |= a >> 32;
+ low |= a & 0xFFFFFFFF;
+
+ return (@bitCast(f64, high) - twop84_plus_twop52) + @bitCast(f64, low);
+}
+
+test "import floatundidf" {
+ _ = @import("floatundidf_test.zig");
+}
diff --git a/std/special/compiler_rt/floatundidf_test.zig b/std/special/compiler_rt/floatundidf_test.zig
new file mode 100644
index 0000000000..084ada51c9
--- /dev/null
+++ b/std/special/compiler_rt/floatundidf_test.zig
@@ -0,0 +1,50 @@
+const __floatundidf = @import("floatundidf.zig").__floatundidf;
+const testing = @import("std").testing;
+
+fn test__floatundidf(a: u64, expected: f64) void {
+ const r = __floatundidf(a);
+ testing.expect(r == expected);
+}
+
+test "floatundidf" {
+ test__floatundidf(0, 0.0);
+ test__floatundidf(1, 1.0);
+ test__floatundidf(2, 2.0);
+ test__floatundidf(20, 20.0);
+ test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
+ test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
+ test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
+ test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
+ test__floatundidf(0x8000008000000000, 0x1.000001p+63);
+ test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63);
+ test__floatundidf(0x8000010000000000, 0x1.000002p+63);
+ test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63);
+ test__floatundidf(0x8000000000000000, 0x1p+63);
+ test__floatundidf(0x8000000000000001, 0x1p+63);
+ test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
+ test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
+ test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
+ test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
+ test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
+ test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
+ test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
+ test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
+ test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
+ test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
+ test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
+ test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
+ test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
+ test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
+ test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
+ test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
+ test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
+}
diff --git a/std/special/compiler_rt/floatunsidf.zig b/std/special/compiler_rt/floatunsidf.zig
new file mode 100644
index 0000000000..db02894448
--- /dev/null
+++ b/std/special/compiler_rt/floatunsidf.zig
@@ -0,0 +1,33 @@
+const builtin = @import("builtin");
+const std = @import("std");
+const maxInt = std.math.maxInt;
+
+const implicitBit = u64(1) << 52;
+
+pub extern fn __floatunsidf(arg: u32) f64 {
+ @setRuntimeSafety(builtin.is_test);
+
+ if (arg == 0) return 0.0;
+
+ // The exponent is the width of abs(a)
+ const exp = u64(31) - @clz(arg);
+ // Shift a into the significand field and clear the implicit bit
+ const shift = @intCast(u6, 52 - exp);
+ const mant = u64(arg) << shift ^ implicitBit;
+
+ return @bitCast(f64, mant | (exp + 1023) << 52);
+}
+
+fn test_one_floatunsidf(a: u32, expected: u64) void {
+ const r = __floatunsidf(a);
+ std.testing.expect(@bitCast(u64, r) == expected);
+}
+
+test "floatsidf" {
+ // Test the produced bit pattern
+ test_one_floatunsidf(0, 0x0000000000000000);
+ test_one_floatunsidf(1, 0x3ff0000000000000);
+ test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000);
+ test_one_floatunsidf(@intCast(u32, 0x80000000), 0x41e0000000000000);
+ test_one_floatunsidf(@intCast(u32, 0xFFFFFFFF), 0x41efffffffe00000);
+}
diff --git a/std/special/compiler_rt/lshrti3.zig b/std/special/compiler_rt/lshrti3.zig
new file mode 100644
index 0000000000..329968ae40
--- /dev/null
+++ b/std/special/compiler_rt/lshrti3.zig
@@ -0,0 +1,41 @@
+const builtin = @import("builtin");
+const compiler_rt = @import("../compiler_rt.zig");
+
+pub extern fn __lshrti3(a: i128, b: i32) i128 {
+ var input = twords{ .all = a };
+ var result: twords = undefined;
+
+ if (b > 63) {
+ // 64 <= b < 128
+ result.s.low = input.s.high >> @intCast(u6, b - 64);
+ result.s.high = 0;
+ } else {
+ // 0 <= b < 64
+ if (b == 0) return a;
+ result.s.low = input.s.high << @intCast(u6, 64 - b);
+ result.s.low |= input.s.low >> @intCast(u6, b);
+ result.s.high = input.s.high >> @intCast(u6, b);
+ }
+
+ return result.all;
+}
+
+const twords = extern union {
+ all: i128,
+ s: S,
+
+ const S = if (builtin.endian == builtin.Endian.Little)
+ struct {
+ low: u64,
+ high: u64,
+ }
+ else
+ struct {
+ high: u64,
+ low: u64,
+ };
+};
+
+test "import lshrti3" {
+ _ = @import("lshrti3_test.zig");
+}
diff --git a/std/special/compiler_rt/lshrti3_test.zig b/std/special/compiler_rt/lshrti3_test.zig
new file mode 100644
index 0000000000..60f83d816e
--- /dev/null
+++ b/std/special/compiler_rt/lshrti3_test.zig
@@ -0,0 +1,46 @@
+const __lshrti3 = @import("lshrti3.zig").__lshrti3;
+const testing = @import("std").testing;
+
+fn test__lshrti3(a: i128, b: i32, expected: i128) void {
+ const x = __lshrti3(a, b);
+ testing.expect(x == expected);
+}
+
+test "lshrti3" {
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 0, @bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 1, @bitCast(i128, @intCast(u128, 0x7F6E5D4C3B2A190AFF6E5D4C3B2A190A)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 2, @bitCast(i128, @intCast(u128, 0x3FB72EA61D950C857FB72EA61D950C85)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 3, @bitCast(i128, @intCast(u128, 0x1FDB97530ECA8642BFDB97530ECA8642)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 4, @bitCast(i128, @intCast(u128, 0x0FEDCBA9876543215FEDCBA987654321)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 28, @bitCast(i128, @intCast(u128, 0x0000000FEDCBA9876543215FEDCBA987)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 29, @bitCast(i128, @intCast(u128, 0x00000007F6E5D4C3B2A190AFF6E5D4C3)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 30, @bitCast(i128, @intCast(u128, 0x00000003FB72EA61D950C857FB72EA61)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 31, @bitCast(i128, @intCast(u128, 0x00000001FDB97530ECA8642BFDB97530)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 32, @bitCast(i128, @intCast(u128, 0x00000000FEDCBA9876543215FEDCBA98)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 33, @bitCast(i128, @intCast(u128, 0x000000007F6E5D4C3B2A190AFF6E5D4C)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 34, @bitCast(i128, @intCast(u128, 0x000000003FB72EA61D950C857FB72EA6)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 35, @bitCast(i128, @intCast(u128, 0x000000001FDB97530ECA8642BFDB9753)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 36, @bitCast(i128, @intCast(u128, 0x000000000FEDCBA9876543215FEDCBA9)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 60, @bitCast(i128, @intCast(u128, 0x000000000000000FEDCBA9876543215F)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 61, @bitCast(i128, @intCast(u128, 0x0000000000000007F6E5D4C3B2A190AF)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 62, @bitCast(i128, @intCast(u128, 0x0000000000000003FB72EA61D950C857)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 63, @bitCast(i128, @intCast(u128, 0x0000000000000001FDB97530ECA8642B)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 64, @bitCast(i128, @intCast(u128, 0x0000000000000000FEDCBA9876543215)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 65, @bitCast(i128, @intCast(u128, 0x00000000000000007F6E5D4C3B2A190A)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 66, @bitCast(i128, @intCast(u128, 0x00000000000000003FB72EA61D950C85)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 67, @bitCast(i128, @intCast(u128, 0x00000000000000001FDB97530ECA8642)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 68, @bitCast(i128, @intCast(u128, 0x00000000000000000FEDCBA987654321)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 92, @bitCast(i128, @intCast(u128, 0x00000000000000000000000FEDCBA987)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 93, @bitCast(i128, @intCast(u128, 0x000000000000000000000007F6E5D4C3)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 94, @bitCast(i128, @intCast(u128, 0x000000000000000000000003FB72EA61)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 95, @bitCast(i128, @intCast(u128, 0x000000000000000000000001FDB97530)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 96, @bitCast(i128, @intCast(u128, 0x000000000000000000000000FEDCBA98)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 97, @bitCast(i128, @intCast(u128, 0x0000000000000000000000007F6E5D4C)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 98, @bitCast(i128, @intCast(u128, 0x0000000000000000000000003FB72EA6)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 99, @bitCast(i128, @intCast(u128, 0x0000000000000000000000001FDB9753)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 100, @bitCast(i128, @intCast(u128, 0x0000000000000000000000000FEDCBA9)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 124, @bitCast(i128, @intCast(u128, 0x0000000000000000000000000000000F)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 125, @bitCast(i128, @intCast(u128, 0x00000000000000000000000000000007)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 126, @bitCast(i128, @intCast(u128, 0x00000000000000000000000000000003)));
+ test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 127, @bitCast(i128, @intCast(u128, 0x00000000000000000000000000000001)));
+}
diff --git a/std/special/compiler_rt/modti3.zig b/std/special/compiler_rt/modti3.zig
index 03222cadf5..16f2f38ba3 100644
--- a/std/special/compiler_rt/modti3.zig
+++ b/std/special/compiler_rt/modti3.zig
@@ -20,9 +20,9 @@ pub extern fn __modti3(a: i128, b: i128) i128 {
return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -1
}
-pub extern fn __modti3_windows_x86_64(a: *const i128, b: *const i128) void {
- @setRuntimeSafety(builtin.is_test);
- compiler_rt.setXmm0(i128, __modti3(a.*, b.*));
+const v128 = @Vector(2, u64);
+pub extern fn __modti3_windows_x86_64(a: v128, b: v128) v128 {
+ return @bitCast(v128, @inlineCall(__modti3, @bitCast(i128, a), @bitCast(i128, b)));
}
test "import modti3" {
diff --git a/std/special/compiler_rt/mulodi4.zig b/std/special/compiler_rt/mulodi4.zig
new file mode 100644
index 0000000000..82e9ef3253
--- /dev/null
+++ b/std/special/compiler_rt/mulodi4.zig
@@ -0,0 +1,44 @@
+const builtin = @import("builtin");
+const compiler_rt = @import("../compiler_rt.zig");
+const maxInt = std.math.maxInt;
+const minInt = std.math.minInt;
+
+pub extern fn __mulodi4(a: i64, b: i64, overflow: *c_int) i64 {
+ @setRuntimeSafety(builtin.is_test);
+
+ const min = @bitCast(i64, u64(1 << (i64.bit_count - 1)));
+ const max = ~min;
+
+ overflow.* = 0;
+ const result = a *% b;
+
+ // Edge cases
+ if (a == min) {
+ if (b != 0 and b != 1) overflow.* = 1;
+ return result;
+ }
+ if (b == min) {
+ if (a != 0 and a != 1) overflow.* = 1;
+ return result;
+ }
+
+ // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
+ const abs_a = (a ^ (a >> 63)) -% (a >> 63);
+ const abs_b = (b ^ (b >> 63)) -% (b >> 63);
+
+ // Unitary magnitude, cannot have overflow
+ if (abs_a < 2 or abs_b < 2) return result;
+
+ // Compare the signs of the operands
+ if ((a ^ b) >> 63 != 0) {
+ if (abs_a > @divTrunc(max, abs_b)) overflow.* = 1;
+ } else {
+ if (abs_a > @divTrunc(min, -abs_b)) overflow.* = 1;
+ }
+
+ return result;
+}
+
+test "import mulodi4" {
+ _ = @import("mulodi4_test.zig");
+}
diff --git a/std/special/compiler_rt/mulodi4_test.zig b/std/special/compiler_rt/mulodi4_test.zig
new file mode 100644
index 0000000000..7575c77044
--- /dev/null
+++ b/std/special/compiler_rt/mulodi4_test.zig
@@ -0,0 +1,85 @@
+const __mulodi4 = @import("mulodi4.zig").__mulodi4;
+const testing = @import("std").testing;
+
+fn test__mulodi4(a: i64, b: i64, expected: i64, expected_overflow: c_int) void {
+ var overflow: c_int = undefined;
+ const x = __mulodi4(a, b, &overflow);
+ testing.expect(overflow == expected_overflow and (expected_overflow != 0 or x == expected));
+}
+
+test "mulodi4" {
+ test__mulodi4(0, 0, 0, 0);
+ test__mulodi4(0, 1, 0, 0);
+ test__mulodi4(1, 0, 0, 0);
+ test__mulodi4(0, 10, 0, 0);
+ test__mulodi4(10, 0, 0, 0);
+ test__mulodi4(0, 81985529216486895, 0, 0);
+ test__mulodi4(81985529216486895, 0, 0, 0);
+
+ test__mulodi4(0, -1, 0, 0);
+ test__mulodi4(-1, 0, 0, 0);
+ test__mulodi4(0, -10, 0, 0);
+ test__mulodi4(-10, 0, 0, 0);
+ test__mulodi4(0, -81985529216486895, 0, 0);
+ test__mulodi4(-81985529216486895, 0, 0, 0);
+
+ test__mulodi4(1, 1, 1, 0);
+ test__mulodi4(1, 10, 10, 0);
+ test__mulodi4(10, 1, 10, 0);
+ test__mulodi4(1, 81985529216486895, 81985529216486895, 0);
+ test__mulodi4(81985529216486895, 1, 81985529216486895, 0);
+
+ test__mulodi4(1, -1, -1, 0);
+ test__mulodi4(1, -10, -10, 0);
+ test__mulodi4(-10, 1, -10, 0);
+ test__mulodi4(1, -81985529216486895, -81985529216486895, 0);
+ test__mulodi4(-81985529216486895, 1, -81985529216486895, 0);
+
+ test__mulodi4(3037000499, 3037000499, 9223372030926249001, 0);
+ test__mulodi4(-3037000499, 3037000499, -9223372030926249001, 0);
+ test__mulodi4(3037000499, -3037000499, -9223372030926249001, 0);
+ test__mulodi4(-3037000499, -3037000499, 9223372030926249001, 0);
+
+ test__mulodi4(4398046511103, 2097152, 9223372036852678656, 0);
+ test__mulodi4(-4398046511103, 2097152, -9223372036852678656, 0);
+ test__mulodi4(4398046511103, -2097152, -9223372036852678656, 0);
+ test__mulodi4(-4398046511103, -2097152, 9223372036852678656, 0);
+
+ test__mulodi4(2097152, 4398046511103, 9223372036852678656, 0);
+ test__mulodi4(-2097152, 4398046511103, -9223372036852678656, 0);
+ test__mulodi4(2097152, -4398046511103, -9223372036852678656, 0);
+ test__mulodi4(-2097152, -4398046511103, 9223372036852678656, 0);
+
+ test__mulodi4(0x7FFFFFFFFFFFFFFF, -2, 2, 1);
+ test__mulodi4(-2, 0x7FFFFFFFFFFFFFFF, 2, 1);
+ test__mulodi4(0x7FFFFFFFFFFFFFFF, -1, @bitCast(i64, u64(0x8000000000000001)), 0);
+ test__mulodi4(-1, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, u64(0x8000000000000001)), 0);
+ test__mulodi4(0x7FFFFFFFFFFFFFFF, 0, 0, 0);
+ test__mulodi4(0, 0x7FFFFFFFFFFFFFFF, 0, 0);
+ test__mulodi4(0x7FFFFFFFFFFFFFFF, 1, 0x7FFFFFFFFFFFFFFF, 0);
+ test__mulodi4(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF, 0);
+ test__mulodi4(0x7FFFFFFFFFFFFFFF, 2, @bitCast(i64, u64(0x8000000000000001)), 1);
+ test__mulodi4(2, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, u64(0x8000000000000001)), 1);
+
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), -2, @bitCast(i64, u64(0x8000000000000000)), 1);
+ test__mulodi4(-2, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 1);
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), -1, @bitCast(i64, u64(0x8000000000000000)), 1);
+ test__mulodi4(-1, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 1);
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), 0, 0, 0);
+ test__mulodi4(0, @bitCast(i64, u64(0x8000000000000000)), 0, 0);
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), 1, @bitCast(i64, u64(0x8000000000000000)), 0);
+ test__mulodi4(1, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 0);
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), 2, @bitCast(i64, u64(0x8000000000000000)), 1);
+ test__mulodi4(2, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 1);
+
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), -2, @bitCast(i64, u64(0x8000000000000001)), 1);
+ test__mulodi4(-2, @bitCast(i64, u64(0x8000000000000001)), @bitCast(i64, u64(0x8000000000000001)), 1);
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), -1, 0x7FFFFFFFFFFFFFFF, 0);
+ test__mulodi4(-1, @bitCast(i64, u64(0x8000000000000001)), 0x7FFFFFFFFFFFFFFF, 0);
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), 0, 0, 0);
+ test__mulodi4(0, @bitCast(i64, u64(0x8000000000000001)), 0, 0);
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), 1, @bitCast(i64, u64(0x8000000000000001)), 0);
+ test__mulodi4(1, @bitCast(i64, u64(0x8000000000000001)), @bitCast(i64, u64(0x8000000000000001)), 0);
+ test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), 2, @bitCast(i64, u64(0x8000000000000000)), 1);
+ test__mulodi4(2, @bitCast(i64, u64(0x8000000000000001)), @bitCast(i64, u64(0x8000000000000000)), 1);
+}
diff --git a/std/special/compiler_rt/muloti4.zig b/std/special/compiler_rt/muloti4.zig
index fd6855072b..ccde8e3e6c 100644
--- a/std/special/compiler_rt/muloti4.zig
+++ b/std/special/compiler_rt/muloti4.zig
@@ -1,4 +1,3 @@
-const udivmod = @import("udivmod.zig").udivmod;
const builtin = @import("builtin");
const compiler_rt = @import("../compiler_rt.zig");
@@ -33,11 +32,11 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {
}
if (sa == sb) {
- if (abs_a > @divFloor(max, abs_b)) {
+ if (abs_a > @divTrunc(max, abs_b)) {
overflow.* = 1;
}
} else {
- if (abs_a > @divFloor(min, -abs_b)) {
+ if (abs_a > @divTrunc(min, -abs_b)) {
overflow.* = 1;
}
}
@@ -45,11 +44,6 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {
return r;
}
-pub extern fn __muloti4_windows_x86_64(a: *const i128, b: *const i128, overflow: *c_int) void {
- @setRuntimeSafety(builtin.is_test);
- compiler_rt.setXmm0(i128, __muloti4(a.*, b.*, overflow));
-}
-
test "import muloti4" {
_ = @import("muloti4_test.zig");
}
diff --git a/std/special/compiler_rt/multi3.zig b/std/special/compiler_rt/multi3.zig
index a0c84adaf4..799b1f575d 100644
--- a/std/special/compiler_rt/multi3.zig
+++ b/std/special/compiler_rt/multi3.zig
@@ -14,9 +14,9 @@ pub extern fn __multi3(a: i128, b: i128) i128 {
return r.all;
}
-pub extern fn __multi3_windows_x86_64(a: *const i128, b: *const i128) void {
- @setRuntimeSafety(builtin.is_test);
- compiler_rt.setXmm0(i128, __multi3(a.*, b.*));
+const v128 = @Vector(2, u64);
+pub extern fn __multi3_windows_x86_64(a: v128, b: v128) v128 {
+ return @bitCast(v128, @inlineCall(__multi3, @bitCast(i128, a), @bitCast(i128, b)));
}
fn __mulddi3(a: u64, b: u64) i128 {
diff --git a/std/special/compiler_rt/stack_probe.zig b/std/special/compiler_rt/stack_probe.zig
new file mode 100644
index 0000000000..71a349d2a8
--- /dev/null
+++ b/std/special/compiler_rt/stack_probe.zig
@@ -0,0 +1,206 @@
+const builtin = @import("builtin");
+
+// Zig's own stack-probe routine (available only on x86 and x86_64)
+pub nakedcc fn zig_probe_stack() void {
+ @setRuntimeSafety(false);
+
+ // Versions of the Linux kernel before 5.1 treat any access below SP as
+ // invalid so let's update it on the go, otherwise we'll get a segfault
+ // instead of triggering the stack growth.
+
+ switch (builtin.arch) {
+ .x86_64 => {
+ // %rax = probe length, %rsp = stack pointer
+ asm volatile (
+ \\ push %%rcx
+ \\ mov %%rax, %%rcx
+ \\ cmp $0x1000,%%rcx
+ \\ jb 2f
+ \\ 1:
+ \\ sub $0x1000,%%rsp
+ \\ orl $0,16(%%rsp)
+ \\ sub $0x1000,%%rcx
+ \\ cmp $0x1000,%%rcx
+ \\ ja 1b
+ \\ 2:
+ \\ sub %%rcx, %%rsp
+ \\ orl $0,16(%%rsp)
+ \\ add %%rax,%%rsp
+ \\ pop %%rcx
+ \\ ret
+ );
+ },
+ .i386 => {
+ // %eax = probe length, %esp = stack pointer
+ asm volatile (
+ \\ push %%ecx
+ \\ mov %%eax, %%ecx
+ \\ cmp $0x1000,%%ecx
+ \\ jb 2f
+ \\ 1:
+ \\ sub $0x1000,%%esp
+ \\ orl $0,8(%%esp)
+ \\ sub $0x1000,%%ecx
+ \\ cmp $0x1000,%%ecx
+ \\ ja 1b
+ \\ 2:
+ \\ sub %%ecx, %%esp
+ \\ orl $0,8(%%esp)
+ \\ add %%eax,%%esp
+ \\ pop %%ecx
+ \\ ret
+ );
+ },
+ else => { }
+ }
+
+ unreachable;
+}
+
+fn win_probe_stack_only() void {
+ @setRuntimeSafety(false);
+
+ switch (builtin.arch) {
+ .x86_64 => {
+ asm volatile (
+ \\ push %%rcx
+ \\ push %%rax
+ \\ cmp $0x1000,%%rax
+ \\ lea 24(%%rsp),%%rcx
+ \\ jb 1f
+ \\ 2:
+ \\ sub $0x1000,%%rcx
+ \\ test %%rcx,(%%rcx)
+ \\ sub $0x1000,%%rax
+ \\ cmp $0x1000,%%rax
+ \\ ja 2b
+ \\ 1:
+ \\ sub %%rax,%%rcx
+ \\ test %%rcx,(%%rcx)
+ \\ pop %%rax
+ \\ pop %%rcx
+ \\ ret
+ );
+ },
+ .i386 => {
+ asm volatile (
+ \\ push %%ecx
+ \\ push %%eax
+ \\ cmp $0x1000,%%eax
+ \\ lea 12(%%esp),%%ecx
+ \\ jb 1f
+ \\ 2:
+ \\ sub $0x1000,%%ecx
+ \\ test %%ecx,(%%ecx)
+ \\ sub $0x1000,%%eax
+ \\ cmp $0x1000,%%eax
+ \\ ja 2b
+ \\ 1:
+ \\ sub %%eax,%%ecx
+ \\ test %%ecx,(%%ecx)
+ \\ pop %%eax
+ \\ pop %%ecx
+ \\ ret
+ );
+ },
+ else => { }
+ }
+
+ unreachable;
+}
+
+fn win_probe_stack_adjust_sp() void {
+ @setRuntimeSafety(false);
+
+ switch (builtin.arch) {
+ .x86_64 => {
+ asm volatile (
+ \\ push %%rcx
+ \\ cmp $0x1000,%%rax
+ \\ lea 16(%%rsp),%%rcx
+ \\ jb 1f
+ \\ 2:
+ \\ sub $0x1000,%%rcx
+ \\ test %%rcx,(%%rcx)
+ \\ sub $0x1000,%%rax
+ \\ cmp $0x1000,%%rax
+ \\ ja 2b
+ \\ 1:
+ \\ sub %%rax,%%rcx
+ \\ test %%rcx,(%%rcx)
+ \\
+ \\ lea 8(%%rsp),%%rax
+ \\ mov %%rcx,%%rsp
+ \\ mov -8(%%rax),%%rcx
+ \\ push (%%rax)
+ \\ sub %%rsp,%%rax
+ \\ ret
+ );
+ },
+ .i386 => {
+ asm volatile (
+ \\ push %%ecx
+ \\ cmp $0x1000,%%eax
+ \\ lea 8(%%esp),%%ecx
+ \\ jb 1f
+ \\ 2:
+ \\ sub $0x1000,%%ecx
+ \\ test %%ecx,(%%ecx)
+ \\ sub $0x1000,%%eax
+ \\ cmp $0x1000,%%eax
+ \\ ja 2b
+ \\ 1:
+ \\ sub %%eax,%%ecx
+ \\ test %%ecx,(%%ecx)
+ \\
+ \\ lea 4(%%esp),%%eax
+ \\ mov %%ecx,%%esp
+ \\ mov -4(%%eax),%%ecx
+ \\ push (%%eax)
+ \\ sub %%esp,%%eax
+ \\ ret
+ );
+ },
+ else => { },
+ }
+
+ unreachable;
+}
+
+// Windows has a multitude of stack-probing functions with similar names and
+// slightly different behaviours: some behave as alloca() and update the stack
+// pointer after probing the stack, other do not.
+//
+// Function name | Adjusts the SP? |
+// | x86 | x86_64 |
+// ----------------------------------------
+// _chkstk (_alloca) | yes | yes |
+// __chkstk | yes | no |
+// __chkstk_ms | no | no |
+// ___chkstk (__alloca) | yes | yes |
+// ___chkstk_ms | no | no |
+
+pub nakedcc fn _chkstk() void {
+ @setRuntimeSafety(false);
+ @inlineCall(win_probe_stack_adjust_sp);
+}
+pub nakedcc fn __chkstk() void {
+ @setRuntimeSafety(false);
+ switch (builtin.arch) {
+ .i386 => @inlineCall(win_probe_stack_adjust_sp),
+ .x86_64 => @inlineCall(win_probe_stack_only),
+ else => unreachable
+ }
+}
+pub nakedcc fn ___chkstk() void {
+ @setRuntimeSafety(false);
+ @inlineCall(win_probe_stack_adjust_sp);
+}
+pub nakedcc fn __chkstk_ms() void {
+ @setRuntimeSafety(false);
+ @inlineCall(win_probe_stack_only);
+}
+pub nakedcc fn ___chkstk_ms() void {
+ @setRuntimeSafety(false);
+ @inlineCall(win_probe_stack_only);
+}
diff --git a/std/special/compiler_rt/truncXfYf2.zig b/std/special/compiler_rt/truncXfYf2.zig
index b385090a93..e4c4aa38a7 100644
--- a/std/special/compiler_rt/truncXfYf2.zig
+++ b/std/special/compiler_rt/truncXfYf2.zig
@@ -16,6 +16,10 @@ pub extern fn __trunctfdf2(a: f128) f64 {
return truncXfYf2(f64, f128, a);
}
+pub extern fn __truncdfsf2(a: f64) f32 {
+ return truncXfYf2(f32, f64, a);
+}
+
inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);
const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits);
diff --git a/std/special/compiler_rt/truncXfYf2_test.zig b/std/special/compiler_rt/truncXfYf2_test.zig
index 429372c3f1..eccf7efb7e 100644
--- a/std/special/compiler_rt/truncXfYf2_test.zig
+++ b/std/special/compiler_rt/truncXfYf2_test.zig
@@ -200,3 +200,40 @@ test "trunctfdf2" {
test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);
test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);
}
+
+const __truncdfsf2 = @import("truncXfYf2.zig").__truncdfsf2;
+
+fn test__truncdfsf2(a: f64, expected: u32) void {
+ const x = __truncdfsf2(a);
+
+ const rep = @bitCast(u32, x);
+ if (rep == expected) {
+ return;
+ }
+ // test other possible NaN representation(signal NaN)
+ else if (expected == 0x7fc00000) {
+ if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) {
+ return;
+ }
+ }
+
+ @import("std").debug.warn("got 0x{x} wanted 0x{x}\n", rep, expected);
+
+ @panic("__trunctfsf2 test failure");
+}
+
+test "truncdfsf2" {
+ // nan & qnan
+ test__truncdfsf2(@bitCast(f64, u64(0x7ff8000000000000)), 0x7fc00000);
+ test__truncdfsf2(@bitCast(f64, u64(0x7ff0000000000001)), 0x7fc00000);
+ // inf
+ test__truncdfsf2(@bitCast(f64, u64(0x7ff0000000000000)), 0x7f800000);
+ test__truncdfsf2(@bitCast(f64, u64(0xfff0000000000000)), 0xff800000);
+
+ test__truncdfsf2(0.0, 0x0);
+ test__truncdfsf2(1.0, 0x3f800000);
+ test__truncdfsf2(-1.0, 0xbf800000);
+
+ // huge number becomes inf
+ test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);
+}
diff --git a/std/special/compiler_rt/udivmodti4.zig b/std/special/compiler_rt/udivmodti4.zig
index 6a037d3bae..c74dff512d 100644
--- a/std/special/compiler_rt/udivmodti4.zig
+++ b/std/special/compiler_rt/udivmodti4.zig
@@ -7,9 +7,10 @@ pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) u128 {
return udivmod(u128, a, b, maybe_rem);
}
-pub extern fn __udivmodti4_windows_x86_64(a: *const u128, b: *const u128, maybe_rem: ?*u128) void {
+const v128 = @Vector(2, u64);
+pub extern fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) v128 {
@setRuntimeSafety(builtin.is_test);
- compiler_rt.setXmm0(u128, udivmod(u128, a.*, b.*, maybe_rem));
+ return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), maybe_rem));
}
test "import udivmodti4" {
diff --git a/std/special/compiler_rt/udivti3.zig b/std/special/compiler_rt/udivti3.zig
index 510e21ac1d..ab451859bf 100644
--- a/std/special/compiler_rt/udivti3.zig
+++ b/std/special/compiler_rt/udivti3.zig
@@ -6,7 +6,8 @@ pub extern fn __udivti3(a: u128, b: u128) u128 {
return udivmodti4.__udivmodti4(a, b, null);
}
-pub extern fn __udivti3_windows_x86_64(a: *const u128, b: *const u128) void {
+const v128 = @Vector(2, u64);
+pub extern fn __udivti3_windows_x86_64(a: v128, b: v128) v128 {
@setRuntimeSafety(builtin.is_test);
- udivmodti4.__udivmodti4_windows_x86_64(a, b, null);
+ return udivmodti4.__udivmodti4_windows_x86_64(a, b, null);
}
diff --git a/std/special/compiler_rt/umodti3.zig b/std/special/compiler_rt/umodti3.zig
index 12aca8b036..7add0b2ffe 100644
--- a/std/special/compiler_rt/umodti3.zig
+++ b/std/special/compiler_rt/umodti3.zig
@@ -9,7 +9,7 @@ pub extern fn __umodti3(a: u128, b: u128) u128 {
return r;
}
-pub extern fn __umodti3_windows_x86_64(a: *const u128, b: *const u128) void {
- @setRuntimeSafety(builtin.is_test);
- compiler_rt.setXmm0(u128, __umodti3(a.*, b.*));
+const v128 = @Vector(2, u64);
+pub extern fn __umodti3_windows_x86_64(a: v128, b: v128) v128 {
+ return @bitCast(v128, @inlineCall(__umodti3, @bitCast(u128, a), @bitCast(u128, b)));
}
diff --git a/std/special/panic.zig b/std/special/panic.zig
index 7cb7143955..40b1d5e7fe 100644
--- a/std/special/panic.zig
+++ b/std/special/panic.zig
@@ -9,10 +9,15 @@ const std = @import("std");
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
@setCold(true);
switch (builtin.os) {
- // TODO: fix panic in zen.
+ // TODO: fix panic in zen
builtin.Os.freestanding, builtin.Os.zen => {
while (true) {}
},
+ builtin.Os.wasi => {
+ std.debug.warn("{}", msg);
+ _ = std.os.wasi.proc_raise(std.os.wasi.SIGABRT);
+ unreachable;
+ },
builtin.Os.uefi => {
// TODO look into using the debug info and logging helpful messages
std.os.abort();
diff --git a/std/special/test_runner.zig b/std/special/test_runner.zig
index 36b098bd61..db01293059 100644
--- a/std/special/test_runner.zig
+++ b/std/special/test_runner.zig
@@ -8,7 +8,7 @@ pub fn main() !void {
var ok_count: usize = 0;
var skip_count: usize = 0;
for (test_fn_list) |test_fn, i| {
- warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
+ warn("{}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
if (test_fn.func()) |_| {
ok_count += 1;
diff --git a/std/std.zig b/std/std.zig
index f68edf6435..8ec042fdb8 100644
--- a/std/std.zig
+++ b/std/std.zig
@@ -9,6 +9,10 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
pub const HashMap = @import("hash_map.zig").HashMap;
pub const LinkedList = @import("linked_list.zig").LinkedList;
pub const Mutex = @import("mutex.zig").Mutex;
+pub const PackedIntArrayEndian = @import("packed_int_array.zig").PackedIntArrayEndian;
+pub const PackedIntArray = @import("packed_int_array.zig").PackedIntArray;
+pub const PackedIntSliceEndian = @import("packed_int_array.zig").PackedIntSliceEndian;
+pub const PackedIntSlice = @import("packed_int_array.zig").PackedIntSlice;
pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue;
pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
@@ -87,6 +91,7 @@ test "std" {
_ = @import("net.zig");
_ = @import("os.zig");
_ = @import("pdb.zig");
+ _ = @import("packed_int_array.zig");
_ = @import("priority_queue.zig");
_ = @import("rand.zig");
_ = @import("sort.zig");
@@ -94,4 +99,6 @@ test "std" {
_ = @import("unicode.zig");
_ = @import("valgrind.zig");
_ = @import("zig.zig");
+
+ _ = @import("debug/leb128.zig");
}
diff --git a/std/zig/ast.zig b/std/zig/ast.zig
index 77e487f1ef..75a811220f 100644
--- a/std/zig/ast.zig
+++ b/std/zig/ast.zig
@@ -18,7 +18,11 @@ pub const Tree = struct {
pub const ErrorList = SegmentedList(Error, 0);
pub fn deinit(self: *Tree) void {
- self.arena_allocator.deinit();
+ // Here we copy the arena allocator into stack memory, because
+ // otherwise it would destroy itself while it was still working.
+ var arena_allocator = self.arena_allocator;
+ arena_allocator.deinit();
+ // self is destroyed
}
pub fn renderError(self: *Tree, parse_error: *Error, stream: var) !void {
@@ -551,7 +555,6 @@ pub const Node = struct {
doc_comments: ?*DocComment,
decls: DeclList,
eof_token: TokenIndex,
- shebang: ?TokenIndex,
pub const DeclList = SegmentedList(*Node, 4);
@@ -563,7 +566,6 @@ pub const Node = struct {
}
pub fn firstToken(self: *const Root) TokenIndex {
- if (self.shebang) |shebang| return shebang;
return if (self.decls.len == 0) self.eof_token else (self.decls.at(0).*).firstToken();
}
@@ -2307,7 +2309,6 @@ test "iterate" {
.doc_comments = null,
.decls = Node.Root.DeclList.init(std.debug.global_allocator),
.eof_token = 0,
- .shebang = null,
};
var base = &root.base;
testing.expect(base.iterate(0) == null);
diff --git a/std/zig/parse.zig b/std/zig/parse.zig
index 96aec714ab..efe83a7dac 100644
--- a/std/zig/parse.zig
+++ b/std/zig/parse.zig
@@ -9,7 +9,7 @@ const Error = ast.Error;
/// Result should be freed with tree.deinit() when there are
/// no more references to any of the tokens or nodes.
-pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
+pub fn parse(allocator: *mem.Allocator, source: []const u8) !*ast.Tree {
var tree_arena = std.heap.ArenaAllocator.init(allocator);
errdefer tree_arena.deinit();
@@ -22,12 +22,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.base = ast.Node{ .id = ast.Node.Id.Root },
.decls = ast.Node.Root.DeclList.init(arena),
.doc_comments = null,
- .shebang = null,
// initialized when we get the eof token
.eof_token = undefined,
};
- var tree = ast.Tree{
+ const tree = try arena.create(ast.Tree);
+ tree.* = ast.Tree{
.source = source,
.root_node = root_node,
.arena_allocator = tree_arena,
@@ -43,15 +43,6 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
var tok_it = tree.tokens.iterator(0);
- // skip over shebang line
- shebang: {
- const shebang_tok_index = tok_it.index;
- const shebang_tok_ptr = tok_it.peek() orelse break :shebang;
- if (shebang_tok_ptr.id != Token.Id.ShebangLine) break :shebang;
- root_node.shebang = shebang_tok_index;
- _ = tok_it.next();
- }
-
// skip over line comments at the top of the file
while (true) {
const next_tok = tok_it.peek() orelse break;
@@ -67,9 +58,9 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
switch (state) {
State.TopLevel => {
- const comments = try eatDocComments(arena, &tok_it, &tree);
+ const comments = try eatDocComments(arena, &tok_it, tree);
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -150,7 +141,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
else => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
stack.append(State.TopLevel) catch unreachable;
try stack.append(State{
.TopLevelExtern = TopLevelDeclCtx{
@@ -166,7 +157,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.TopLevelExtern => |ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -201,7 +192,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
else => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
stack.append(State{ .TopLevelDecl = ctx }) catch unreachable;
continue;
},
@@ -209,11 +200,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.TopLevelLibname => |ctx| {
const lib_name = blk: {
- const lib_name_token = nextToken(&tok_it, &tree);
+ const lib_name_token = nextToken(&tok_it, tree);
const lib_name_token_index = lib_name_token.index;
const lib_name_token_ptr = lib_name_token.ptr;
- break :blk (try parseStringLiteral(arena, &tok_it, lib_name_token_ptr, lib_name_token_index, &tree)) orelse {
- prevToken(&tok_it, &tree);
+ break :blk (try parseStringLiteral(arena, &tok_it, lib_name_token_ptr, lib_name_token_index, tree)) orelse {
+ prevToken(&tok_it, tree);
break :blk null;
};
};
@@ -230,7 +221,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.ThreadLocal => |ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -256,7 +247,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.TopLevelDecl => |ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -397,7 +388,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.TopLevelExternOrField => |ctx| {
- if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| {
+ if (eatToken(&tok_it, tree, Token.Id.Identifier)) |identifier| {
const node = try arena.create(ast.Node.StructField);
node.* = ast.Node.StructField{
.base = ast.Node{ .id = ast.Node.Id.StructField },
@@ -434,11 +425,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.FieldInitValue => |ctx| {
- const eq_tok = nextToken(&tok_it, &tree);
+ const eq_tok = nextToken(&tok_it, tree);
const eq_tok_index = eq_tok.index;
const eq_tok_ptr = eq_tok.ptr;
if (eq_tok_ptr.id != Token.Id.Equal) {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
stack.append(State{ .Expression = ctx }) catch unreachable;
@@ -446,7 +437,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.ContainerKind => |ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
const node = try arena.create(ast.Node.ContainerDecl);
@@ -479,7 +470,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.ContainerInitArgStart => |container_decl| {
- if (eatToken(&tok_it, &tree, Token.Id.LParen) == null) {
+ if (eatToken(&tok_it, tree, Token.Id.LParen) == null) {
continue;
}
@@ -489,24 +480,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.ContainerInitArg => |container_decl| {
- const init_arg_token = nextToken(&tok_it, &tree);
+ const init_arg_token = nextToken(&tok_it, tree);
const init_arg_token_index = init_arg_token.index;
const init_arg_token_ptr = init_arg_token.ptr;
switch (init_arg_token_ptr.id) {
Token.Id.Keyword_enum => {
container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Enum = null };
- const lparen_tok = nextToken(&tok_it, &tree);
+ const lparen_tok = nextToken(&tok_it, tree);
const lparen_tok_index = lparen_tok.index;
const lparen_tok_ptr = lparen_tok.ptr;
if (lparen_tok_ptr.id == Token.Id.LParen) {
try stack.append(State{ .ExpectToken = Token.Id.RParen });
try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &container_decl.init_arg_expr.Enum } });
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
}
},
else => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Type = undefined };
stack.append(State{ .Expression = OptionalCtx{ .Required = &container_decl.init_arg_expr.Type } }) catch unreachable;
},
@@ -515,8 +506,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.ContainerDecl => |container_decl| {
- const comments = try eatDocComments(arena, &tok_it, &tree);
- const token = nextToken(&tok_it, &tree);
+ const comments = try eatDocComments(arena, &tok_it, tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -629,6 +620,35 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
});
continue;
},
+ Token.Id.Keyword_comptime => {
+ const block = try arena.create(ast.Node.Block);
+ block.* = ast.Node.Block{
+ .base = ast.Node{ .id = ast.Node.Id.Block },
+ .label = null,
+ .lbrace = undefined,
+ .statements = ast.Node.Block.StatementList.init(arena),
+ .rbrace = undefined,
+ };
+
+ const node = try arena.create(ast.Node.Comptime);
+ node.* = ast.Node.Comptime{
+ .base = ast.Node{ .id = ast.Node.Id.Comptime },
+ .comptime_token = token_index,
+ .expr = &block.base,
+ .doc_comments = comments,
+ };
+ try container_decl.fields_and_decls.push(&node.base);
+
+ stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
+ try stack.append(State{ .Block = block });
+ try stack.append(State{
+ .ExpectTokenSave = ExpectTokenSave{
+ .id = Token.Id.LBrace,
+ .ptr = &block.lbrace,
+ },
+ });
+ continue;
+ },
Token.Id.RBrace => {
if (comments != null) {
((try tree.errors.addOne())).* = Error{ .UnattachedDocComment = Error.UnattachedDocComment{ .token = token_index } };
@@ -638,7 +658,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
else => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
try stack.append(State{
.TopLevelExtern = TopLevelDeclCtx{
@@ -690,7 +710,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.VarDeclAlign => |var_decl| {
try stack.append(State{ .VarDeclSection = var_decl });
- const next_token = nextToken(&tok_it, &tree);
+ const next_token = nextToken(&tok_it, tree);
const next_token_index = next_token.index;
const next_token_ptr = next_token.ptr;
if (next_token_ptr.id == Token.Id.Keyword_align) {
@@ -700,13 +720,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
},
State.VarDeclSection => |var_decl| {
try stack.append(State{ .VarDeclEq = var_decl });
- const next_token = nextToken(&tok_it, &tree);
+ const next_token = nextToken(&tok_it, tree);
const next_token_index = next_token.index;
const next_token_ptr = next_token.ptr;
if (next_token_ptr.id == Token.Id.Keyword_linksection) {
@@ -716,11 +736,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
},
State.VarDeclEq => |var_decl| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -742,7 +762,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.VarDeclSemiColon => |var_decl| {
- const semicolon_token = nextToken(&tok_it, &tree);
+ const semicolon_token = nextToken(&tok_it, tree);
if (semicolon_token.ptr.id != Token.Id.Semicolon) {
((try tree.errors.addOne())).* = Error{
@@ -756,18 +776,18 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
var_decl.semicolon_token = semicolon_token.index;
- if (eatToken(&tok_it, &tree, Token.Id.DocComment)) |doc_comment_token| {
+ if (eatToken(&tok_it, tree, Token.Id.DocComment)) |doc_comment_token| {
const loc = tree.tokenLocation(semicolon_token.ptr.end, doc_comment_token);
if (loc.line == 0) {
try pushDocComment(arena, doc_comment_token, &var_decl.doc_comments);
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
}
}
},
State.FnDef => |fn_proto| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -796,7 +816,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
try stack.append(State{ .ParamDecl = fn_proto });
try stack.append(State{ .ExpectToken = Token.Id.LParen });
- if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |name_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Identifier)) |name_token| {
fn_proto.name_token = name_token;
}
continue;
@@ -804,7 +824,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.FnProtoAlign => |fn_proto| {
stack.append(State{ .FnProtoSection = fn_proto }) catch unreachable;
- if (eatToken(&tok_it, &tree, Token.Id.Keyword_align)) |align_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Keyword_align)) |align_token| {
try stack.append(State{ .ExpectToken = Token.Id.RParen });
try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.align_expr } });
try stack.append(State{ .ExpectToken = Token.Id.LParen });
@@ -814,7 +834,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.FnProtoSection => |fn_proto| {
stack.append(State{ .FnProtoReturnType = fn_proto }) catch unreachable;
- if (eatToken(&tok_it, &tree, Token.Id.Keyword_linksection)) |align_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Keyword_linksection)) |align_token| {
try stack.append(State{ .ExpectToken = Token.Id.RParen });
try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.section_expr } });
try stack.append(State{ .ExpectToken = Token.Id.LParen });
@@ -822,7 +842,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.FnProtoReturnType => |fn_proto| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -845,7 +865,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
}
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = undefined };
stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.Explicit } }) catch unreachable;
continue;
@@ -854,8 +874,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.ParamDecl => |fn_proto| {
- const comments = try eatDocComments(arena, &tok_it, &tree);
- if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {
+ const comments = try eatDocComments(arena, &tok_it, tree);
+ if (eatToken(&tok_it, tree, Token.Id.RParen)) |_| {
continue;
}
const param_decl = try arena.create(ast.Node.ParamDecl);
@@ -881,9 +901,9 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.ParamDeclAliasOrComptime => |param_decl| {
- if (eatToken(&tok_it, &tree, Token.Id.Keyword_comptime)) |comptime_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Keyword_comptime)) |comptime_token| {
param_decl.comptime_token = comptime_token;
- } else if (eatToken(&tok_it, &tree, Token.Id.Keyword_noalias)) |noalias_token| {
+ } else if (eatToken(&tok_it, tree, Token.Id.Keyword_noalias)) |noalias_token| {
param_decl.noalias_token = noalias_token;
}
continue;
@@ -891,20 +911,20 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.ParamDeclName => |param_decl| {
// TODO: Here, we eat two tokens in one state. This means that we can't have
// comments between these two tokens.
- if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |ident_token| {
- if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| {
+ if (eatToken(&tok_it, tree, Token.Id.Identifier)) |ident_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Colon)) |_| {
param_decl.name_token = ident_token;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
}
}
continue;
},
State.ParamDeclEnd => |ctx| {
- if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {
+ if (eatToken(&tok_it, tree, Token.Id.Ellipsis3)) |ellipsis3| {
ctx.param_decl.var_args_token = ellipsis3;
- switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) {
+ switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RParen)) {
ExpectCommaOrEndResult.end_token => |t| {
if (t == null) {
stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable;
@@ -924,7 +944,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.ParamDeclComma => |fn_proto| {
- switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) {
+ switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RParen)) {
ExpectCommaOrEndResult.end_token => |t| {
if (t == null) {
stack.append(State{ .ParamDecl = fn_proto }) catch unreachable;
@@ -939,7 +959,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.MaybeLabeledExpression => |ctx| {
- if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| {
+ if (eatToken(&tok_it, tree, Token.Id.Colon)) |_| {
stack.append(State{
.LabeledExpression = LabelCtx{
.label = ctx.label,
@@ -953,7 +973,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.LabeledExpression => |ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -1008,13 +1028,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
return tree;
}
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
},
}
},
State.Inline => |ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -1046,7 +1066,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
return tree;
}
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
},
}
@@ -1103,7 +1123,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.Else => |dest| {
- if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Keyword_else)) |else_token| {
const node = try arena.create(ast.Node.Else);
node.* = ast.Node.Else{
.base = ast.Node{ .id = ast.Node.Id.Else },
@@ -1122,7 +1142,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.Block => |block| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -1131,7 +1151,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
else => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
stack.append(State{ .Block = block }) catch unreachable;
try stack.append(State{ .Statement = block });
@@ -1140,7 +1160,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.Statement => |block| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -1197,7 +1217,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
else => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
const statement = try block.statements.addOne();
try stack.append(State{ .Semicolon = statement });
try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } });
@@ -1206,7 +1226,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.ComptimeStatement => |ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -1226,8 +1246,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
else => {
- prevToken(&tok_it, &tree);
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
+ prevToken(&tok_it, tree);
const statement = try ctx.block.statements.addOne();
try stack.append(State{ .Semicolon = statement });
try stack.append(State{ .Expression = OptionalCtx{ .Required = statement } });
@@ -1245,11 +1265,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.AsmOutputItems => |items| {
- const lbracket = nextToken(&tok_it, &tree);
+ const lbracket = nextToken(&tok_it, tree);
const lbracket_index = lbracket.index;
const lbracket_ptr = lbracket.ptr;
if (lbracket_ptr.id != Token.Id.LBracket) {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
@@ -1280,7 +1300,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.AsmOutputReturnOrType => |node| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -1300,11 +1320,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.AsmInputItems => |items| {
- const lbracket = nextToken(&tok_it, &tree);
+ const lbracket = nextToken(&tok_it, tree);
const lbracket_index = lbracket.index;
const lbracket_ptr = lbracket.ptr;
if (lbracket_ptr.id != Token.Id.LBracket) {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
@@ -1335,16 +1355,16 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.AsmClobberItems => |items| {
- while (eatToken(&tok_it, &tree, Token.Id.StringLiteral)) |strlit| {
+ while (eatToken(&tok_it, tree, Token.Id.StringLiteral)) |strlit| {
try items.push(strlit);
- if (eatToken(&tok_it, &tree, Token.Id.Comma) == null)
+ if (eatToken(&tok_it, tree, Token.Id.Comma) == null)
break;
}
continue;
},
State.ExprListItemOrEnd => |list_state| {
- if (eatToken(&tok_it, &tree, list_state.end)) |token_index| {
+ if (eatToken(&tok_it, tree, list_state.end)) |token_index| {
(list_state.ptr).* = token_index;
continue;
}
@@ -1354,7 +1374,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.ExprListCommaOrEnd => |list_state| {
- switch (expectCommaOrEnd(&tok_it, &tree, list_state.end)) {
+ switch (expectCommaOrEnd(&tok_it, tree, list_state.end)) {
ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
(list_state.ptr).* = end;
continue;
@@ -1369,7 +1389,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.FieldInitListItemOrEnd => |list_state| {
- if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| {
+ if (eatToken(&tok_it, tree, Token.Id.RBrace)) |rbrace| {
(list_state.ptr).* = rbrace;
continue;
}
@@ -1401,7 +1421,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.FieldInitListCommaOrEnd => |list_state| {
- switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {
+ switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RBrace)) {
ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
(list_state.ptr).* = end;
continue;
@@ -1416,17 +1436,17 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.FieldListCommaOrEnd => |field_ctx| {
- const end_token = nextToken(&tok_it, &tree);
+ const end_token = nextToken(&tok_it, tree);
const end_token_index = end_token.index;
const end_token_ptr = end_token.ptr;
switch (end_token_ptr.id) {
Token.Id.Comma => {
- if (eatToken(&tok_it, &tree, Token.Id.DocComment)) |doc_comment_token| {
+ if (eatToken(&tok_it, tree, Token.Id.DocComment)) |doc_comment_token| {
const loc = tree.tokenLocation(end_token_ptr.end, doc_comment_token);
if (loc.line == 0) {
try pushDocComment(arena, doc_comment_token, field_ctx.doc_comments);
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
}
}
@@ -1449,7 +1469,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.ErrorTagListItemOrEnd => |list_state| {
- if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| {
+ if (eatToken(&tok_it, tree, Token.Id.RBrace)) |rbrace| {
(list_state.ptr).* = rbrace;
continue;
}
@@ -1461,7 +1481,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.ErrorTagListCommaOrEnd => |list_state| {
- switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {
+ switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RBrace)) {
ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
(list_state.ptr).* = end;
continue;
@@ -1476,12 +1496,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.SwitchCaseOrEnd => |list_state| {
- if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| {
+ if (eatToken(&tok_it, tree, Token.Id.RBrace)) |rbrace| {
(list_state.ptr).* = rbrace;
continue;
}
- const comments = try eatDocComments(arena, &tok_it, &tree);
+ const comments = try eatDocComments(arena, &tok_it, tree);
const node = try arena.create(ast.Node.SwitchCase);
node.* = ast.Node.SwitchCase{
.base = ast.Node{ .id = ast.Node.Id.SwitchCase },
@@ -1500,7 +1520,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.SwitchCaseCommaOrEnd => |list_state| {
- switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {
+ switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RBrace)) {
ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
(list_state.ptr).* = end;
continue;
@@ -1516,7 +1536,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.SwitchCaseFirstItem => |switch_case| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (token_ptr.id == Token.Id.Keyword_else) {
@@ -1535,26 +1555,26 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
});
continue;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;
try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });
continue;
}
},
State.SwitchCaseItemOrEnd => |switch_case| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
if (token.ptr.id == Token.Id.EqualAngleBracketRight) {
switch_case.arrow_token = token.index;
continue;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;
try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });
continue;
}
},
State.SwitchCaseItemCommaOrEnd => |switch_case| {
- switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.EqualAngleBracketRight)) {
+ switch (expectCommaOrEnd(&tok_it, tree, Token.Id.EqualAngleBracketRight)) {
ExpectCommaOrEndResult.end_token => |end_token| {
if (end_token) |t| {
switch_case.arrow_token = t;
@@ -1572,14 +1592,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.SuspendBody => |suspend_node| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
switch (token.ptr.id) {
Token.Id.Semicolon => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
},
Token.Id.LBrace => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } });
continue;
},
@@ -1589,7 +1609,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.AsyncAllocator => |async_node| {
- if (eatToken(&tok_it, &tree, Token.Id.AngleBracketLeft) == null) {
+ if (eatToken(&tok_it, tree, Token.Id.AngleBracketLeft) == null) {
continue;
}
@@ -1630,7 +1650,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.ExternType => |ctx| {
- if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Keyword_fn)) |fn_token| {
const fn_proto = try arena.create(ast.Node.FnProto);
fn_proto.* = ast.Node.FnProto{
.base = ast.Node{ .id = ast.Node.Id.FnProto },
@@ -1663,7 +1683,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.SliceOrArrayAccess => |node| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -1696,7 +1716,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.SliceOrArrayType => |node| {
- if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| {
+ if (eatToken(&tok_it, tree, Token.Id.RBracket)) |_| {
node.op = ast.Node.PrefixOp.Op{
.SliceType = ast.Node.PrefixOp.PtrInfo{
.align_info = null,
@@ -1718,7 +1738,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.PtrTypeModifiers => |addr_of_info| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -1768,14 +1788,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
else => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
},
}
},
State.AlignBitRange => |align_info| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
switch (token.ptr.id) {
Token.Id.Colon => {
align_info.bit_range = ast.Node.PrefixOp.PtrInfo.Align.BitRange(undefined);
@@ -1798,7 +1818,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.Payload => |opt_ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (token_ptr.id != Token.Id.Pipe) {
@@ -1812,7 +1832,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
return tree;
}
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
@@ -1835,7 +1855,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.PointerPayload => |opt_ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (token_ptr.id != Token.Id.Pipe) {
@@ -1849,7 +1869,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
return tree;
}
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
@@ -1879,7 +1899,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.PointerIndexPayload => |opt_ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (token_ptr.id != Token.Id.Pipe) {
@@ -1893,7 +1913,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
return tree;
}
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
@@ -1927,7 +1947,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.Expression => |opt_ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -1981,7 +2001,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
else => {
if (!try parseBlockExpr(&stack, arena, opt_ctx, token_ptr.*, token_index)) {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
stack.append(State{ .UnwrapExpressionBegin = opt_ctx }) catch unreachable;
}
continue;
@@ -1996,7 +2016,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.RangeExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {
+ if (eatToken(&tok_it, tree, Token.Id.Ellipsis3)) |ellipsis3| {
const node = try arena.create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
@@ -2019,7 +2039,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.AssignmentExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToAssignment(token_ptr.id)) |ass_id| {
@@ -2036,7 +2056,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });
continue;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
},
@@ -2050,7 +2070,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.UnwrapExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {
@@ -2072,7 +2092,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
continue;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
},
@@ -2086,7 +2106,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.BoolOrExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Keyword_or)) |or_token| {
const node = try arena.create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
@@ -2111,7 +2131,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.BoolAndExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Keyword_and)) |and_token| {
const node = try arena.create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
@@ -2136,7 +2156,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.ComparisonExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToComparison(token_ptr.id)) |comp_id| {
@@ -2153,7 +2173,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
continue;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
},
@@ -2167,7 +2187,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.BinaryOrExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| {
+ if (eatToken(&tok_it, tree, Token.Id.Pipe)) |pipe| {
const node = try arena.create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
@@ -2192,7 +2212,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.BinaryXorExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| {
+ if (eatToken(&tok_it, tree, Token.Id.Caret)) |caret| {
const node = try arena.create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
@@ -2217,7 +2237,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.BinaryAndExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| {
+ if (eatToken(&tok_it, tree, Token.Id.Ampersand)) |ampersand| {
const node = try arena.create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
@@ -2242,7 +2262,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.BitShiftExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {
@@ -2259,7 +2279,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
continue;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
},
@@ -2273,7 +2293,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.AdditionExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToAddition(token_ptr.id)) |add_id| {
@@ -2290,7 +2310,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
continue;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
},
@@ -2304,7 +2324,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.MultiplyExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToMultiply(token_ptr.id)) |mult_id| {
@@ -2321,7 +2341,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
continue;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
},
@@ -2386,7 +2406,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.TypeExprEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| {
+ if (eatToken(&tok_it, tree, Token.Id.Bang)) |bang| {
const node = try arena.create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
@@ -2403,7 +2423,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.PrefixOpExpression => |opt_ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {
@@ -2435,14 +2455,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
continue;
} else {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
stack.append(State{ .SuffixOpExpressionBegin = opt_ctx }) catch unreachable;
continue;
}
},
State.SuffixOpExpressionBegin => |opt_ctx| {
- if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Keyword_async)) |async_token| {
const async_node = try arena.create(ast.Node.AsyncAttribute);
async_node.* = ast.Node.AsyncAttribute{
.base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
@@ -2470,7 +2490,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.SuffixOpExpressionEnd => |opt_ctx| {
const lhs = opt_ctx.get() orelse continue;
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
@@ -2515,7 +2535,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Period => {
- if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Asterisk)) |asterisk_token| {
const node = try arena.create(ast.Node.SuffixOp);
node.* = ast.Node.SuffixOp{
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
@@ -2527,7 +2547,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
continue;
}
- if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| {
+ if (eatToken(&tok_it, tree, Token.Id.QuestionMark)) |question_token| {
const node = try arena.create(ast.Node.SuffixOp);
node.* = ast.Node.SuffixOp{
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
@@ -2554,21 +2574,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
else => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
},
}
},
State.PrimaryExpression => |opt_ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
switch (token.ptr.id) {
Token.Id.IntegerLiteral => {
_ = try createToCtxLiteral(arena, opt_ctx, ast.Node.IntegerLiteral, token.index);
continue;
},
Token.Id.Period => {
- const name_token = nextToken(&tok_it, &tree);
+ const name_token = nextToken(&tok_it, tree);
if (name_token.ptr.id != Token.Id.Identifier) {
((try tree.errors.addOne())).* = Error{
.ExpectedToken = Error.ExpectedToken{
@@ -2624,11 +2644,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.result = null,
};
opt_ctx.store(&node.base);
- const next_token = nextToken(&tok_it, &tree);
+ const next_token = nextToken(&tok_it, tree);
const next_token_index = next_token.index;
const next_token_ptr = next_token.ptr;
if (next_token_ptr.id != Token.Id.Arrow) {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
continue;
}
node.result = ast.Node.PromiseType.Result{
@@ -2640,7 +2660,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {
- opt_ctx.store((try parseStringLiteral(arena, &tok_it, token.ptr, token.index, &tree)) orelse unreachable);
+ opt_ctx.store((try parseStringLiteral(arena, &tok_it, token.ptr, token.index, tree)) orelse unreachable);
continue;
},
Token.Id.LParen => {
@@ -2728,7 +2748,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
stack.append(State{
.ContainerKind = ContainerKindCtx{
.opt_ctx = opt_ctx,
@@ -2845,7 +2865,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
else => {
if (!try parseBlockExpr(&stack, arena, opt_ctx, token.ptr.*, token.index)) {
- prevToken(&tok_it, &tree);
+ prevToken(&tok_it, tree);
if (opt_ctx != OptionalCtx.Optional) {
((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token.index } };
return tree;
@@ -2857,7 +2877,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.ErrorTypeOrSetDecl => |ctx| {
- if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) {
+ if (eatToken(&tok_it, tree, Token.Id.LBrace) == null) {
const node = try arena.create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
@@ -2895,11 +2915,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.StringLiteral => |opt_ctx| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
- opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) orelse {
- prevToken(&tok_it, &tree);
+ opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, tree)) orelse {
+ prevToken(&tok_it, tree);
if (opt_ctx != OptionalCtx.Optional) {
((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token_index } };
return tree;
@@ -2910,13 +2930,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.Identifier => |opt_ctx| {
- if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |ident_token| {
+ if (eatToken(&tok_it, tree, Token.Id.Identifier)) |ident_token| {
_ = try createToCtxLiteral(arena, opt_ctx, ast.Node.Identifier, ident_token);
continue;
}
if (opt_ctx != OptionalCtx.Optional) {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
((try tree.errors.addOne())).* = Error{
@@ -2930,8 +2950,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.ErrorTag => |node_ptr| {
- const comments = try eatDocComments(arena, &tok_it, &tree);
- const ident_token = nextToken(&tok_it, &tree);
+ const comments = try eatDocComments(arena, &tok_it, tree);
+ const ident_token = nextToken(&tok_it, tree);
const ident_token_index = ident_token.index;
const ident_token_ptr = ident_token.ptr;
if (ident_token_ptr.id != Token.Id.Identifier) {
@@ -2955,7 +2975,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.ExpectToken => |token_id| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (token_ptr.id != token_id) {
@@ -2970,7 +2990,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.ExpectTokenSave => |expect_token_save| {
- const token = nextToken(&tok_it, &tree);
+ const token = nextToken(&tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
if (token_ptr.id != expect_token_save.id) {
@@ -2986,7 +3006,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.IfToken => |token_id| {
- if (eatToken(&tok_it, &tree, token_id)) |_| {
+ if (eatToken(&tok_it, tree, token_id)) |_| {
continue;
}
@@ -2994,7 +3014,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.IfTokenSave => |if_token_save| {
- if (eatToken(&tok_it, &tree, if_token_save.id)) |token_index| {
+ if (eatToken(&tok_it, tree, if_token_save.id)) |token_index| {
(if_token_save.ptr).* = token_index;
continue;
}
@@ -3003,7 +3023,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.OptionalTokenSave => |optional_token_save| {
- if (eatToken(&tok_it, &tree, optional_token_save.id)) |token_index| {
+ if (eatToken(&tok_it, tree, optional_token_save.id)) |token_index| {
(optional_token_save.ptr).* = token_index;
continue;
}
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index 955e65eeed..6977e4e6b1 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,10 +1,3 @@
-test "temporary trivial example" {
- try testCanonical(
- \\const x = true;
- \\
- );
-}
-
test "zig fmt: allowzero pointer" {
try testCanonical(
\\const T = [*]allowzero const u8;
@@ -57,14 +50,6 @@ test "zig fmt: linksection" {
);
}
-test "zig fmt: shebang line" {
- try testCanonical(
- \\#!/usr/bin/env zig
- \\pub fn main() void {}
- \\
- );
-}
-
test "zig fmt: correctly move doc comments on struct fields" {
try testTransform(
\\pub const section_64 = extern struct {
@@ -2125,6 +2110,21 @@ test "zig fmt: error return" {
);
}
+test "zig fmt: comptime block in container" {
+ try testCanonical(
+ \\pub fn container() type {
+ \\ return struct {
+ \\ comptime {
+ \\ if (false) {
+ \\ unreachable;
+ \\ }
+ \\ }
+ \\ };
+ \\}
+ \\
+ );
+}
+
const std = @import("std");
const mem = std.mem;
const warn = std.debug.warn;
@@ -2137,7 +2137,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
var stderr_file = try io.getStdErr();
var stderr = &stderr_file.outStream().stream;
- var tree = try std.zig.parse2(allocator, source);
+ const tree = try std.zig.parse(allocator, source);
defer tree.deinit();
var error_it = tree.errors.iterator(0);
@@ -2170,7 +2170,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
errdefer buffer.deinit();
var buffer_out_stream = io.BufferOutStream.init(&buffer);
- anything_changed.* = try std.zig.render(allocator, &buffer_out_stream.stream, &tree);
+ anything_changed.* = try std.zig.render(allocator, &buffer_out_stream.stream, tree);
return buffer.toOwnedSlice();
}
@@ -2215,7 +2215,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
needed_alloc_count,
failing_allocator.allocated_bytes,
failing_allocator.freed_bytes,
- failing_allocator.index,
+ failing_allocator.allocations,
failing_allocator.deallocations,
);
return error.MemoryLeakDetected;
diff --git a/std/zig/render.zig b/std/zig/render.zig
index f1fe23c2a8..cabc4ea9ef 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -73,11 +73,6 @@ fn renderRoot(
) (@typeOf(stream).Child.Error || Error)!void {
var tok_it = tree.tokens.iterator(0);
- // render the shebang line
- if (tree.root_node.shebang) |shebang| {
- try stream.write(tree.tokenSlice(shebang));
- }
-
// render all the line comments at the beginning of the file
while (tok_it.next()) |token| {
if (token.id != Token.Id.LineComment) break;
@@ -753,7 +748,7 @@ fn renderExpression(
counting_stream.bytes_written = 0;
var dummy_col: usize = 0;
try renderExpression(allocator, &counting_stream.stream, tree, 0, &dummy_col, expr.*, Space.None);
- const width = counting_stream.bytes_written;
+ const width = @intCast(usize, counting_stream.bytes_written);
const col = i % row_size;
column_widths[col] = std.math.max(column_widths[col], width);
expr_widths[i] = width;
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index a31605b02a..297673235d 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -3,6 +3,64 @@ const builtin = @import("builtin");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
+ "peer cast then implicit cast const pointer to mutable C pointer",
+ \\export fn func() void {
+ \\ var strValue: [*c]u8 = undefined;
+ \\ strValue = strValue orelse c"";
+ \\}
+ ,
+ "tmp.zig:3:32: error: cast discards const qualifier",
+ );
+
+ cases.add(
+ "overflow in enum value allocation",
+ \\const Moo = enum(u8) {
+ \\ Last = 255,
+ \\ Over,
+ \\};
+ \\pub fn main() void {
+ \\ var y = Moo.Last;
+ \\}
+ ,
+ "tmp.zig:3:5: error: enumeration value 256 too large for type 'u8'",
+ );
+
+ cases.add(
+ "attempt to cast enum literal to error",
+ \\export fn entry() void {
+ \\ switch (error.Hi) {
+ \\ .Hi => {},
+ \\ }
+ \\}
+ ,
+ "tmp.zig:3:9: error: expected type 'error{Hi}', found '(enum literal)'",
+ );
+
+ cases.add(
+ "@sizeOf bad type",
+ \\export fn entry() void {
+ \\ _ = @sizeOf(@typeOf(null));
+ \\}
+ ,
+ "tmp.zig:2:17: error: no size available for type '(null)'",
+ );
+
+ cases.add(
+ "Generic function where return type is self-referenced",
+ \\fn Foo(comptime T: type) Foo(T) {
+ \\ return struct{ x: T };
+ \\}
+ \\export fn entry() void {
+ \\ const t = Foo(u32) {
+ \\ .x = 1
+ \\ };
+ \\}
+ ,
+ "tmp.zig:1:29: error: evaluation exceeded 1000 backwards branches",
+ "tmp.zig:1:29: note: called from here",
+ );
+
+ cases.add(
"@ptrToInt 0 to non optional pointer",
\\export fn entry() void {
\\ var b = @intToPtr(*i32, 0);
@@ -553,15 +611,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
);
cases.add(
- "threadlocal qualifier on local variable",
- \\export fn entry() void {
- \\ threadlocal var x: i32 = 1234;
- \\}
- ,
- "tmp.zig:2:5: error: function-local variable 'x' cannot be threadlocal",
- );
-
- cases.add(
"@bitCast same size but bit count mismatch",
\\export fn entry(byte: u8) void {
\\ var oops = @bitCast(u7, byte);
@@ -839,7 +888,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = &x == null;
\\}
,
- "tmp.zig:3:12: error: only optionals (not '*i32') can compare to null",
+ "tmp.zig:3:12: error: comparison of '*i32' with null",
);
cases.add(
@@ -5347,8 +5396,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:12:20: note: referenced here",
);
- cases.add(
- "specify enum tag type that is too small",
+ cases.add("specify enum tag type that is too small",
\\const Small = enum (u2) {
\\ One,
\\ Two,
@@ -5360,9 +5408,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\export fn entry() void {
\\ var x = Small.One;
\\}
- ,
- "tmp.zig:1:21: error: 'u2' too small to hold all bits; must be at least 'u3'",
- );
+ , "tmp.zig:6:5: error: enumeration value 4 too large for type 'u2'");
cases.add(
"specify non-integer enum tag type",
@@ -5413,22 +5459,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
);
cases.add(
- "non unsigned integer enum tag type",
- \\const Small = enum(i2) {
- \\ One,
- \\ Two,
- \\ Three,
- \\ Four,
- \\};
- \\
- \\export fn entry() void {
- \\ var y = Small.Two;
- \\}
- ,
- "tmp.zig:1:20: error: expected unsigned integer, found 'i2'",
- );
-
- cases.add(
"struct fields with value assignments",
\\const MultipleChoice = struct {
\\ A: i32 = 20,
@@ -5486,8 +5516,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var x = MultipleChoice.C;
\\}
,
- "tmp.zig:6:9: error: enum tag value 60 already taken",
- "tmp.zig:4:9: note: other occurrence here",
+ "tmp.zig:6:5: error: enum tag value 60 already taken",
+ "tmp.zig:4:5: note: other occurrence here",
);
cases.add(
@@ -5892,4 +5922,21 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
,
"tmp.zig:3:23: error: expected type '[]u32', found '*const u32'",
);
+
+ cases.add(
+ "for loop body expression ignored",
+ \\fn returns() usize {
+ \\ return 2;
+ \\}
+ \\export fn f1() void {
+ \\ for ("hello") |_| returns();
+ \\}
+ \\export fn f2() void {
+ \\ var x: anyerror!i32 = error.Bad;
+ \\ for ("hello") |_| returns() else unreachable;
+ \\}
+ ,
+ "tmp.zig:5:30: error: expression value is ignored",
+ "tmp.zig:9:30: error: expression value is ignored",
+ );
}
diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig
index 78b45ac05f..b10accd213 100644
--- a/test/runtime_safety.zig
+++ b/test/runtime_safety.zig
@@ -1,6 +1,26 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompareOutputContext) void {
+ cases.addRuntimeSafety(".? operator on null pointer",
+ \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
+ \\ @import("std").os.exit(126);
+ \\}
+ \\pub fn main() void {
+ \\ var ptr: ?*i32 = null;
+ \\ var b = ptr.?;
+ \\}
+ );
+
+ cases.addRuntimeSafety(".? operator on C pointer",
+ \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
+ \\ @import("std").os.exit(126);
+ \\}
+ \\pub fn main() void {
+ \\ var ptr: [*c]i32 = null;
+ \\ var b = ptr.?;
+ \\}
+ );
+
cases.addRuntimeSafety("@ptrToInt address zero to non-optional pointer",
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
\\ @import("std").os.exit(126);
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index da90660bf1..bc3be172ab 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -20,9 +20,12 @@ comptime {
_ = @import("behavior/bugs/1442.zig");
_ = @import("behavior/bugs/1486.zig");
_ = @import("behavior/bugs/1500.zig");
+ _ = @import("behavior/bugs/1607.zig");
_ = @import("behavior/bugs/1851.zig");
_ = @import("behavior/bugs/1914.zig");
_ = @import("behavior/bugs/2006.zig");
+ _ = @import("behavior/bugs/2114.zig");
+ _ = @import("behavior/bugs/2346.zig");
_ = @import("behavior/bugs/394.zig");
_ = @import("behavior/bugs/421.zig");
_ = @import("behavior/bugs/529.zig");
diff --git a/test/stage1/behavior/bit_shifting.zig b/test/stage1/behavior/bit_shifting.zig
index 610acc06c2..1877c8cdcb 100644
--- a/test/stage1/behavior/bit_shifting.zig
+++ b/test/stage1/behavior/bit_shifting.zig
@@ -86,3 +86,13 @@ fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, c
expect(table.get(@intCast(Key, i)) == node);
}
}
+
+// #2225
+test "comptime shr of BigInt" {
+ comptime {
+ var n0 = 0xdeadbeef0000000000000000;
+ std.debug.assert(n0 >> 64 == 0xdeadbeef);
+ var n1 = 17908056155735594659;
+ std.debug.assert(n1 >> 64 == 0);
+ }
+}
diff --git a/test/stage1/behavior/bugs/1607.zig b/test/stage1/behavior/bugs/1607.zig
new file mode 100644
index 0000000000..f32eeb03d6
--- /dev/null
+++ b/test/stage1/behavior/bugs/1607.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+const testing = std.testing;
+
+const a = []u8{ 1, 2, 3 };
+
+fn checkAddress(s: []const u8) void {
+ for (s) |*i, j| {
+ testing.expect(i == &a[j]);
+ }
+}
+
+test "slices pointing at the same address as global array." {
+ checkAddress(a);
+ comptime checkAddress(a);
+}
diff --git a/test/stage1/behavior/bugs/2114.zig b/test/stage1/behavior/bugs/2114.zig
new file mode 100644
index 0000000000..61ea2675b9
--- /dev/null
+++ b/test/stage1/behavior/bugs/2114.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const math = std.math;
+
+fn ctz(x: var) usize {
+ return @ctz(x);
+}
+
+test "fixed" {
+ testClz();
+ comptime testClz();
+}
+
+fn testClz() void {
+ expect(ctz(u128(0x40000000000000000000000000000000)) == 126);
+ expect(math.rotl(u128, u128(0x40000000000000000000000000000000), u8(1)) == u128(0x80000000000000000000000000000000));
+ expect(ctz(u128(0x80000000000000000000000000000000)) == 127);
+ expect(ctz(math.rotl(u128, u128(0x40000000000000000000000000000000), u8(1))) == 127);
+}
diff --git a/test/stage1/behavior/bugs/2346.zig b/test/stage1/behavior/bugs/2346.zig
new file mode 100644
index 0000000000..c8cea34813
--- /dev/null
+++ b/test/stage1/behavior/bugs/2346.zig
@@ -0,0 +1,6 @@
+test "fixed" {
+ const a: *void = undefined;
+ const b: *[1]void = a;
+ const c: *[0]u8 = undefined;
+ const d: []u8 = c;
+}
diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig
index f584fc265a..8a5edaa3dd 100644
--- a/test/stage1/behavior/enum.zig
+++ b/test/stage1/behavior/enum.zig
@@ -923,3 +923,42 @@ test "peer type resolution with enum literal" {
expect(Items.two == .two);
expect(.two == Items.two);
}
+
+test "enum literal in array literal" {
+ const Items = enum {
+ one,
+ two,
+ };
+
+ const array = []Items {
+ .one,
+ .two,
+ };
+
+ expect(array[0] == .one);
+ expect(array[1] == .two);
+}
+
+test "signed integer as enum tag" {
+ const SignedEnum = enum(i2) {
+ A0 = -1,
+ A1 = 0,
+ A2 = 1,
+ };
+
+ expect(@enumToInt(SignedEnum.A0) == -1);
+ expect(@enumToInt(SignedEnum.A1) == 0);
+ expect(@enumToInt(SignedEnum.A2) == 1);
+}
+
+test "enum value allocation" {
+ const LargeEnum = enum(u32) {
+ A0 = 0x80000000,
+ A1,
+ A2,
+ };
+
+ expect(@enumToInt(LargeEnum.A0) == 0x80000000);
+ expect(@enumToInt(LargeEnum.A1) == 0x80000001);
+ expect(@enumToInt(LargeEnum.A2) == 0x80000002);
+}
diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig
index 23dc6d1feb..acbd9209df 100644
--- a/test/stage1/behavior/math.zig
+++ b/test/stage1/behavior/math.zig
@@ -632,3 +632,10 @@ fn testNanEqNan(comptime F: type) void {
expect(!(nan1 < nan2));
expect(!(nan1 <= nan2));
}
+
+test "128-bit multiplication" {
+ var a: i128 = 3;
+ var b: i128 = 2;
+ var c = a * b;
+ expect(c == 6);
+}
diff --git a/test/stage1/behavior/pointers.zig b/test/stage1/behavior/pointers.zig
index be47718358..50b36fe583 100644
--- a/test/stage1/behavior/pointers.zig
+++ b/test/stage1/behavior/pointers.zig
@@ -150,3 +150,53 @@ test "allowzero pointer and slice" {
expect(@typeInfo(@typeOf(ptr)).Pointer.is_allowzero);
expect(@typeInfo(@typeOf(slice)).Pointer.is_allowzero);
}
+
+test "assign null directly to C pointer and test null equality" {
+ var x: [*c]i32 = null;
+ expect(x == null);
+ expect(null == x);
+ expect(!(x != null));
+ expect(!(null != x));
+ if (x) |same_x| {
+ @panic("fail");
+ }
+ var otherx: i32 = undefined;
+ expect((x orelse &otherx) == &otherx);
+
+ const y: [*c]i32 = null;
+ comptime expect(y == null);
+ comptime expect(null == y);
+ comptime expect(!(y != null));
+ comptime expect(!(null != y));
+ if (y) |same_y| @panic("fail");
+ const othery: i32 = undefined;
+ comptime expect((y orelse &othery) == &othery);
+
+ var n: i32 = 1234;
+ var x1: [*c]i32 = &n;
+ expect(!(x1 == null));
+ expect(!(null == x1));
+ expect(x1 != null);
+ expect(null != x1);
+ expect(x1.?.* == 1234);
+ if (x1) |same_x1| {
+ expect(same_x1.* == 1234);
+ } else {
+ @panic("fail");
+ }
+ expect((x1 orelse &otherx) == x1);
+
+ const nc: i32 = 1234;
+ const y1: [*c]const i32 = &nc;
+ comptime expect(!(y1 == null));
+ comptime expect(!(null == y1));
+ comptime expect(y1 != null);
+ comptime expect(null != y1);
+ comptime expect(y1.?.* == 1234);
+ if (y1) |same_y1| {
+ expect(same_y1.* == 1234);
+ } else {
+ @compileError("fail");
+ }
+ comptime expect((y1 orelse &othery) == y1);
+}
diff --git a/test/stage1/behavior/sizeof_and_typeof.zig b/test/stage1/behavior/sizeof_and_typeof.zig
index 58a6c81759..cfad311e06 100644
--- a/test/stage1/behavior/sizeof_and_typeof.zig
+++ b/test/stage1/behavior/sizeof_and_typeof.zig
@@ -67,3 +67,10 @@ test "@bitOffsetOf" {
expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
}
+
+test "@sizeOf on compile-time types" {
+ expect(@sizeOf(comptime_int) == 0);
+ expect(@sizeOf(comptime_float) == 0);
+ expect(@sizeOf(@typeOf(.hi)) == 0);
+ expect(@sizeOf(@typeOf(type)) == 0);
+}
diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig
index 62fb41ca28..114f06982b 100644
--- a/test/stage1/behavior/struct.zig
+++ b/test/stage1/behavior/struct.zig
@@ -2,8 +2,7 @@ const std = @import("std");
const expect = std.testing.expect;
const expectEqualSlices = std.testing.expectEqualSlices;
const builtin = @import("builtin");
-const maxInt = std.math.maxInt;
-
+const maxInt = std.math.maxInt;
const StructWithNoFields = struct {
fn add(a: i32, b: i32) i32 {
return a + b;
@@ -505,3 +504,22 @@ test "packed struct with u0 field access" {
var s = S{ .f0 = 0 };
comptime expect(s.f0 == 0);
}
+
+const S0 = struct{
+ bar: S1,
+
+ pub const S1 = struct{
+ value: u8,
+ };
+
+ fn init() @This() {
+ return S0{ .bar = S1{ .value = 123 } };
+ }
+};
+
+var g_foo: S0 = S0.init();
+
+test "access to global struct fields" {
+ g_foo.bar.value = 42;
+ expect(g_foo.bar.value == 42);
+}
diff --git a/test/stage1/behavior/syntax.zig b/test/stage1/behavior/syntax.zig
index 451e396142..12df8a4315 100644
--- a/test/stage1/behavior/syntax.zig
+++ b/test/stage1/behavior/syntax.zig
@@ -1,6 +1,14 @@
// Test trailing comma syntax
// zig fmt: off
+extern var a: c_int;
+extern "c" var b: c_int;
+export var c: c_int = 0;
+threadlocal var d: c_int;
+extern threadlocal var e: c_int;
+extern "c" threadlocal var f: c_int;
+export threadlocal var g: c_int = 0;
+
const struct_trailing_comma = struct { x: i32, y: i32, };
const struct_no_comma = struct { x: i32, y: i32 };
const struct_fn_no_comma = struct { fn m() void {} y: i32 };
diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig
index bbba867667..b8bb9a51b8 100644
--- a/test/stage1/behavior/union.zig
+++ b/test/stage1/behavior/union.zig
@@ -365,3 +365,40 @@ test "@enumToInt works on unions" {
expect(@enumToInt(b) == 1);
expect(@enumToInt(c) == 2);
}
+
+const Attribute = union(enum) {
+ A: bool,
+ B: u8,
+};
+
+fn setAttribute(attr: Attribute) void {}
+
+fn Setter(attr: Attribute) type {
+ return struct{
+ fn set() void {
+ setAttribute(attr);
+ }
+ };
+}
+
+test "comptime union field value equality" {
+ const a0 = Setter(Attribute{ .A = false });
+ const a1 = Setter(Attribute{ .A = true });
+ const a2 = Setter(Attribute{ .A = false });
+
+ const b0 = Setter(Attribute{ .B = 5 });
+ const b1 = Setter(Attribute{ .B = 9 });
+ const b2 = Setter(Attribute{ .B = 5 });
+
+ expect(a0 == a0);
+ expect(a1 == a1);
+ expect(a0 == a2);
+
+ expect(b0 == b0);
+ expect(b1 == b1);
+ expect(b0 == b2);
+
+ expect(a0 != b0);
+ expect(a0 != a1);
+ expect(b0 != b1);
+}
diff --git a/test/tests.zig b/test/tests.zig
index 61fd0426f1..4b67cf0f6c 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -903,6 +903,7 @@ pub const TranslateCContext = struct {
sources: ArrayList(SourceFile),
expected_lines: ArrayList([]const u8),
allow_warnings: bool,
+ stage2: bool,
const SourceFile = struct {
filename: []const u8,
@@ -955,7 +956,8 @@ pub const TranslateCContext = struct {
var zig_args = ArrayList([]const u8).init(b.allocator);
zig_args.append(b.zig_exe) catch unreachable;
- zig_args.append("translate-c") catch unreachable;
+ const translate_c_cmd = if (self.case.stage2) "translate-c-2" else "translate-c";
+ zig_args.append(translate_c_cmd) catch unreachable;
zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
@@ -1052,6 +1054,7 @@ pub const TranslateCContext = struct {
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
.allow_warnings = allow_warnings,
+ .stage2 = false,
};
tc.addSourceFile(filename, source);
@@ -1072,6 +1075,34 @@ pub const TranslateCContext = struct {
self.addCase(tc);
}
+ pub fn add_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
+ for ([]bool{ false, true }) |stage2| {
+ const tc = self.create(false, "source.h", name, source, expected_lines);
+ tc.stage2 = stage2;
+ self.addCase(tc);
+ }
+ }
+
+ pub fn addC_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
+ for ([]bool{ false, true }) |stage2| {
+ const tc = self.create(false, "source.c", name, source, expected_lines);
+ tc.stage2 = stage2;
+ self.addCase(tc);
+ }
+ }
+
+ pub fn add_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
+ const tc = self.create(false, "source.h", name, source, expected_lines);
+ tc.stage2 = true;
+ self.addCase(tc);
+ }
+
+ pub fn addC_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
+ const tc = self.create(false, "source.c", name, source, expected_lines);
+ tc.stage2 = true;
+ self.addCase(tc);
+ }
+
pub fn addAllowWarnings(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
const tc = self.create(true, "source.h", name, source, expected_lines);
self.addCase(tc);
@@ -1080,7 +1111,8 @@ pub const TranslateCContext = struct {
pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
const b = self.b;
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable;
+ const translate_c_cmd = if (case.stage2) "translate-c-2" else "translate-c";
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", translate_c_cmd, case.name) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
diff --git a/test/translate_c.zig b/test/translate_c.zig
index cd8e7cb6d0..930442f293 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -1,7 +1,66 @@
const tests = @import("tests.zig");
const builtin = @import("builtin");
+// add_both - test for stage1 and stage2, in #include mode
+// add - test stage1 only, in #include mode
+// add_2 - test stage2 only, in #include mode
+// addC_both - test for stage1 and stage2, in -c mode
+// addC - test stage1 only, in -c mode
+// addC_2 - test stage2 only, in -c mode
+
pub fn addCases(cases: *tests.TranslateCContext) void {
+ /////////////// Cases that pass for both stage1/stage2 ////////////////
+ cases.add_both("simple function prototypes",
+ \\void __attribute__((noreturn)) foo(void);
+ \\int bar(void);
+ ,
+ \\pub extern fn foo() noreturn;
+ \\pub extern fn bar() c_int;
+ );
+
+ /////////////// Cases that pass for only stage2 ////////////////
+ cases.add_2("Parameterless function prototypes",
+ \\void a() {}
+ \\void b(void) {}
+ \\void c();
+ \\void d(void);
+ ,
+ \\pub export fn a() void {}
+ \\pub export fn b() void {}
+ \\pub extern fn c(...) void;
+ \\pub extern fn d() void;
+ );
+
+ cases.add_2("simple function definition",
+ \\void foo(void) {}
+ \\static void bar(void) {}
+ ,
+ \\pub export fn foo() void {}
+ \\pub extern fn bar() void {}
+ );
+
+ /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
+
+ cases.add("macro with left shift",
+ \\#define REDISMODULE_READ (1<<0)
+ ,
+ \\pub const REDISMODULE_READ = 1 << 0;
+ );
+
+ cases.add("casting pointers to ints and ints to pointers",
+ \\void foo(void);
+ \\void bar(void) {
+ \\ void *func_ptr = foo;
+ \\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
+ \\}
+ ,
+ \\pub extern fn foo() void;
+ \\pub fn bar() void {
+ \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
+ \\ var typed_func_ptr: ?extern fn() void = @intToPtr(?extern fn() void, c_ulong(@ptrToInt(func_ptr)));
+ \\}
+ );
+
if (builtin.os != builtin.Os.windows) {
// Windows treats this as an enum with type c_int
cases.add("big negative enum init values when C ABI supports long long enums",
@@ -72,7 +131,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ _ = c"void foo(void)";
\\}
);
-
+
cases.add("ignore result",
\\void foo() {
\\ int a;
@@ -648,11 +707,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
\\ if ((a != 0) and (b != 0)) return 0;
- \\ if ((b != 0) and (c != 0)) return 1;
- \\ if ((a != 0) and (c != 0)) return 2;
+ \\ if ((b != 0) and (c != null)) return 1;
+ \\ if ((a != 0) and (c != null)) return 2;
\\ if ((a != 0) or (b != 0)) return 3;
- \\ if ((b != 0) or (c != 0)) return 4;
- \\ if ((a != 0) or (c != 0)) return 5;
+ \\ if ((b != 0) or (c != null)) return 4;
+ \\ if ((a != 0) or (c != null)) return 5;
\\ return 6;
\\}
);
@@ -832,7 +891,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
,
\\pub export fn foo() [*c]c_int {
- \\ return 0;
+ \\ return null;
\\}
);
@@ -1334,7 +1393,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
,
\\fn ptrcast(a: [*c]c_int) [*c]f32 {
- \\ return @ptrCast([*c]f32, a);
+ \\ return @ptrCast([*c]f32, @alignCast(@alignOf(f32), a));
\\}
);
@@ -1360,7 +1419,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return !(a == 0);
\\ return !(a != 0);
\\ return !(b != 0);
- \\ return !(c != 0);
+ \\ return !(c != null);
\\}
);
@@ -1417,7 +1476,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
\\ if (a != 0) return 0;
\\ if (b != 0) return 1;
- \\ if (c != 0) return 2;
+ \\ if (c != null) return 2;
\\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
\\ return 4;
\\}
@@ -1434,7 +1493,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
\\ while (a != 0) return 0;
\\ while (b != 0) return 1;
- \\ while (c != 0) return 2;
+ \\ while (c != null) return 2;
\\ return 3;
\\}
);
@@ -1450,7 +1509,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
\\ while (a != 0) return 0;
\\ while (b != 0) return 1;
- \\ while (c != 0) return 2;
+ \\ while (c != null) return 2;
\\ return 3;
\\}
);
@@ -1497,14 +1556,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
);
- cases.addC("Parameterless function prototypes",
- \\void foo() {}
- \\void bar(void) {}
- ,
- \\pub export fn foo() void {}
- \\pub export fn bar() void {}
- );
-
cases.addC(
"u integer suffix after 0 (zero) in macro definition",
"#define ZERO 0U",
@@ -1553,33 +1604,101 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
"pub const NOT_ZERO = ~c_uint(0);",
);
- // cases.add("empty array with initializer",
- // "int a[4] = {};"
- // ,
- // "pub var a: [4]c_int = [1]c_int{0} ** 4;"
- // );
-
- // cases.add("array with initialization",
- // "int a[4] = {1, 2, 3, 4};"
- // ,
- // "pub var a: [4]c_int = [4]c_int{1, 2, 3, 4};"
- // );
-
- // cases.add("array with incomplete initialization",
- // "int a[4] = {3, 4};"
- // ,
- // "pub var a: [4]c_int = [2]c_int{3, 4} ++ ([1]c_int{0} ** 2);"
- // );
-
- // cases.add("2D array with initialization",
- // "int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };"
- // ,
- // "pub var a: [3][3]c_int = [3][3]c_int{[3]c_int{1, 2, 3}, [3]c_int{4, 5, 6}, [3]c_int{7, 8, 9}};"
- // );
-
- // cases.add("2D array with incomplete initialization",
- // "int a[3][3] = { {1, 2}, {4, 5, 6} };"
- // ,
- // "pub var a: [3][3]c_int = [2][3]c_int{[2]c_int{1, 2} ++ [1]c_int{0}, [3]c_int{4, 5, 6}} ++ [1][3]c_int{[1]c_int{0} ** 3};"
- // );
+ cases.addC("implicit casts",
+ \\#include <stdbool.h>
+ \\
+ \\void fn_int(int x);
+ \\void fn_f32(float x);
+ \\void fn_f64(double x);
+ \\void fn_char(char x);
+ \\void fn_bool(bool x);
+ \\void fn_ptr(void *x);
+ \\
+ \\void call(int q) {
+ \\ fn_int(3.0f);
+ \\ fn_int(3.0);
+ \\ fn_int(3.0L);
+ \\ fn_int('ABCD');
+ \\ fn_f32(3);
+ \\ fn_f64(3);
+ \\ fn_char('3');
+ \\ fn_char('\x1');
+ \\ fn_char(0);
+ \\ fn_f32(3.0f);
+ \\ fn_f64(3.0);
+ \\ fn_bool(123);
+ \\ fn_bool(0);
+ \\ fn_bool(&fn_int);
+ \\ fn_int(&fn_int);
+ \\ fn_ptr(42);
+ \\}
+ ,
+ \\pub extern fn fn_int(x: c_int) void;
+ \\pub extern fn fn_f32(x: f32) void;
+ \\pub extern fn fn_f64(x: f64) void;
+ \\pub extern fn fn_char(x: u8) void;
+ \\pub extern fn fn_bool(x: bool) void;
+ \\pub extern fn fn_ptr(x: ?*c_void) void;
+ \\pub export fn call(q: c_int) void {
+ \\ fn_int(@floatToInt(c_int, 3.000000));
+ \\ fn_int(@floatToInt(c_int, 3.000000));
+ \\ fn_int(@floatToInt(c_int, 3.000000));
+ \\ fn_int(1094861636);
+ \\ fn_f32(@intToFloat(f32, 3));
+ \\ fn_f64(@intToFloat(f64, 3));
+ \\ fn_char(u8('3'));
+ \\ fn_char(u8('\x01'));
+ \\ fn_char(u8(0));
+ \\ fn_f32(3.000000);
+ \\ fn_f64(3.000000);
+ \\ fn_bool(true);
+ \\ fn_bool(false);
+ \\ fn_bool(@ptrToInt(&fn_int) != 0);
+ \\ fn_int(@intCast(c_int, @ptrToInt(&fn_int)));
+ \\ fn_ptr(@intToPtr(?*c_void, 42));
+ \\}
+ );
+
+ cases.addC("pointer conversion with different alignment",
+ \\void test_ptr_cast() {
+ \\ void *p;
+ \\ {
+ \\ char *to_char = (char *)p;
+ \\ short *to_short = (short *)p;
+ \\ int *to_int = (int *)p;
+ \\ long long *to_longlong = (long long *)p;
+ \\ }
+ \\ {
+ \\ char *to_char = p;
+ \\ short *to_short = p;
+ \\ int *to_int = p;
+ \\ long long *to_longlong = p;
+ \\ }
+ \\}
+ ,
+ \\pub export fn test_ptr_cast() void {
+ \\ var p: ?*c_void = undefined;
+ \\ {
+ \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p));
+ \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p));
+ \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p));
+ \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p));
+ \\ }
+ \\ {
+ \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p));
+ \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p));
+ \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p));
+ \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p));
+ \\ }
+ \\}
+ );
+
+ /////////////// Cases for only stage1 because stage2 behavior is better ////////////////
+ cases.addC("Parameterless function prototypes",
+ \\void foo() {}
+ \\void bar(void) {}
+ ,
+ \\pub export fn foo() void {}
+ \\pub export fn bar() void {}
+ );
}