authorgravatar for codroid@gmail.comhryx <codroid@gmail.com> 2019-05-12 02:00:49-07:00
committergravatar for codroid@gmail.comhryx <codroid@gmail.com> 2019-05-12 02:00:49-07:00
log3787f3428625e830fd852a8f5a40c7d8a2d429f6
tree23fb493b9d2f07c7abe57955874682959936319a
parent16aee1f58a80295f7599a8290d764a5c7040c373
parentedcc7c72d1a684a8a16ca23ad26689f2cce4e803
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'master' into rebased


222 files changed, 18469 insertions(+), 7246 deletions(-)

CMakeLists.txt+87-24
...@@ -15,7 +15,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})...@@ -15,7 +15,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
1515
1616
17set(ZIG_VERSION_MAJOR 0)17set(ZIG_VERSION_MAJOR 0)
18set(ZIG_VERSION_MINOR 3)18set(ZIG_VERSION_MINOR 4)
19set(ZIG_VERSION_PATCH 0)19set(ZIG_VERSION_PATCH 0)
20set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}")20set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}")
2121
...@@ -50,10 +50,6 @@ option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead...@@ -50,10 +50,6 @@ option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead
50find_package(llvm)50find_package(llvm)
51find_package(clang)51find_package(clang)
5252
53if(MINGW)
54 find_package(z3)
55endif()
56
57if(APPLE AND ZIG_STATIC)53if(APPLE AND ZIG_STATIC)
58 list(REMOVE_ITEM LLVM_LIBRARIES "-lz")54 list(REMOVE_ITEM LLVM_LIBRARIES "-lz")
59 find_library(ZLIB NAMES z zlib libz)55 find_library(ZLIB NAMES z zlib libz)
...@@ -62,6 +58,16 @@ endif()...@@ -62,6 +58,16 @@ endif()
6258
63set(ZIG_CPP_LIB_DIR "${CMAKE_BINARY_DIR}/zig_cpp")59set(ZIG_CPP_LIB_DIR "${CMAKE_BINARY_DIR}/zig_cpp")
6460
61# Handle multi-config builds and place each into a common lib. The VS generator
62# for example will append a Debug folder by default if not explicitly specified.
63set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ZIG_CPP_LIB_DIR})
64set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ZIG_CPP_LIB_DIR})
65foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
66 string(TOUPPER ${CONFIG_TYPE} CONFIG_TYPE)
67 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_TYPE} ${ZIG_CPP_LIB_DIR})
68 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONFIG_TYPE} ${ZIG_CPP_LIB_DIR})
69endforeach(CONFIG_TYPE CMAKE_CONFIGURATION_TYPES)
70
65if(ZIG_FORCE_EXTERNAL_LLD)71if(ZIG_FORCE_EXTERNAL_LLD)
66 find_package(lld)72 find_package(lld)
67 include_directories(${LLVM_INCLUDE_DIRS})73 include_directories(${LLVM_INCLUDE_DIRS})
...@@ -196,7 +202,7 @@ else()...@@ -196,7 +202,7 @@ else()
196 if(MSVC)202 if(MSVC)
197 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")203 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")
198 else()204 else()
199 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment")205 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Wno-comment")
200 if(MINGW)206 if(MINGW)
201 set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")207 set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")
202 endif()208 endif()
...@@ -257,7 +263,6 @@ else()...@@ -257,7 +263,6 @@ else()
257 embedded_lld_wasm263 embedded_lld_wasm
258 embedded_lld_lib264 embedded_lld_lib
259 )265 )
260 install(TARGETS embedded_lld_elf embedded_lld_coff embedded_lld_mingw embedded_lld_wasm embedded_lld_lib DESTINATION "${ZIG_CPP_LIB_DIR}")
261endif()266endif()
262267
263# No patches have been applied to SoftFloat-3e268# No patches have been applied to SoftFloat-3e
...@@ -407,6 +412,12 @@ set(SOFTFLOAT_LIBRARIES embedded_softfloat)...@@ -407,6 +412,12 @@ set(SOFTFLOAT_LIBRARIES embedded_softfloat)
407412
408find_package(Threads)413find_package(Threads)
409414
415# CMake doesn't let us create an empty executable, so we hang on to this one separately.
416set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp")
417
418# This is our shim which will be replaced by libuserland written in Zig.
419set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp")
420
410set(ZIG_SOURCES421set(ZIG_SOURCES
411 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"422 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"
412 "${CMAKE_SOURCE_DIR}/src/ast_render.cpp"423 "${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
...@@ -423,7 +434,6 @@ set(ZIG_SOURCES...@@ -423,7 +434,6 @@ set(ZIG_SOURCES
423 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"434 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
424 "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"435 "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
425 "${CMAKE_SOURCE_DIR}/src/link.cpp"436 "${CMAKE_SOURCE_DIR}/src/link.cpp"
426 "${CMAKE_SOURCE_DIR}/src/main.cpp"
427 "${CMAKE_SOURCE_DIR}/src/os.cpp"437 "${CMAKE_SOURCE_DIR}/src/os.cpp"
428 "${CMAKE_SOURCE_DIR}/src/parser.cpp"438 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
429 "${CMAKE_SOURCE_DIR}/src/range_set.cpp"439 "${CMAKE_SOURCE_DIR}/src/range_set.cpp"
...@@ -477,6 +487,7 @@ set(ZIG_STD_FILES...@@ -477,6 +487,7 @@ set(ZIG_STD_FILES
477 "crypto/x25519.zig"487 "crypto/x25519.zig"
478 "cstr.zig"488 "cstr.zig"
479 "debug.zig"489 "debug.zig"
490 "debug/leb128.zig"
480 "debug/failing_allocator.zig"491 "debug/failing_allocator.zig"
481 "dwarf.zig"492 "dwarf.zig"
482 "dynamic_library.zig"493 "dynamic_library.zig"
...@@ -507,6 +518,7 @@ set(ZIG_STD_FILES...@@ -507,6 +518,7 @@ set(ZIG_STD_FILES
507 "heap.zig"518 "heap.zig"
508 "io.zig"519 "io.zig"
509 "io/seekable_stream.zig"520 "io/seekable_stream.zig"
521 "io/c_out_stream.zig"
510 "json.zig"522 "json.zig"
511 "lazy_init.zig"523 "lazy_init.zig"
512 "linked_list.zig"524 "linked_list.zig"
...@@ -521,6 +533,7 @@ set(ZIG_STD_FILES...@@ -521,6 +533,7 @@ set(ZIG_STD_FILES
521 "math/atanh.zig"533 "math/atanh.zig"
522 "math/big.zig"534 "math/big.zig"
523 "math/big/int.zig"535 "math/big/int.zig"
536 "math/big/rational.zig"
524 "math/cbrt.zig"537 "math/cbrt.zig"
525 "math/ceil.zig"538 "math/ceil.zig"
526 "math/complex.zig"539 "math/complex.zig"
...@@ -599,6 +612,7 @@ set(ZIG_STD_FILES...@@ -599,6 +612,7 @@ set(ZIG_STD_FILES
599 "os/linux.zig"612 "os/linux.zig"
600 "os/linux/arm64.zig"613 "os/linux/arm64.zig"
601 "os/linux/errno.zig"614 "os/linux/errno.zig"
615 "os/linux/tls.zig"
602 "os/linux/vdso.zig"616 "os/linux/vdso.zig"
603 "os/linux/x86_64.zig"617 "os/linux/x86_64.zig"
604 "os/netbsd.zig"618 "os/netbsd.zig"
...@@ -606,6 +620,8 @@ set(ZIG_STD_FILES...@@ -606,6 +620,8 @@ set(ZIG_STD_FILES
606 "os/path.zig"620 "os/path.zig"
607 "os/time.zig"621 "os/time.zig"
608 "os/uefi.zig"622 "os/uefi.zig"
623 "os/wasi.zig"
624 "os/wasi/core.zig"
609 "os/windows.zig"625 "os/windows.zig"
610 "os/windows/advapi32.zig"626 "os/windows/advapi32.zig"
611 "os/windows/error.zig"627 "os/windows/error.zig"
...@@ -615,6 +631,7 @@ set(ZIG_STD_FILES...@@ -615,6 +631,7 @@ set(ZIG_STD_FILES
615 "os/windows/shell32.zig"631 "os/windows/shell32.zig"
616 "os/windows/util.zig"632 "os/windows/util.zig"
617 "os/zen.zig"633 "os/zen.zig"
634 "packed_int_array.zig"
618 "pdb.zig"635 "pdb.zig"
619 "priority_queue.zig"636 "priority_queue.zig"
620 "rand.zig"637 "rand.zig"
...@@ -628,10 +645,15 @@ set(ZIG_STD_FILES...@@ -628,10 +645,15 @@ set(ZIG_STD_FILES
628 "special/build_runner.zig"645 "special/build_runner.zig"
629 "special/builtin.zig"646 "special/builtin.zig"
630 "special/compiler_rt.zig"647 "special/compiler_rt.zig"
648 "special/compiler_rt/stack_probe.zig"
649 "special/compiler_rt/arm/aeabi_fcmp.zig"
650 "special/compiler_rt/arm/aeabi_dcmp.zig"
631 "special/compiler_rt/addXf3.zig"651 "special/compiler_rt/addXf3.zig"
632 "special/compiler_rt/aulldiv.zig"652 "special/compiler_rt/aulldiv.zig"
633 "special/compiler_rt/aullrem.zig"653 "special/compiler_rt/aullrem.zig"
634 "special/compiler_rt/comparetf2.zig"654 "special/compiler_rt/comparetf2.zig"
655 "special/compiler_rt/comparedf2.zig"
656 "special/compiler_rt/comparesf2.zig"
635 "special/compiler_rt/divsf3.zig"657 "special/compiler_rt/divsf3.zig"
636 "special/compiler_rt/divdf3.zig"658 "special/compiler_rt/divdf3.zig"
637 "special/compiler_rt/divti3.zig"659 "special/compiler_rt/divti3.zig"
...@@ -656,9 +678,13 @@ set(ZIG_STD_FILES...@@ -656,9 +678,13 @@ set(ZIG_STD_FILES
656 "special/compiler_rt/fixunstfdi.zig"678 "special/compiler_rt/fixunstfdi.zig"
657 "special/compiler_rt/fixunstfsi.zig"679 "special/compiler_rt/fixunstfsi.zig"
658 "special/compiler_rt/fixunstfti.zig"680 "special/compiler_rt/fixunstfti.zig"
681 "special/compiler_rt/floatdidf.zig"
682 "special/compiler_rt/floatsiXf.zig"
683 "special/compiler_rt/floatunsidf.zig"
659 "special/compiler_rt/floattidf.zig"684 "special/compiler_rt/floattidf.zig"
660 "special/compiler_rt/floattisf.zig"685 "special/compiler_rt/floattisf.zig"
661 "special/compiler_rt/floattitf.zig"686 "special/compiler_rt/floattitf.zig"
687 "special/compiler_rt/floatundidf.zig"
662 "special/compiler_rt/floatunditf.zig"688 "special/compiler_rt/floatunditf.zig"
663 "special/compiler_rt/floatunsitf.zig"689 "special/compiler_rt/floatunsitf.zig"
664 "special/compiler_rt/floatuntidf.zig"690 "special/compiler_rt/floatuntidf.zig"
...@@ -667,7 +693,11 @@ set(ZIG_STD_FILES...@@ -667,7 +693,11 @@ set(ZIG_STD_FILES
667 "special/compiler_rt/modti3.zig"693 "special/compiler_rt/modti3.zig"
668 "special/compiler_rt/mulXf3.zig"694 "special/compiler_rt/mulXf3.zig"
669 "special/compiler_rt/muloti4.zig"695 "special/compiler_rt/muloti4.zig"
696 "special/compiler_rt/mulodi4.zig"
670 "special/compiler_rt/multi3.zig"697 "special/compiler_rt/multi3.zig"
698 "special/compiler_rt/ashlti3.zig"
699 "special/compiler_rt/ashrti3.zig"
700 "special/compiler_rt/lshrti3.zig"
671 "special/compiler_rt/negXf2.zig"701 "special/compiler_rt/negXf2.zig"
672 "special/compiler_rt/popcountdi2.zig"702 "special/compiler_rt/popcountdi2.zig"
673 "special/compiler_rt/truncXfYf2.zig"703 "special/compiler_rt/truncXfYf2.zig"
...@@ -676,7 +706,6 @@ set(ZIG_STD_FILES...@@ -676,7 +706,6 @@ set(ZIG_STD_FILES
676 "special/compiler_rt/udivmodti4.zig"706 "special/compiler_rt/udivmodti4.zig"
677 "special/compiler_rt/udivti3.zig"707 "special/compiler_rt/udivti3.zig"
678 "special/compiler_rt/umodti3.zig"708 "special/compiler_rt/umodti3.zig"
679 "special/fmt_runner.zig"
680 "special/init-exe/build.zig"709 "special/init-exe/build.zig"
681 "special/init-exe/src/main.zig"710 "special/init-exe/src/main.zig"
682 "special/init-lib/build.zig"711 "special/init-lib/build.zig"
...@@ -6604,7 +6633,7 @@ endif()...@@ -6604,7 +6633,7 @@ endif()
6604if(MSVC)6633if(MSVC)
6605 set(EXE_CFLAGS "${EXE_CFLAGS}")6634 set(EXE_CFLAGS "${EXE_CFLAGS}")
6606else()6635else()
6607 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")6636 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")
6608 if(MINGW)6637 if(MINGW)
6609 set(EXE_CFLAGS "${EXE_CFLAGS} -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")6638 set(EXE_CFLAGS "${EXE_CFLAGS} -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")
6610 endif()6639 endif()
...@@ -6639,13 +6668,12 @@ set_target_properties(opt_c_util PROPERTIES...@@ -6639,13 +6668,12 @@ set_target_properties(opt_c_util PROPERTIES
6639 COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"6668 COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"
6640)6669)
66416670
6642add_executable(zig ${ZIG_SOURCES})6671add_library(compiler STATIC ${ZIG_SOURCES})
6643set_target_properties(zig PROPERTIES6672set_target_properties(compiler PROPERTIES
6644 COMPILE_FLAGS ${EXE_CFLAGS}6673 COMPILE_FLAGS ${EXE_CFLAGS}
6645 LINK_FLAGS ${EXE_LDFLAGS}6674 LINK_FLAGS ${EXE_LDFLAGS}
6646)6675)
66476676target_link_libraries(compiler LINK_PUBLIC
6648target_link_libraries(zig LINK_PUBLIC
6649 zig_cpp6677 zig_cpp
6650 opt_c_util6678 opt_c_util
6651 ${SOFTFLOAT_LIBRARIES}6679 ${SOFTFLOAT_LIBRARIES}
...@@ -6654,24 +6682,63 @@ target_link_libraries(zig LINK_PUBLIC...@@ -6654,24 +6682,63 @@ target_link_libraries(zig LINK_PUBLIC
6654 ${LLVM_LIBRARIES}6682 ${LLVM_LIBRARIES}
6655 ${CMAKE_THREAD_LIBS_INIT}6683 ${CMAKE_THREAD_LIBS_INIT}
6656)6684)
6657
6658if(NOT MSVC)6685if(NOT MSVC)
6659 target_link_libraries(zig LINK_PUBLIC ${LIBXML2})6686 target_link_libraries(compiler LINK_PUBLIC ${LIBXML2})
6660endif()6687endif()
66616688
6662if(MINGW)6689if(MINGW)
6663 target_link_libraries(zig LINK_PUBLIC ${Z3_LIBRARIES})6690 find_library(Z3_LIBRARIES NAMES z3 z3.dll)
6691 target_link_libraries(compiler LINK_PUBLIC ${Z3_LIBRARIES})
6664endif()6692endif()
66656693
6666if(ZIG_DIA_GUIDS_LIB)6694if(ZIG_DIA_GUIDS_LIB)
6667 target_link_libraries(zig LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})6695 target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
6668endif()6696endif()
66696697
6670if(MSVC OR MINGW)6698if(MSVC OR MINGW)
6671 target_link_libraries(zig LINK_PUBLIC version)6699 target_link_libraries(compiler LINK_PUBLIC version)
6672endif()6700endif()
6701
6702add_executable(zig0 "${ZIG_MAIN_SRC}" "${ZIG0_SHIM_SRC}")
6703set_target_properties(zig0 PROPERTIES
6704 COMPILE_FLAGS ${EXE_CFLAGS}
6705 LINK_FLAGS ${EXE_LDFLAGS}
6706)
6707target_link_libraries(zig0 compiler)
6708
6709if(WIN32)
6710 set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib")
6711elseif(APPLE)
6712 set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.o")
6713else()
6714 set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a")
6715endif()
6716add_custom_command(
6717 OUTPUT "${LIBUSERLAND}"
6718 COMMAND zig0 ARGS build
6719 --override-std-dir std
6720 --override-lib-dir "${CMAKE_SOURCE_DIR}"
6721 libuserland
6722 "-Doutput-dir=${CMAKE_BINARY_DIR}"
6723 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
6724 DEPENDS
6725 "${CMAKE_SOURCE_DIR}/src-self-hosted/stage1.zig"
6726 "${CMAKE_SOURCE_DIR}/src-self-hosted/translate_c.zig"
6727 "${CMAKE_SOURCE_DIR}/build.zig"
6728)
6729add_custom_target(userland_target DEPENDS "${LIBUSERLAND}")
6730add_executable(zig "${ZIG_MAIN_SRC}")
6731if(MINGW)
6732 set(EXE_LDFLAGS "${EXE_LDFLAGS} -fstack-protector")
6733endif()
6734set_target_properties(zig PROPERTIES
6735 COMPILE_FLAGS ${EXE_CFLAGS}
6736 LINK_FLAGS ${EXE_LDFLAGS}
6737)
6738target_link_libraries(zig compiler "${LIBUSERLAND}")
6739add_dependencies(zig userland_target)
6673install(TARGETS zig DESTINATION bin)6740install(TARGETS zig DESTINATION bin)
6674install(TARGETS zig_cpp DESTINATION "${ZIG_CPP_LIB_DIR}")6741
66756742
6676foreach(file ${ZIG_C_HEADER_FILES})6743foreach(file ${ZIG_C_HEADER_FILES})
6677 get_filename_component(file_dir "${C_HEADERS_DEST}/${file}" DIRECTORY)6744 get_filename_component(file_dir "${C_HEADERS_DEST}/${file}" DIRECTORY)
...@@ -6697,7 +6764,3 @@ foreach(file ${ZIG_LIBCXX_FILES})...@@ -6697,7 +6764,3 @@ foreach(file ${ZIG_LIBCXX_FILES})
6697 get_filename_component(file_dir "${LIBCXX_FILES_DEST}/${file}" DIRECTORY)6764 get_filename_component(file_dir "${LIBCXX_FILES_DEST}/${file}" DIRECTORY)
6698 install(FILES "${CMAKE_SOURCE_DIR}/libcxx/${file}" DESTINATION "${file_dir}")6765 install(FILES "${CMAKE_SOURCE_DIR}/libcxx/${file}" DESTINATION "${file_dir}")
6699endforeach()6766endforeach()
6700
6701install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/arg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
6702install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/main.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
6703install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/errmsg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
README.md+104-138
...@@ -1,140 +1,15 @@...@@ -1,140 +1,15 @@
1![ZIG](https://ziglang.org/zig-logo.svg)1![ZIG](https://ziglang.org/zig-logo.svg)
22
3A programming language designed for robustness, optimality, and3Zig is an open-source programming language designed for **robustness**,
4clarity.4**optimality**, and **maintainability**.
55
6[Download & Documentation](https://ziglang.org/download/)6## Resources
77
8## Feature Highlights8 * [Introduction](https://ziglang.org/#Introduction)
99 * [Download & Documentation](https://ziglang.org/download)
10 * Small, simple language. Focus on debugging your application rather than10 * [Community](https://github.com/ziglang/zig/wiki/Community)
11 debugging knowledge of your programming language.11
12 * Ships with a build system that obviates the need for a configure script12## Building from Source
13 or a makefile. In fact, existing C and C++ projects may choose to depend on
14 Zig instead of e.g. cmake.
15 * A fresh take on error handling which makes writing correct code easier than
16 writing buggy code.
17 * Debug mode optimizes for fast compilation time and crashing with a stack trace
18 when undefined behavior *would* happen.
19 * ReleaseFast mode produces heavily optimized code. What other projects call
20 "Link Time Optimization" Zig does automatically.
21 * Compatible with C libraries with no wrapper necessary. Directly include
22 C .h files and get access to the functions and symbols therein.
23 * Provides standard library which competes with the C standard library and is
24 always compiled against statically in source form. Zig binaries do not
25 depend on libc unless explicitly linked.
26 * Optional type instead of null pointers.
27 * Safe unions, tagged unions, and C ABI compatible unions.
28 * Generics so that one can write efficient data structures that work for any
29 data type.
30 * No header files required. Top level declarations are entirely
31 order-independent.
32 * Compile-time code execution. Compile-time reflection.
33 * Partial compile-time function evaluation which eliminates the need for
34 a preprocessor or macros.
35 * The binaries produced by Zig have complete debugging information so you can,
36 for example, use GDB, MSVC, or LLDB to debug your software.
37 * Built-in unit tests with `zig test`.
38 * Friendly toward package maintainers. Reproducible build, bootstrapping
39 process carefully documented. Issues filed by package maintainers are
40 considered especially important.
41 * Cross-compiling is a primary use case.
42 * In addition to creating executables, creating a C library is a primary use
43 case. You can export an auto-generated .h file.
44
45### Supported Targets
46
47#### Tier 1 Support
48
49 * Not only can Zig generate machine code for these targets, but the standard
50 library cross-platform abstractions have implementations for these targets.
51 Thus it is practical to write a pure Zig application with no dependency on
52 libc.
53 * The CI server automatically tests these targets on every commit to master
54 branch, and updates ziglang.org/download with links to pre-built binaries.
55 * These targets have debug info capabilities and therefore produce stack
56 traces on failed assertions.
57 * ([coming soon](https://github.com/ziglang/zig/issues/514)) libc is available
58 for this target even when cross compiling.
59
60#### Tier 2 Support
61
62 * There may be some standard library implementations, but many abstractions
63 will give an "Unsupported OS" compile error. One can link with libc or other
64 libraries to fill in the gaps in the standard library.
65 * These targets are known to work, but are not automatically tested, so there
66 are occasional regressions.
67 * Some tests may be disabled for these targets as we work toward Tier 1
68 support.
69
70#### Tier 3 Support
71
72 * The standard library has little to no knowledge of the existence of this
73 target.
74 * Because Zig is based on LLVM, it has the capability to build for these
75 targets, and LLVM has the target enabled by default.
76 * These targets are not frequently tested; one will likely need to contribute
77 to Zig in order to build for these targets.
78 * The Zig compiler might need to be updated with a few things such as
79 - what sizes are the C integer types
80 - C ABI calling convention for this target
81 - bootstrap code and default panic handler
82 * `zig targets` is guaranteed to include this target.
83
84#### Tier 4 Support
85
86 * Support for these targets is entirely experimental.
87 * LLVM may have the target as an experimental target, which means that you
88 need to use Zig-provided binaries for the target to be available, or
89 build LLVM from source with special configure flags. `zig targets` will
90 display the target if it is available.
91 * This target may be considered deprecated by an official party,
92 [such as macosx/i386](https://support.apple.com/en-us/HT208436) in which
93 case this target will remain forever stuck in Tier 4.
94 * This target may only support `--emit asm` and cannot emit object files.
95
96#### Support Table
97
98| | freestanding | linux | macosx | windows | freebsd | netbsd | UEFI | other |
99|-------------|--------------|--------|--------|---------|---------|------- | -------|--------|
100|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 2 | Tier 3 |
101|i386 | Tier 2 | Tier 2 | Tier 4 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
102|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
103|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
104|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
105|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
106|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
107|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
108|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
109|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
110|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
111|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
112|wasm32 | Tier 3 | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
113|wasm64 | Tier 3 | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
114|avr | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
115|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | Tier 4 |
116|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | Tier 4 |
117|xcore | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
118|nvptx | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
119|msp430 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
120|r600 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
121|arc | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
122|tce | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
123|le | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
124|amdil | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
125|hsail | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
126|spir | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
127|kalimba | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
128|shave | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
129|renderscript | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
130
131## Community
132
133 * IRC: `#zig` on Freenode ([Channel Logs](https://irclog.whitequark.org/zig/)).
134 * Reddit: [/r/zig](https://www.reddit.com/r/zig)
135 * Email list: [~andrewrk/ziglang@lists.sr.ht](https://lists.sr.ht/%7Eandrewrk/ziglang)
136
137## Building
13813
139[![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)14[![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)
14015
...@@ -150,12 +25,14 @@ Note that you can...@@ -150,12 +25,14 @@ Note that you can
150 * cmake >= 2.8.525 * cmake >= 2.8.5
151 * gcc >= 5.0.0 or clang >= 3.6.026 * gcc >= 5.0.0 or clang >= 3.6.0
152 * LLVM, Clang, LLD development libraries == 8.x, compiled with the same gcc or clang version above27 * LLVM, Clang, LLD development libraries == 8.x, compiled with the same gcc or clang version above
28 - 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).
15329
154##### Windows30##### Windows
15531
156 * cmake >= 2.8.532 * cmake >= 2.8.5
157 * Microsoft Visual Studio 2017 (version 15.8)33 * Microsoft Visual Studio 2017 (version 15.8)
158 * LLVM, Clang, LLD development libraries == 8.x, compiled with the same MSVC version above34 * LLVM, Clang, LLD development libraries == 8.x, compiled with the same MSVC version above
35 - 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).
15936
160#### Instructions37#### Instructions
16138
...@@ -165,9 +42,7 @@ Note that you can...@@ -165,9 +42,7 @@ Note that you can
165mkdir build42mkdir build
166cd build43cd build
167cmake ..44cmake ..
168make
169make install45make install
170bin/zig build --build-file ../build.zig test
171```46```
17247
173##### MacOS48##### MacOS
...@@ -179,7 +54,6 @@ mkdir build...@@ -179,7 +54,6 @@ mkdir build
179cd build54cd build
180cmake .. -DCMAKE_PREFIX_PATH=/usr/local/Cellar/llvm/8.0.055cmake .. -DCMAKE_PREFIX_PATH=/usr/local/Cellar/llvm/8.0.0
181make install56make install
182bin/zig build --build-file ../build.zig test
183```57```
18458
185##### Windows59##### Windows
...@@ -222,3 +96,95 @@ use stage 1....@@ -222,3 +96,95 @@ use stage 1.
222```96```
223./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast97./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast
224```98```
99
100## Contributing
101
102### Start a Project Using Zig
103
104One of the best ways you can contribute to Zig is to start using it for a
105personal project. Here are some great examples:
106
107 * [Oxid](https://github.com/dbandstra/oxid) - arcade style game
108 * [TM35-Metronome](https://github.com/TM35-Metronome) - tools for modifying and randomizing Pokémon games
109 * [trOS](https://github.com/sjdh02/trOS) - tiny aarch64 baremetal OS thingy
110
111Without fail, these projects lead to discovering bugs and helping flesh out use
112cases, which lead to further design iterations of Zig. Importantly, each issue
113found this way comes with real world motivations, so it is easy to explain
114your reasoning behind proposals and feature requests.
115
116Ideally, such a project will help you to learn new skills and add something
117to your personal portfolio at the same time.
118
119### Spread the Word
120
121Another way to contribute is to write about Zig, or speak about Zig at a
122conference, or do either of those things for your project which uses Zig.
123Here are some examples:
124
125 * [Iterative Replacement of C with Zig](http://tiehuis.github.io/blog/zig1.html)
126 * [The Right Tool for the Right Job: Redis Modules & Zig](https://www.youtube.com/watch?v=eCHM8-_poZY)
127
128Zig is a brand new language, with no advertising budget. Word of mouth is the
129only way people find out about the project, and the more people hear about it,
130the more people will use it, and the better chance we have to take over the
131world.
132
133### Finding Contributor Friendly Issues
134
135Please note that issues labeled
136[Proposal](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aproposal)
137but do not also have the
138[Accepted](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aaccepted)
139label are still under consideration, and efforts to implement such a proposal
140have a high risk of being wasted. If you are interested in a proposal which is
141still under consideration, please express your interest in the issue tracker,
142providing extra insights and considerations that others have not yet expressed.
143The most highly regarded argument in such a discussion is a real world use case.
144
145The issue label
146[Contributor Friendly](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3A%22contributor+friendly%22)
147exists to help contributors find issues that are "limited in scope and/or
148knowledge of Zig internals."
149
150### Editing Source Code
151
152First, build the Stage 1 compiler as described in [the Building section](#building).
153
154When making changes to the standard library, be sure to edit the files in the
155`std` directory and not the installed copy in the build directory. If you add a
156new file to the standard library, you must also add the file path in
157CMakeLists.txt.
158
159To test changes, do the following from the build directory:
160
1611. Run `make install` (on POSIX) or
162 `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows).
1632. `bin/zig build --build-file ../build.zig test` (on POSIX) or
164 `bin\zig.exe build --build-file ..\build.zig test` (on Windows).
165
166That runs the whole test suite, which does a lot of extra testing that you
167likely won't always need, and can take upwards of 2 hours. This is what the
168CI server runs when you make a pull request.
169
170To save time, you can add the `--help` option to the `zig build` command and
171see what options are available. One of the most helpful ones is
172`-Dskip-release`. Adding this option to the command in step 2 above will take
173the time down from around 2 hours to about 6 minutes, and this is a good
174enough amount of testing before making a pull request.
175
176Another example is choosing a different set of things to test. For example,
177`test-std` instead of `test` will only run the standard library tests, and
178not the other ones. Combining this suggestion with the previous one, you could
179do this:
180
181`bin/zig build --build-file ../build.zig test-std -Dskip-release` (on POSIX) or
182`bin\zig.exe build --build-file ..\build.zig test-std -Dskip-release` (on Windows).
183
184This will run only the standard library tests, in debug mode only, for all
185targets (it will cross-compile the tests for non-native targets but not run
186them).
187
188When making changes to the compiler source code, the most helpful test step to
189run is `test-behavior`. When editing documentation it is `docs`. You can find
190this information and more in the `--help` menu.
build.zig+27
...@@ -65,6 +65,8 @@ pub fn build(b: *Builder) !void {...@@ -65,6 +65,8 @@ pub fn build(b: *Builder) !void {
6565
66 b.default_step.dependOn(&exe.step);66 b.default_step.dependOn(&exe.step);
6767
68 addLibUserlandStep(b);
69
68 const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;70 const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;
69 const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;71 const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;
70 const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release;72 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 {...@@ -380,3 +382,28 @@ const Context = struct {
380 dia_guids_lib: []const u8,382 dia_guids_lib: []const u8,
381 llvm: LibraryDep,383 llvm: LibraryDep,
382};384};
385
386fn addLibUserlandStep(b: *Builder) void {
387 // Sadly macOS requires hacks to work around the buggy MACH-O linker code.
388 const artifact = if (builtin.os == .macosx)
389 b.addObject("userland", "src-self-hosted/stage1.zig")
390 else
391 b.addStaticLibrary("userland", "src-self-hosted/stage1.zig");
392 artifact.disable_gen_h = true;
393 if (builtin.os == .macosx) {
394 artifact.disable_stack_probing = true;
395 } else {
396 artifact.bundle_compiler_rt = true;
397 }
398 artifact.setTarget(builtin.arch, builtin.os, builtin.abi);
399 artifact.linkSystemLibrary("c");
400 const libuserland_step = b.step("libuserland", "Build the userland compiler library for use in stage1");
401 libuserland_step.dependOn(&artifact.step);
402
403 const output_dir = b.option(
404 []const u8,
405 "output-dir",
406 "For libuserland step, where to put the output",
407 ) orelse return;
408 artifact.setOutputDir(output_dir);
409}
ci/azure/windows_upload+1-1
...@@ -6,7 +6,7 @@ set -e...@@ -6,7 +6,7 @@ set -e
6if [ "${BUILD_REASON}" != "PullRequest" ]; then6if [ "${BUILD_REASON}" != "PullRequest" ]; then
7 cd "$ZIGBUILDDIR"7 cd "$ZIGBUILDDIR"
88
9 rm release/*.lib9 rm release/*.exe
10 mv ../LICENSE release/10 mv ../LICENSE release/
11 mv ../zig-cache/langref.html release/11 mv ../zig-cache/langref.html release/
12 mv release/bin/zig.exe release/12 mv release/bin/zig.exe release/
cmake/Findclang.cmake+1-1
...@@ -44,7 +44,7 @@ else()...@@ -44,7 +44,7 @@ else()
44 /usr/local/llvm80/include44 /usr/local/llvm80/include
45 /mingw64/include)45 /mingw64/include)
4646
47 macro(FIND_AND_ADD_CLANG_LIB _libname_)47 macro(FIND_AND_ADD_CLANG_LIB _libname_)
48 string(TOUPPER ${_libname_} _prettylibname_)48 string(TOUPPER ${_libname_} _prettylibname_)
49 find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_}49 find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_}
50 PATHS50 PATHS
deps/lld/wasm/OutputSections.cpp+6-6
...@@ -111,8 +111,8 @@ void CodeSection::writeTo(uint8_t *Buf) {...@@ -111,8 +111,8 @@ void CodeSection::writeTo(uint8_t *Buf) {
111 memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());111 memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());
112112
113 // Write code section bodies113 // Write code section bodies
114 parallelForEach(Functions,114 for (const InputChunk *Chunk : Functions)
115 [&](const InputChunk *Chunk) { Chunk->writeTo(Buf); });115 Chunk->writeTo(Buf);
116}116}
117117
118uint32_t CodeSection::numRelocations() const {118uint32_t CodeSection::numRelocations() const {
...@@ -176,7 +176,7 @@ void DataSection::writeTo(uint8_t *Buf) {...@@ -176,7 +176,7 @@ void DataSection::writeTo(uint8_t *Buf) {
176 // Write data section headers176 // Write data section headers
177 memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());177 memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());
178178
179 parallelForEach(Segments, [&](const OutputSegment *Segment) {179 for (const OutputSegment *Segment : Segments) {
180 // Write data segment header180 // Write data segment header
181 uint8_t *SegStart = Buf + Segment->SectionOffset;181 uint8_t *SegStart = Buf + Segment->SectionOffset;
182 memcpy(SegStart, Segment->Header.data(), Segment->Header.size());182 memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
...@@ -184,7 +184,7 @@ void DataSection::writeTo(uint8_t *Buf) {...@@ -184,7 +184,7 @@ void DataSection::writeTo(uint8_t *Buf) {
184 // Write segment data payload184 // Write segment data payload
185 for (const InputChunk *Chunk : Segment->InputSegments)185 for (const InputChunk *Chunk : Segment->InputSegments)
186 Chunk->writeTo(Buf);186 Chunk->writeTo(Buf);
187 });187 }
188}188}
189189
190uint32_t DataSection::numRelocations() const {190uint32_t DataSection::numRelocations() const {
...@@ -232,8 +232,8 @@ void CustomSection::writeTo(uint8_t *Buf) {...@@ -232,8 +232,8 @@ void CustomSection::writeTo(uint8_t *Buf) {
232 Buf += NameData.size();232 Buf += NameData.size();
233233
234 // Write custom sections payload234 // Write custom sections payload
235 parallelForEach(InputSections,235 for (const InputSection *Section : InputSections)
236 [&](const InputSection *Section) { Section->writeTo(Buf); });236 Section->writeTo(Buf);
237}237}
238238
239uint32_t CustomSection::numRelocations() const {239uint32_t CustomSection::numRelocations() const {
doc/docgen.zig+54-1
...@@ -265,6 +265,7 @@ const SeeAlsoItem = struct {...@@ -265,6 +265,7 @@ const SeeAlsoItem = struct {
265const ExpectedOutcome = enum {265const ExpectedOutcome = enum {
266 Succeed,266 Succeed,
267 Fail,267 Fail,
268 BuildFail,
268};269};
269270
270const Code = struct {271const Code = struct {
...@@ -468,6 +469,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -468,6 +469,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
468 code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Succeed };469 code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Succeed };
469 } else if (mem.eql(u8, code_kind_str, "exe_err")) {470 } else if (mem.eql(u8, code_kind_str, "exe_err")) {
470 code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Fail };471 code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Fail };
472 } else if (mem.eql(u8, code_kind_str, "exe_build_err")) {
473 code_kind_id = Code.Id{ .Exe = ExpectedOutcome.BuildFail };
471 } else if (mem.eql(u8, code_kind_str, "test")) {474 } else if (mem.eql(u8, code_kind_str, "test")) {
472 code_kind_id = Code.Id.Test;475 code_kind_id = Code.Id.Test;
473 } else if (mem.eql(u8, code_kind_str, "test_err")) {476 } else if (mem.eql(u8, code_kind_str, "test_err")) {
...@@ -509,6 +512,10 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -509,6 +512,10 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
509 target_str = "x86_64-windows";512 target_str = "x86_64-windows";
510 } else if (mem.eql(u8, end_tag_name, "target_linux_x86_64")) {513 } else if (mem.eql(u8, end_tag_name, "target_linux_x86_64")) {
511 target_str = "x86_64-linux";514 target_str = "x86_64-linux";
515 } else if (mem.eql(u8, end_tag_name, "target_wasm")) {
516 target_str = "wasm32-freestanding";
517 } else if (mem.eql(u8, end_tag_name, "target_wasi")) {
518 target_str = "wasm32-wasi";
512 } else if (mem.eql(u8, end_tag_name, "link_libc")) {519 } else if (mem.eql(u8, end_tag_name, "link_libc")) {
513 link_libc = true;520 link_libc = true;
514 } else if (mem.eql(u8, end_tag_name, "code_end")) {521 } 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...@@ -1025,6 +1032,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1025 tmp_dir_name,1032 tmp_dir_name,
1026 "--name",1033 "--name",
1027 code.name,1034 code.name,
1035 "--color",
1036 "on",
1028 });1037 });
1029 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);1038 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);
1030 switch (code.mode) {1039 switch (code.mode) {
...@@ -1059,14 +1068,52 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1059,14 +1068,52 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1059 }1068 }
1060 if (code.target_str) |triple| {1069 if (code.target_str) |triple| {
1061 try build_args.appendSlice([][]const u8{ "-target", triple });1070 try build_args.appendSlice([][]const u8{ "-target", triple });
1071 if (!code.is_inline) {
1072 try out.print(" -target {}", triple);
1073 }
1074 }
1075 if (expected_outcome == .BuildFail) {
1076 const result = try os.ChildProcess.exec(
1077 allocator,
1078 build_args.toSliceConst(),
1079 null,
1080 &env_map,
1081 max_doc_file_size,
1082 );
1083 switch (result.term) {
1084 os.ChildProcess.Term.Exited => |exit_code| {
1085 if (exit_code == 0) {
1086 warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
1087 for (build_args.toSliceConst()) |arg|
1088 warn("{} ", arg)
1089 else
1090 warn("\n");
1091 return parseError(tokenizer, code.source_token, "example incorrectly compiled");
1092 }
1093 },
1094 else => {
1095 warn("{}\nThe following command crashed:\n", result.stderr);
1096 for (build_args.toSliceConst()) |arg|
1097 warn("{} ", arg)
1098 else
1099 warn("\n");
1100 return parseError(tokenizer, code.source_token, "example compile crashed");
1101 },
1102 }
1103 const escaped_stderr = try escapeHtml(allocator, result.stderr);
1104 const colored_stderr = try termColor(allocator, escaped_stderr);
1105 try out.print("\n{}</code></pre>\n", colored_stderr);
1106 break :code_block;
1062 }1107 }
1063 _ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");1108 _ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
10641109
1065 if (code.target_str) |triple| {1110 if (code.target_str) |triple| {
1066 if (mem.startsWith(u8, triple, "x86_64-linux") and1111 if (mem.startsWith(u8, triple, "wasm32") or
1112 mem.startsWith(u8, triple, "x86_64-linux") and
1067 (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64))1113 (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64))
1068 {1114 {
1069 // skip execution1115 // skip execution
1116 try out.print("</code></pre>\n");
1070 break :code_block;1117 break :code_block;
1071 }1118 }
1072 }1119 }
...@@ -1130,6 +1177,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1130,6 +1177,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1130 }1177 }
1131 if (code.target_str) |triple| {1178 if (code.target_str) |triple| {
1132 try test_args.appendSlice([][]const u8{ "-target", triple });1179 try test_args.appendSlice([][]const u8{ "-target", triple });
1180 try out.print(" -target {}", triple);
1133 }1181 }
1134 const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");1182 const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
1135 const escaped_stderr = try escapeHtml(allocator, result.stderr);1183 const escaped_stderr = try escapeHtml(allocator, result.stderr);
...@@ -1310,6 +1358,11 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1310,6 +1358,11 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1310 },1358 },
1311 }1359 }
13121360
1361 if (code.target_str) |triple| {
1362 try build_args.appendSlice([][]const u8{ "-target", triple });
1363 try out.print(" -target {}", triple);
1364 }
1365
1313 if (maybe_error_match) |error_match| {1366 if (maybe_error_match) |error_match| {
1314 const result = try os.ChildProcess.exec(allocator, build_args.toSliceConst(), null, &env_map, max_doc_file_size);1367 const result = try os.ChildProcess.exec(allocator, build_args.toSliceConst(), null, &env_map, max_doc_file_size);
1315 switch (result.term) {1368 switch (result.term) {
doc/langref.html.in+74-35
...@@ -4,11 +4,12 @@...@@ -4,11 +4,12 @@
4 <meta charset="utf-8">4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />5 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
6 <title>Documentation - The Zig Programming Language</title>6 <title>Documentation - The Zig Programming Language</title>
7 <link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNSAxMCIgZmlsbD0iI2Y3YTQxZCI+PHBhdGggZD0iTTAsMSBIMy41IFYzIEgyIFY3IEgzLjY4MiBMMS44ODEsOSBIMCBaIE0xNSw5IEgxMS41IFY3IEgxMyBWMyBIMTEuMzE4IEwxMy4xMTksMSBIMTUgWiBNNCwxIEg5LjkxMiBMMTMuMzI4LDAuMDIxIEw3LjA0NSw3IEgxMSBWOSBINS4wODggTDEuNjcyLDkuOTc5IEw3Ljk1NSwzIEg0IFoiLz48L3N2Zz4="/>
7 <style type="text/css">8 <style type="text/css">
8 body{9 body{
9 font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;10 font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
10 }11 }
11 a {12 a:not(:hover) {
12 text-decoration: none;13 text-decoration: none;
13 }14 }
14 table, th, td {15 table, th, td {
...@@ -158,13 +159,15 @@...@@ -158,13 +159,15 @@
158 <div id="contents">159 <div id="contents">
159 {#header_open|Introduction#}160 {#header_open|Introduction#}
160 <p>161 <p>
161 Zig is an open-source programming language designed for <strong>robustness</strong>,162 Zig is a general-purpose programming language designed for <strong>robustness</strong>,
162 <strong>optimality</strong>, and <strong>clarity</strong>.163 <strong>optimality</strong>, and <strong>maintainability</strong>.
163 </p>164 </p>
164 <ul>165 <ul>
165 <li><strong>Robust</strong> - behavior is correct even for edge cases such as out of memory.</li>166 <li><strong>Robust</strong> - behavior is correct even for edge cases such as out of memory.</li>
166 <li><strong>Optimal</strong> - write programs the best way they can behave and perform.</li>167 <li><strong>Optimal</strong> - write programs the best way they can behave and perform.</li>
167 <li><strong>Clear</strong> - precisely communicate your intent to the compiler and other programmers. The language imposes a low overhead to reading code.</li>168 <li><strong>Maintainable</strong> - precisely communicate intent to the compiler and other programmers.
169 The language imposes a low overhead to reading code and is resilient to changing requirements
170 and environments.</li>
168 </ul>171 </ul>
169 <p>172 <p>
170 Often the most efficient way to learn something new is to see examples, so173 Often the most efficient way to learn something new is to see examples, so
...@@ -3125,7 +3128,7 @@ test "while null capture" {...@@ -3125,7 +3128,7 @@ test "while null capture" {
3125 while (eventuallyNullSequence()) |value| {3128 while (eventuallyNullSequence()) |value| {
3126 sum2 += value;3129 sum2 += value;
3127 } else {3130 } else {
3128 assert(sum1 == 3);3131 assert(sum2 == 3);
3129 }3132 }
3130}3133}
31313134
...@@ -7180,14 +7183,6 @@ pub const FloatMode = enum {...@@ -7180,14 +7183,6 @@ pub const FloatMode = enum {
7180 {#see_also|Floating Point Operations#}7183 {#see_also|Floating Point Operations#}
7181 {#header_close#}7184 {#header_close#}
71827185
7183 {#header_open|@setGlobalLinkage#}
7184 <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>
7185 <p>
7186 {#syntax#}GlobalLinkage{#endsyntax#} can be found with {#syntax#}@import("builtin").GlobalLinkage{#endsyntax#}.
7187 </p>
7188 {#see_also|Compile Variables#}
7189 {#header_close#}
7190
7191 {#header_open|@setRuntimeSafety#}7186 {#header_open|@setRuntimeSafety#}
7192 <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>7187 <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
7193 <p>7188 <p>
...@@ -7217,6 +7212,8 @@ test "@setRuntimeSafety" {...@@ -7217,6 +7212,8 @@ test "@setRuntimeSafety" {
7217 }7212 }
7218}7213}
7219 {#code_end#}7214 {#code_end#}
7215 <p>Note: it is <a href="https://github.com/ziglang/zig/issues/978">planned</a> to replace
7216 {#syntax#}@setRuntimeSafety{#endsyntax#} with <code>@optimizeFor</code></p>
72207217
7221 {#header_close#}7218 {#header_close#}
72227219
...@@ -7272,6 +7269,10 @@ test "@setRuntimeSafety" {...@@ -7272,6 +7269,10 @@ test "@setRuntimeSafety" {
7272 consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or7269 consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or
7273 {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}.7270 {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}.
7274 </p>7271 </p>
7272 <p>
7273 This function measures the size at runtime. For types that are disallowed at runtime, such as
7274 {#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}.
7275 </p>
7275 {#see_also|@typeInfo#}7276 {#see_also|@typeInfo#}
7276 {#header_close#}7277 {#header_close#}
72777278
...@@ -7360,20 +7361,30 @@ fn List(comptime T: type) type {...@@ -7360,20 +7361,30 @@ fn List(comptime T: type) type {
7360 <pre>{#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}</pre>7361 <pre>{#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}</pre>
7361 <p>7362 <p>
7362 This function truncates bits from an integer type, resulting in a smaller7363 This function truncates bits from an integer type, resulting in a smaller
7363 integer type.7364 or same-sized integer type.
7364 </p>7365 </p>
7365 <p>7366 <p>
7366 The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in7367 The following produces safety-checked {#link|Undefined Behavior#}:
7367 {#link|ReleaseFast#} mode:
7368 </p>7368 </p>
7369 <pre>{#syntax#}const a: u16 = 0xabcd;7369 {#code_begin|test_err|cast truncated bits#}
7370const b: u8 = u8(a);{#endsyntax#}</pre>7370test "integer cast panic" {
7371 var a: u16 = 0xabcd;
7372 var b: u8 = @intCast(u8, a);
7373}
7374 {#code_end#}
7371 <p>7375 <p>
7372 However this is well defined and working code:7376 However this is well defined and working code:
7373 </p>7377 </p>
7374 <pre>{#syntax#}const a: u16 = 0xabcd;7378 {#code_begin|test|truncate#}
7375const b: u8 = @truncate(u8, a);7379const std = @import("std");
7376// b is now 0xcd{#endsyntax#}</pre>7380const assert = std.debug.assert;
7381
7382test "integer truncation" {
7383 var a: u16 = 0xabcd;
7384 var b: u8 = @truncate(u8, a);
7385 assert(b == 0xcd);
7386}
7387 {#code_end#}
7377 <p>7388 <p>
7378 This function always truncates the significant bits of the integer, regardless7389 This function always truncates the significant bits of the integer, regardless
7379 of endianness on the target platform.7390 of endianness on the target platform.
...@@ -8840,20 +8851,21 @@ export fn add(a: i32, b: i32) i32 {...@@ -8840,20 +8851,21 @@ export fn add(a: i32, b: i32) i32 {
8840 return a + b;8851 return a + b;
8841}8852}
8842 {#code_end#}8853 {#code_end#}
8843 <p>To make a shared library:</p>8854 <p>To make a static library:</p>
8844 <pre><code class="shell">$ zig build-lib mathtest.zig8855 <pre><code class="shell">$ zig build-lib mathtest.zig
8845</code></pre>8856</code></pre>
8846 <p>To make a static library:</p>8857 <p>To make a shared library:</p>
8847 <pre><code class="shell">$ zig build-lib mathtest.zig --static8858 <pre><code class="shell">$ zig build-lib mathtest.zig -dynamic
8848</code></pre>8859</code></pre>
8849 <p>Here is an example with the {#link|Zig Build System#}:</p>8860 <p>Here is an example with the {#link|Zig Build System#}:</p>
8850 <p class="file">test.c</p>8861 <p class="file">test.c</p>
8851 <pre><code class="cpp">// This header is generated by zig from mathtest.zig8862 <pre><code class="cpp">// This header is generated by zig from mathtest.zig
8852#include "mathtest.h"8863#include "mathtest.h"
8853#include &lt;assert.h&gt;8864#include &lt;stdio.h&gt;
88548865
8855int main(int argc, char **argv) {8866int main(int argc, char **argv) {
8856 assert(add(42, 1337) == 1379);8867 int32_t result = add(42, 1337);
8868 printf("%d\n", result);
8857 return 0;8869 return 0;
8858}</code></pre>8870}</code></pre>
8859 <p class="file">build.zig</p>8871 <p class="file">build.zig</p>
...@@ -8863,10 +8875,10 @@ const Builder = @import("std").build.Builder;...@@ -8863,10 +8875,10 @@ const Builder = @import("std").build.Builder;
8863pub fn build(b: *Builder) void {8875pub fn build(b: *Builder) void {
8864 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));8876 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
88658877
8866 const exe = b.addCExecutable("test");8878 const exe = b.addExecutable("test", null);
8867 exe.addCompileFlags([][]const u8{"-std=c99"});8879 exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
8868 exe.addSourceFile("test.c");
8869 exe.linkLibrary(lib);8880 exe.linkLibrary(lib);
8881 exe.linkSystemLibrary("c");
88708882
8871 b.default_step.dependOn(&exe.step);8883 b.default_step.dependOn(&exe.step);
88728884
...@@ -8877,10 +8889,9 @@ pub fn build(b: *Builder) void {...@@ -8877,10 +8889,9 @@ pub fn build(b: *Builder) void {
8877}8889}
8878 {#code_end#}8890 {#code_end#}
8879 <p class="file">terminal</p>8891 <p class="file">terminal</p>
8880 <pre><code class="shell">$ zig build8892 <pre><code class="shell">$ zig build test
8881$ ./test88931379
8882$ echo $?8894</code></pre>
88830</code></pre>
8884 {#see_also|export#}8895 {#see_also|export#}
8885 {#header_close#}8896 {#header_close#}
8886 {#header_open|Mixing Object Files#}8897 {#header_open|Mixing Object Files#}
...@@ -8947,6 +8958,33 @@ all your base are belong to us</code></pre>...@@ -8947,6 +8958,33 @@ all your base are belong to us</code></pre>
8947 {#see_also|Targets|Zig Build System#}8958 {#see_also|Targets|Zig Build System#}
8948 {#header_close#}8959 {#header_close#}
8949 {#header_close#}8960 {#header_close#}
8961 {#header_open|WebAssembly#}
8962 {#header_open|Freestanding#}
8963 {#code_begin|exe|wasm#}
8964 {#target_wasm#}
8965extern fn print(i32) void;
8966
8967export fn add(a: i32, b: i32) void {
8968 print(a + b);
8969}
8970 {#code_end#}
8971 {#header_close#}
8972 {#header_open|WASI#}
8973 {#code_begin|exe|wasi#}
8974 {#target_wasi#}
8975const std = @import("std");
8976
8977pub fn main() !void {
8978 const args = try std.os.argsAlloc(std.heap.wasm_allocator);
8979 defer std.os.argsFree(std.heap.wasm_allocator, args);
8980
8981 for (args) |arg, i| {
8982 std.debug.warn("{}: {}\n", i, arg);
8983 }
8984}
8985 {#code_end#}
8986 {#header_close#}
8987 {#header_close#}
8950 {#header_open|Targets#}8988 {#header_open|Targets#}
8951 <p>8989 <p>
8952 Zig supports generating code for all targets that LLVM supports. Here is8990 Zig supports generating code for all targets that LLVM supports. Here is
...@@ -9430,8 +9468,6 @@ PrimaryExpr...@@ -9430,8 +9468,6 @@ PrimaryExpr
94309468
9431IfExpr &lt;- IfPrefix Expr (KEYWORD_else Payload? Expr)?9469IfExpr &lt;- IfPrefix Expr (KEYWORD_else Payload? Expr)?
94329470
9433LabeledExpr &lt;- BlockLabel? (Block / LoopExpr)
9434
9435Block &lt;- LBRACE Statement* RBRACE9471Block &lt;- LBRACE Statement* RBRACE
94369472
9437LoopExpr &lt;- KEYWORD_inline? (ForExpr / WhileExpr)9473LoopExpr &lt;- KEYWORD_inline? (ForExpr / WhileExpr)
...@@ -9440,6 +9476,8 @@ ForExpr &lt;- ForPrefix Expr (KEYWORD_else Expr)?...@@ -9440,6 +9476,8 @@ ForExpr &lt;- ForPrefix Expr (KEYWORD_else Expr)?
94409476
9441WhileExpr &lt;- WhilePrefix Expr (KEYWORD_else Payload? Expr)?9477WhileExpr &lt;- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
94429478
9479CurlySuffixExpr &lt;- TypeExpr InitList?
9480
9443InitList9481InitList
9444 &lt;- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE9482 &lt;- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
9445 / LBRACE Expr (COMMA Expr)* COMMA? RBRACE9483 / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
...@@ -9457,6 +9495,7 @@ PrimaryTypeExpr...@@ -9457,6 +9495,7 @@ PrimaryTypeExpr
9457 &lt;- BUILTINIDENTIFIER FnCallArguments9495 &lt;- BUILTINIDENTIFIER FnCallArguments
9458 / CHAR_LITERAL9496 / CHAR_LITERAL
9459 / ContainerDecl9497 / ContainerDecl
9498 / DOT IDENTIFIER
9460 / ErrorSetDecl9499 / ErrorSetDecl
9461 / FLOAT9500 / FLOAT
9462 / FnProto9501 / FnProto
src-self-hosted/clang.zig created+866
...@@ -0,0 +1,866 @@
1pub const struct_ZigClangAPValue = @OpaqueType();
2pub const struct_ZigClangAPSInt = @OpaqueType();
3pub const struct_ZigClangASTContext = @OpaqueType();
4pub const struct_ZigClangASTUnit = @OpaqueType();
5pub const struct_ZigClangArraySubscriptExpr = @OpaqueType();
6pub const struct_ZigClangArrayType = @OpaqueType();
7pub const struct_ZigClangAttributedType = @OpaqueType();
8pub const struct_ZigClangBinaryOperator = @OpaqueType();
9pub const struct_ZigClangBreakStmt = @OpaqueType();
10pub const struct_ZigClangBuiltinType = @OpaqueType();
11pub const struct_ZigClangCStyleCastExpr = @OpaqueType();
12pub const struct_ZigClangCallExpr = @OpaqueType();
13pub const struct_ZigClangCaseStmt = @OpaqueType();
14pub const struct_ZigClangCompoundAssignOperator = @OpaqueType();
15pub const ZigClangCompoundStmt = @OpaqueType();
16pub const struct_ZigClangConditionalOperator = @OpaqueType();
17pub const struct_ZigClangConstantArrayType = @OpaqueType();
18pub const struct_ZigClangContinueStmt = @OpaqueType();
19pub const struct_ZigClangDecayedType = @OpaqueType();
20pub const struct_ZigClangDecl = @OpaqueType();
21pub const struct_ZigClangDeclRefExpr = @OpaqueType();
22pub const struct_ZigClangDeclStmt = @OpaqueType();
23pub const struct_ZigClangDefaultStmt = @OpaqueType();
24pub const struct_ZigClangDiagnosticOptions = @OpaqueType();
25pub const struct_ZigClangDiagnosticsEngine = @OpaqueType();
26pub const struct_ZigClangDoStmt = @OpaqueType();
27pub const struct_ZigClangElaboratedType = @OpaqueType();
28pub const struct_ZigClangEnumConstantDecl = @OpaqueType();
29pub const struct_ZigClangEnumDecl = @OpaqueType();
30pub const struct_ZigClangEnumType = @OpaqueType();
31pub const struct_ZigClangExpr = @OpaqueType();
32pub const struct_ZigClangFieldDecl = @OpaqueType();
33pub const struct_ZigClangFileID = @OpaqueType();
34pub const struct_ZigClangForStmt = @OpaqueType();
35pub const struct_ZigClangFullSourceLoc = @OpaqueType();
36pub const ZigClangFunctionDecl = @OpaqueType();
37pub const struct_ZigClangFunctionProtoType = @OpaqueType();
38pub const struct_ZigClangIfStmt = @OpaqueType();
39pub const struct_ZigClangImplicitCastExpr = @OpaqueType();
40pub const struct_ZigClangIncompleteArrayType = @OpaqueType();
41pub const struct_ZigClangIntegerLiteral = @OpaqueType();
42pub const struct_ZigClangMacroDefinitionRecord = @OpaqueType();
43pub const struct_ZigClangMemberExpr = @OpaqueType();
44pub const struct_ZigClangNamedDecl = @OpaqueType();
45pub const struct_ZigClangNone = @OpaqueType();
46pub const struct_ZigClangPCHContainerOperations = @OpaqueType();
47pub const struct_ZigClangParenExpr = @OpaqueType();
48pub const struct_ZigClangParenType = @OpaqueType();
49pub const struct_ZigClangParmVarDecl = @OpaqueType();
50pub const struct_ZigClangPointerType = @OpaqueType();
51pub const struct_ZigClangPreprocessedEntity = @OpaqueType();
52pub const struct_ZigClangRecordDecl = @OpaqueType();
53pub const struct_ZigClangRecordType = @OpaqueType();
54pub const struct_ZigClangReturnStmt = @OpaqueType();
55pub const struct_ZigClangSkipFunctionBodiesScope = @OpaqueType();
56pub const struct_ZigClangSourceManager = @OpaqueType();
57pub const struct_ZigClangSourceRange = @OpaqueType();
58pub const struct_ZigClangStmt = @OpaqueType();
59pub const struct_ZigClangStringLiteral = @OpaqueType();
60pub const struct_ZigClangStringRef = @OpaqueType();
61pub const struct_ZigClangSwitchStmt = @OpaqueType();
62pub const struct_ZigClangTagDecl = @OpaqueType();
63pub const struct_ZigClangType = @OpaqueType();
64pub const struct_ZigClangTypedefNameDecl = @OpaqueType();
65pub const struct_ZigClangTypedefType = @OpaqueType();
66pub const struct_ZigClangUnaryExprOrTypeTraitExpr = @OpaqueType();
67pub const struct_ZigClangUnaryOperator = @OpaqueType();
68pub const struct_ZigClangValueDecl = @OpaqueType();
69pub const struct_ZigClangVarDecl = @OpaqueType();
70pub const struct_ZigClangWhileStmt = @OpaqueType();
71pub const ZigClangFunctionType = @OpaqueType();
72
73pub const ZigClangBO = extern enum {
74 PtrMemD,
75 PtrMemI,
76 Mul,
77 Div,
78 Rem,
79 Add,
80 Sub,
81 Shl,
82 Shr,
83 Cmp,
84 LT,
85 GT,
86 LE,
87 GE,
88 EQ,
89 NE,
90 And,
91 Xor,
92 Or,
93 LAnd,
94 LOr,
95 Assign,
96 MulAssign,
97 DivAssign,
98 RemAssign,
99 AddAssign,
100 SubAssign,
101 ShlAssign,
102 ShrAssign,
103 AndAssign,
104 XorAssign,
105 OrAssign,
106 Comma,
107};
108
109pub const ZigClangUO = extern enum {
110 PostInc,
111 PostDec,
112 PreInc,
113 PreDec,
114 AddrOf,
115 Deref,
116 Plus,
117 Minus,
118 Not,
119 LNot,
120 Real,
121 Imag,
122 Extension,
123 Coawait,
124};
125
126pub const ZigClangTypeClass = extern enum {
127 Builtin,
128 Complex,
129 Pointer,
130 BlockPointer,
131 LValueReference,
132 RValueReference,
133 MemberPointer,
134 ConstantArray,
135 IncompleteArray,
136 VariableArray,
137 DependentSizedArray,
138 DependentSizedExtVector,
139 DependentAddressSpace,
140 Vector,
141 DependentVector,
142 ExtVector,
143 FunctionProto,
144 FunctionNoProto,
145 UnresolvedUsing,
146 Paren,
147 Typedef,
148 Adjusted,
149 Decayed,
150 TypeOfExpr,
151 TypeOf,
152 Decltype,
153 UnaryTransform,
154 Record,
155 Enum,
156 Elaborated,
157 Attributed,
158 TemplateTypeParm,
159 SubstTemplateTypeParm,
160 SubstTemplateTypeParmPack,
161 TemplateSpecialization,
162 Auto,
163 DeducedTemplateSpecialization,
164 InjectedClassName,
165 DependentName,
166 DependentTemplateSpecialization,
167 PackExpansion,
168 ObjCTypeParam,
169 ObjCObject,
170 ObjCInterface,
171 ObjCObjectPointer,
172 Pipe,
173 Atomic,
174};
175
176pub const ZigClangStmtClass = extern enum {
177 NoStmtClass = 0,
178 GCCAsmStmtClass = 1,
179 MSAsmStmtClass = 2,
180 AttributedStmtClass = 3,
181 BreakStmtClass = 4,
182 CXXCatchStmtClass = 5,
183 CXXForRangeStmtClass = 6,
184 CXXTryStmtClass = 7,
185 CapturedStmtClass = 8,
186 CompoundStmtClass = 9,
187 ContinueStmtClass = 10,
188 CoreturnStmtClass = 11,
189 CoroutineBodyStmtClass = 12,
190 DeclStmtClass = 13,
191 DoStmtClass = 14,
192 BinaryConditionalOperatorClass = 15,
193 ConditionalOperatorClass = 16,
194 AddrLabelExprClass = 17,
195 ArrayInitIndexExprClass = 18,
196 ArrayInitLoopExprClass = 19,
197 ArraySubscriptExprClass = 20,
198 ArrayTypeTraitExprClass = 21,
199 AsTypeExprClass = 22,
200 AtomicExprClass = 23,
201 BinaryOperatorClass = 24,
202 CompoundAssignOperatorClass = 25,
203 BlockExprClass = 26,
204 CXXBindTemporaryExprClass = 27,
205 CXXBoolLiteralExprClass = 28,
206 CXXConstructExprClass = 29,
207 CXXTemporaryObjectExprClass = 30,
208 CXXDefaultArgExprClass = 31,
209 CXXDefaultInitExprClass = 32,
210 CXXDeleteExprClass = 33,
211 CXXDependentScopeMemberExprClass = 34,
212 CXXFoldExprClass = 35,
213 CXXInheritedCtorInitExprClass = 36,
214 CXXNewExprClass = 37,
215 CXXNoexceptExprClass = 38,
216 CXXNullPtrLiteralExprClass = 39,
217 CXXPseudoDestructorExprClass = 40,
218 CXXScalarValueInitExprClass = 41,
219 CXXStdInitializerListExprClass = 42,
220 CXXThisExprClass = 43,
221 CXXThrowExprClass = 44,
222 CXXTypeidExprClass = 45,
223 CXXUnresolvedConstructExprClass = 46,
224 CXXUuidofExprClass = 47,
225 CallExprClass = 48,
226 CUDAKernelCallExprClass = 49,
227 CXXMemberCallExprClass = 50,
228 CXXOperatorCallExprClass = 51,
229 UserDefinedLiteralClass = 52,
230 CStyleCastExprClass = 53,
231 CXXFunctionalCastExprClass = 54,
232 CXXConstCastExprClass = 55,
233 CXXDynamicCastExprClass = 56,
234 CXXReinterpretCastExprClass = 57,
235 CXXStaticCastExprClass = 58,
236 ObjCBridgedCastExprClass = 59,
237 ImplicitCastExprClass = 60,
238 CharacterLiteralClass = 61,
239 ChooseExprClass = 62,
240 CompoundLiteralExprClass = 63,
241 ConvertVectorExprClass = 64,
242 CoawaitExprClass = 65,
243 CoyieldExprClass = 66,
244 DeclRefExprClass = 67,
245 DependentCoawaitExprClass = 68,
246 DependentScopeDeclRefExprClass = 69,
247 DesignatedInitExprClass = 70,
248 DesignatedInitUpdateExprClass = 71,
249 ExpressionTraitExprClass = 72,
250 ExtVectorElementExprClass = 73,
251 FixedPointLiteralClass = 74,
252 FloatingLiteralClass = 75,
253 ConstantExprClass = 76,
254 ExprWithCleanupsClass = 77,
255 FunctionParmPackExprClass = 78,
256 GNUNullExprClass = 79,
257 GenericSelectionExprClass = 80,
258 ImaginaryLiteralClass = 81,
259 ImplicitValueInitExprClass = 82,
260 InitListExprClass = 83,
261 IntegerLiteralClass = 84,
262 LambdaExprClass = 85,
263 MSPropertyRefExprClass = 86,
264 MSPropertySubscriptExprClass = 87,
265 MaterializeTemporaryExprClass = 88,
266 MemberExprClass = 89,
267 NoInitExprClass = 90,
268 OMPArraySectionExprClass = 91,
269 ObjCArrayLiteralClass = 92,
270 ObjCAvailabilityCheckExprClass = 93,
271 ObjCBoolLiteralExprClass = 94,
272 ObjCBoxedExprClass = 95,
273 ObjCDictionaryLiteralClass = 96,
274 ObjCEncodeExprClass = 97,
275 ObjCIndirectCopyRestoreExprClass = 98,
276 ObjCIsaExprClass = 99,
277 ObjCIvarRefExprClass = 100,
278 ObjCMessageExprClass = 101,
279 ObjCPropertyRefExprClass = 102,
280 ObjCProtocolExprClass = 103,
281 ObjCSelectorExprClass = 104,
282 ObjCStringLiteralClass = 105,
283 ObjCSubscriptRefExprClass = 106,
284 OffsetOfExprClass = 107,
285 OpaqueValueExprClass = 108,
286 UnresolvedLookupExprClass = 109,
287 UnresolvedMemberExprClass = 110,
288 PackExpansionExprClass = 111,
289 ParenExprClass = 112,
290 ParenListExprClass = 113,
291 PredefinedExprClass = 114,
292 PseudoObjectExprClass = 115,
293 ShuffleVectorExprClass = 116,
294 SizeOfPackExprClass = 117,
295 StmtExprClass = 118,
296 StringLiteralClass = 119,
297 SubstNonTypeTemplateParmExprClass = 120,
298 SubstNonTypeTemplateParmPackExprClass = 121,
299 TypeTraitExprClass = 122,
300 TypoExprClass = 123,
301 UnaryExprOrTypeTraitExprClass = 124,
302 UnaryOperatorClass = 125,
303 VAArgExprClass = 126,
304 ForStmtClass = 127,
305 GotoStmtClass = 128,
306 IfStmtClass = 129,
307 IndirectGotoStmtClass = 130,
308 LabelStmtClass = 131,
309 MSDependentExistsStmtClass = 132,
310 NullStmtClass = 133,
311 OMPAtomicDirectiveClass = 134,
312 OMPBarrierDirectiveClass = 135,
313 OMPCancelDirectiveClass = 136,
314 OMPCancellationPointDirectiveClass = 137,
315 OMPCriticalDirectiveClass = 138,
316 OMPFlushDirectiveClass = 139,
317 OMPDistributeDirectiveClass = 140,
318 OMPDistributeParallelForDirectiveClass = 141,
319 OMPDistributeParallelForSimdDirectiveClass = 142,
320 OMPDistributeSimdDirectiveClass = 143,
321 OMPForDirectiveClass = 144,
322 OMPForSimdDirectiveClass = 145,
323 OMPParallelForDirectiveClass = 146,
324 OMPParallelForSimdDirectiveClass = 147,
325 OMPSimdDirectiveClass = 148,
326 OMPTargetParallelForSimdDirectiveClass = 149,
327 OMPTargetSimdDirectiveClass = 150,
328 OMPTargetTeamsDistributeDirectiveClass = 151,
329 OMPTargetTeamsDistributeParallelForDirectiveClass = 152,
330 OMPTargetTeamsDistributeParallelForSimdDirectiveClass = 153,
331 OMPTargetTeamsDistributeSimdDirectiveClass = 154,
332 OMPTaskLoopDirectiveClass = 155,
333 OMPTaskLoopSimdDirectiveClass = 156,
334 OMPTeamsDistributeDirectiveClass = 157,
335 OMPTeamsDistributeParallelForDirectiveClass = 158,
336 OMPTeamsDistributeParallelForSimdDirectiveClass = 159,
337 OMPTeamsDistributeSimdDirectiveClass = 160,
338 OMPMasterDirectiveClass = 161,
339 OMPOrderedDirectiveClass = 162,
340 OMPParallelDirectiveClass = 163,
341 OMPParallelSectionsDirectiveClass = 164,
342 OMPSectionDirectiveClass = 165,
343 OMPSectionsDirectiveClass = 166,
344 OMPSingleDirectiveClass = 167,
345 OMPTargetDataDirectiveClass = 168,
346 OMPTargetDirectiveClass = 169,
347 OMPTargetEnterDataDirectiveClass = 170,
348 OMPTargetExitDataDirectiveClass = 171,
349 OMPTargetParallelDirectiveClass = 172,
350 OMPTargetParallelForDirectiveClass = 173,
351 OMPTargetTeamsDirectiveClass = 174,
352 OMPTargetUpdateDirectiveClass = 175,
353 OMPTaskDirectiveClass = 176,
354 OMPTaskgroupDirectiveClass = 177,
355 OMPTaskwaitDirectiveClass = 178,
356 OMPTaskyieldDirectiveClass = 179,
357 OMPTeamsDirectiveClass = 180,
358 ObjCAtCatchStmtClass = 181,
359 ObjCAtFinallyStmtClass = 182,
360 ObjCAtSynchronizedStmtClass = 183,
361 ObjCAtThrowStmtClass = 184,
362 ObjCAtTryStmtClass = 185,
363 ObjCAutoreleasePoolStmtClass = 186,
364 ObjCForCollectionStmtClass = 187,
365 ReturnStmtClass = 188,
366 SEHExceptStmtClass = 189,
367 SEHFinallyStmtClass = 190,
368 SEHLeaveStmtClass = 191,
369 SEHTryStmtClass = 192,
370 CaseStmtClass = 193,
371 DefaultStmtClass = 194,
372 SwitchStmtClass = 195,
373 WhileStmtClass = 196,
374};
375
376pub const ZigClangCK = extern enum {
377 Dependent,
378 BitCast,
379 LValueBitCast,
380 LValueToRValue,
381 NoOp,
382 BaseToDerived,
383 DerivedToBase,
384 UncheckedDerivedToBase,
385 Dynamic,
386 ToUnion,
387 ArrayToPointerDecay,
388 FunctionToPointerDecay,
389 NullToPointer,
390 NullToMemberPointer,
391 BaseToDerivedMemberPointer,
392 DerivedToBaseMemberPointer,
393 MemberPointerToBoolean,
394 ReinterpretMemberPointer,
395 UserDefinedConversion,
396 ConstructorConversion,
397 IntegralToPointer,
398 PointerToIntegral,
399 PointerToBoolean,
400 ToVoid,
401 VectorSplat,
402 IntegralCast,
403 IntegralToBoolean,
404 IntegralToFloating,
405 FixedPointCast,
406 FixedPointToBoolean,
407 FloatingToIntegral,
408 FloatingToBoolean,
409 BooleanToSignedIntegral,
410 FloatingCast,
411 CPointerToObjCPointerCast,
412 BlockPointerToObjCPointerCast,
413 AnyPointerToBlockPointerCast,
414 ObjCObjectLValueCast,
415 FloatingRealToComplex,
416 FloatingComplexToReal,
417 FloatingComplexToBoolean,
418 FloatingComplexCast,
419 FloatingComplexToIntegralComplex,
420 IntegralRealToComplex,
421 IntegralComplexToReal,
422 IntegralComplexToBoolean,
423 IntegralComplexCast,
424 IntegralComplexToFloatingComplex,
425 ARCProduceObject,
426 ARCConsumeObject,
427 ARCReclaimReturnedObject,
428 ARCExtendBlockObject,
429 AtomicToNonAtomic,
430 NonAtomicToAtomic,
431 CopyAndAutoreleaseBlockObject,
432 BuiltinFnToFnPtr,
433 ZeroToOCLOpaqueType,
434 AddressSpaceConversion,
435 IntToOCLSampler,
436};
437
438pub const ZigClangAPValueKind = extern enum {
439 Uninitialized,
440 Int,
441 Float,
442 ComplexInt,
443 ComplexFloat,
444 LValue,
445 Vector,
446 Array,
447 Struct,
448 Union,
449 MemberPointer,
450 AddrLabelDiff,
451};
452
453pub extern fn ZigClangSourceManager_getSpellingLoc(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
454pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*]const u8;
455pub extern fn ZigClangSourceManager_getSpellingLineNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
456pub extern fn ZigClangSourceManager_getSpellingColumnNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
457pub extern fn ZigClangSourceManager_getCharacterData(arg0: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8;
458pub extern fn ZigClangASTContext_getPointerType(arg0: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType;
459pub extern fn ZigClangASTUnit_getASTContext(arg0: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext;
460pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
461pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;
462pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) ?*const struct_ZigClangRecordDecl;
463pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;
464pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
465pub extern fn ZigClangEnumDecl_getCanonicalDecl(arg0: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
466pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(arg0: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;
467pub extern fn ZigClangRecordDecl_getDefinition(arg0: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangRecordDecl;
468pub extern fn ZigClangEnumDecl_getDefinition(arg0: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangEnumDecl;
469pub extern fn ZigClangRecordDecl_getLocation(arg0: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation;
470pub extern fn ZigClangEnumDecl_getLocation(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangSourceLocation;
471pub extern fn ZigClangTypedefNameDecl_getLocation(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangSourceLocation;
472pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSourceLocation;
473pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
474pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool;
475pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
476pub extern fn ZigClangEnumDecl_getIntegerType(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
477pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
478pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
479pub extern fn ZigClangTypedefType_getDecl(arg0: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
480pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
481pub extern fn ZigClangQualType_getCanonicalType(arg0: struct_ZigClangQualType) struct_ZigClangQualType;
482pub extern fn ZigClangQualType_getTypePtr(self: struct_ZigClangQualType) *const struct_ZigClangType;
483pub extern fn ZigClangQualType_addConst(arg0: [*c]struct_ZigClangQualType) void;
484pub extern fn ZigClangQualType_eq(arg0: struct_ZigClangQualType, arg1: struct_ZigClangQualType) bool;
485pub extern fn ZigClangQualType_isConstQualified(arg0: struct_ZigClangQualType) bool;
486pub extern fn ZigClangQualType_isVolatileQualified(arg0: struct_ZigClangQualType) bool;
487pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType) bool;
488pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
489pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
490pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
491pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
492pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
493pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
494pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass;
495pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType;
496pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation;
497pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
498pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;
499pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
500pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) ?*const struct_ZigClangAPValue;
501pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPValue;
502pub extern fn ZigClangAPValue_getArraySize(self: ?*const struct_ZigClangAPValue) c_uint;
503pub extern fn ZigClangAPValue_getLValueBase(self: ?*const struct_ZigClangAPValue) struct_ZigClangAPValueLValueBase;
504pub extern fn ZigClangAPSInt_isSigned(self: ?*const struct_ZigClangAPSInt) bool;
505pub extern fn ZigClangAPSInt_isNegative(self: ?*const struct_ZigClangAPSInt) bool;
506pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const struct_ZigClangAPSInt;
507pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
508pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64;
509pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
510pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
511pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void;
512
513pub extern fn ZigClangFunctionDecl_getType(self: *const ZigClangFunctionDecl) struct_ZigClangQualType;
514pub extern fn ZigClangFunctionDecl_getLocation(self: *const ZigClangFunctionDecl) struct_ZigClangSourceLocation;
515pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bool;
516pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass;
517pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;
518pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt;
519
520pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;
521
522pub extern fn ZigClangFunctionType_getNoReturnAttr(self: *const ZigClangFunctionType) bool;
523pub extern fn ZigClangFunctionType_getCallConv(self: *const ZigClangFunctionType) ZigClangCallingConv;
524pub extern fn ZigClangFunctionType_getReturnType(self: *const ZigClangFunctionType) ZigClangQualType;
525
526pub extern fn ZigClangFunctionProtoType_isVariadic(self: *const struct_ZigClangFunctionProtoType) bool;
527pub extern fn ZigClangFunctionProtoType_getNumParams(self: *const struct_ZigClangFunctionProtoType) c_uint;
528pub extern fn ZigClangFunctionProtoType_getParamType(self: *const struct_ZigClangFunctionProtoType, i: c_uint) ZigClangQualType;
529
530pub const ZigClangSourceLocation = struct_ZigClangSourceLocation;
531pub const ZigClangQualType = struct_ZigClangQualType;
532pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase;
533pub const ZigClangAPValue = struct_ZigClangAPValue;
534pub const ZigClangAPSInt = struct_ZigClangAPSInt;
535pub const ZigClangASTContext = struct_ZigClangASTContext;
536pub const ZigClangASTUnit = struct_ZigClangASTUnit;
537pub const ZigClangArraySubscriptExpr = struct_ZigClangArraySubscriptExpr;
538pub const ZigClangArrayType = struct_ZigClangArrayType;
539pub const ZigClangAttributedType = struct_ZigClangAttributedType;
540pub const ZigClangBinaryOperator = struct_ZigClangBinaryOperator;
541pub const ZigClangBreakStmt = struct_ZigClangBreakStmt;
542pub const ZigClangBuiltinType = struct_ZigClangBuiltinType;
543pub const ZigClangCStyleCastExpr = struct_ZigClangCStyleCastExpr;
544pub const ZigClangCallExpr = struct_ZigClangCallExpr;
545pub const ZigClangCaseStmt = struct_ZigClangCaseStmt;
546pub const ZigClangCompoundAssignOperator = struct_ZigClangCompoundAssignOperator;
547pub const ZigClangConditionalOperator = struct_ZigClangConditionalOperator;
548pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType;
549pub const ZigClangContinueStmt = struct_ZigClangContinueStmt;
550pub const ZigClangDecayedType = struct_ZigClangDecayedType;
551pub const ZigClangDecl = struct_ZigClangDecl;
552pub const ZigClangDeclRefExpr = struct_ZigClangDeclRefExpr;
553pub const ZigClangDeclStmt = struct_ZigClangDeclStmt;
554pub const ZigClangDefaultStmt = struct_ZigClangDefaultStmt;
555pub const ZigClangDiagnosticOptions = struct_ZigClangDiagnosticOptions;
556pub const ZigClangDiagnosticsEngine = struct_ZigClangDiagnosticsEngine;
557pub const ZigClangDoStmt = struct_ZigClangDoStmt;
558pub const ZigClangElaboratedType = struct_ZigClangElaboratedType;
559pub const ZigClangEnumConstantDecl = struct_ZigClangEnumConstantDecl;
560pub const ZigClangEnumDecl = struct_ZigClangEnumDecl;
561pub const ZigClangEnumType = struct_ZigClangEnumType;
562pub const ZigClangExpr = struct_ZigClangExpr;
563pub const ZigClangFieldDecl = struct_ZigClangFieldDecl;
564pub const ZigClangFileID = struct_ZigClangFileID;
565pub const ZigClangForStmt = struct_ZigClangForStmt;
566pub const ZigClangFullSourceLoc = struct_ZigClangFullSourceLoc;
567pub const ZigClangFunctionProtoType = struct_ZigClangFunctionProtoType;
568pub const ZigClangIfStmt = struct_ZigClangIfStmt;
569pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr;
570pub const ZigClangIncompleteArrayType = struct_ZigClangIncompleteArrayType;
571pub const ZigClangIntegerLiteral = struct_ZigClangIntegerLiteral;
572pub const ZigClangMacroDefinitionRecord = struct_ZigClangMacroDefinitionRecord;
573pub const ZigClangMemberExpr = struct_ZigClangMemberExpr;
574pub const ZigClangNamedDecl = struct_ZigClangNamedDecl;
575pub const ZigClangNone = struct_ZigClangNone;
576pub const ZigClangPCHContainerOperations = struct_ZigClangPCHContainerOperations;
577pub const ZigClangParenExpr = struct_ZigClangParenExpr;
578pub const ZigClangParenType = struct_ZigClangParenType;
579pub const ZigClangParmVarDecl = struct_ZigClangParmVarDecl;
580pub const ZigClangPointerType = struct_ZigClangPointerType;
581pub const ZigClangPreprocessedEntity = struct_ZigClangPreprocessedEntity;
582pub const ZigClangRecordDecl = struct_ZigClangRecordDecl;
583pub const ZigClangRecordType = struct_ZigClangRecordType;
584pub const ZigClangReturnStmt = struct_ZigClangReturnStmt;
585pub const ZigClangSkipFunctionBodiesScope = struct_ZigClangSkipFunctionBodiesScope;
586pub const ZigClangSourceManager = struct_ZigClangSourceManager;
587pub const ZigClangSourceRange = struct_ZigClangSourceRange;
588pub const ZigClangStmt = struct_ZigClangStmt;
589pub const ZigClangStringLiteral = struct_ZigClangStringLiteral;
590pub const ZigClangStringRef = struct_ZigClangStringRef;
591pub const ZigClangSwitchStmt = struct_ZigClangSwitchStmt;
592pub const ZigClangTagDecl = struct_ZigClangTagDecl;
593pub const ZigClangType = struct_ZigClangType;
594pub const ZigClangTypedefNameDecl = struct_ZigClangTypedefNameDecl;
595pub const ZigClangTypedefType = struct_ZigClangTypedefType;
596pub const ZigClangUnaryExprOrTypeTraitExpr = struct_ZigClangUnaryExprOrTypeTraitExpr;
597pub const ZigClangUnaryOperator = struct_ZigClangUnaryOperator;
598pub const ZigClangValueDecl = struct_ZigClangValueDecl;
599pub const ZigClangVarDecl = struct_ZigClangVarDecl;
600pub const ZigClangWhileStmt = struct_ZigClangWhileStmt;
601
602pub const struct_ZigClangSourceLocation = extern struct {
603 ID: c_uint,
604};
605
606pub const Stage2ErrorMsg = extern struct {
607 filename_ptr: ?[*]const u8,
608 filename_len: usize,
609 msg_ptr: [*]const u8,
610 msg_len: usize,
611 // valid until the ASTUnit is freed
612 source: ?[*]const u8,
613 // 0 based
614 line: c_uint,
615 // 0 based
616 column: c_uint,
617 // byte offset into source
618 offset: c_uint,
619};
620pub extern fn ZigClangErrorMsg_delete(ptr: [*c]Stage2ErrorMsg, len: usize) void;
621
622pub extern fn ZigClangLoadFromCommandLine(
623 args_begin: [*]?[*]const u8,
624 args_end: [*]?[*]const u8,
625 errors_ptr: *[*]Stage2ErrorMsg,
626 errors_len: *usize,
627 resources_path: [*c]const u8,
628) ?*ZigClangASTUnit;
629
630pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind;
631pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*]const u8;
632
633pub const ZigClangDeclKind = extern enum {
634 AccessSpec,
635 Block,
636 Captured,
637 ClassScopeFunctionSpecialization,
638 Empty,
639 Export,
640 ExternCContext,
641 FileScopeAsm,
642 Friend,
643 FriendTemplate,
644 Import,
645 LinkageSpec,
646 Label,
647 Namespace,
648 NamespaceAlias,
649 ObjCCompatibleAlias,
650 ObjCCategory,
651 ObjCCategoryImpl,
652 ObjCImplementation,
653 ObjCInterface,
654 ObjCProtocol,
655 ObjCMethod,
656 ObjCProperty,
657 BuiltinTemplate,
658 ClassTemplate,
659 FunctionTemplate,
660 TypeAliasTemplate,
661 VarTemplate,
662 TemplateTemplateParm,
663 Enum,
664 Record,
665 CXXRecord,
666 ClassTemplateSpecialization,
667 ClassTemplatePartialSpecialization,
668 TemplateTypeParm,
669 ObjCTypeParam,
670 TypeAlias,
671 Typedef,
672 UnresolvedUsingTypename,
673 Using,
674 UsingDirective,
675 UsingPack,
676 UsingShadow,
677 ConstructorUsingShadow,
678 Binding,
679 Field,
680 ObjCAtDefsField,
681 ObjCIvar,
682 Function,
683 CXXDeductionGuide,
684 CXXMethod,
685 CXXConstructor,
686 CXXConversion,
687 CXXDestructor,
688 MSProperty,
689 NonTypeTemplateParm,
690 Var,
691 Decomposition,
692 ImplicitParam,
693 OMPCapturedExpr,
694 ParmVar,
695 VarTemplateSpecialization,
696 VarTemplatePartialSpecialization,
697 EnumConstant,
698 IndirectField,
699 OMPDeclareReduction,
700 UnresolvedUsingValue,
701 OMPRequires,
702 OMPThreadPrivate,
703 ObjCPropertyImpl,
704 PragmaComment,
705 PragmaDetectMismatch,
706 StaticAssert,
707 TranslationUnit,
708};
709
710pub const struct_ZigClangQualType = extern struct {
711 ptr: ?*c_void,
712};
713
714pub const ZigClangBuiltinTypeKind = extern enum {
715 OCLImage1dRO,
716 OCLImage1dArrayRO,
717 OCLImage1dBufferRO,
718 OCLImage2dRO,
719 OCLImage2dArrayRO,
720 OCLImage2dDepthRO,
721 OCLImage2dArrayDepthRO,
722 OCLImage2dMSAARO,
723 OCLImage2dArrayMSAARO,
724 OCLImage2dMSAADepthRO,
725 OCLImage2dArrayMSAADepthRO,
726 OCLImage3dRO,
727 OCLImage1dWO,
728 OCLImage1dArrayWO,
729 OCLImage1dBufferWO,
730 OCLImage2dWO,
731 OCLImage2dArrayWO,
732 OCLImage2dDepthWO,
733 OCLImage2dArrayDepthWO,
734 OCLImage2dMSAAWO,
735 OCLImage2dArrayMSAAWO,
736 OCLImage2dMSAADepthWO,
737 OCLImage2dArrayMSAADepthWO,
738 OCLImage3dWO,
739 OCLImage1dRW,
740 OCLImage1dArrayRW,
741 OCLImage1dBufferRW,
742 OCLImage2dRW,
743 OCLImage2dArrayRW,
744 OCLImage2dDepthRW,
745 OCLImage2dArrayDepthRW,
746 OCLImage2dMSAARW,
747 OCLImage2dArrayMSAARW,
748 OCLImage2dMSAADepthRW,
749 OCLImage2dArrayMSAADepthRW,
750 OCLImage3dRW,
751 OCLIntelSubgroupAVCMcePayload,
752 OCLIntelSubgroupAVCImePayload,
753 OCLIntelSubgroupAVCRefPayload,
754 OCLIntelSubgroupAVCSicPayload,
755 OCLIntelSubgroupAVCMceResult,
756 OCLIntelSubgroupAVCImeResult,
757 OCLIntelSubgroupAVCRefResult,
758 OCLIntelSubgroupAVCSicResult,
759 OCLIntelSubgroupAVCImeResultSingleRefStreamout,
760 OCLIntelSubgroupAVCImeResultDualRefStreamout,
761 OCLIntelSubgroupAVCImeSingleRefStreamin,
762 OCLIntelSubgroupAVCImeDualRefStreamin,
763 Void,
764 Bool,
765 Char_U,
766 UChar,
767 WChar_U,
768 Char8,
769 Char16,
770 Char32,
771 UShort,
772 UInt,
773 ULong,
774 ULongLong,
775 UInt128,
776 Char_S,
777 SChar,
778 WChar_S,
779 Short,
780 Int,
781 Long,
782 LongLong,
783 Int128,
784 ShortAccum,
785 Accum,
786 LongAccum,
787 UShortAccum,
788 UAccum,
789 ULongAccum,
790 ShortFract,
791 Fract,
792 LongFract,
793 UShortFract,
794 UFract,
795 ULongFract,
796 SatShortAccum,
797 SatAccum,
798 SatLongAccum,
799 SatUShortAccum,
800 SatUAccum,
801 SatULongAccum,
802 SatShortFract,
803 SatFract,
804 SatLongFract,
805 SatUShortFract,
806 SatUFract,
807 SatULongFract,
808 Half,
809 Float,
810 Double,
811 LongDouble,
812 Float16,
813 Float128,
814 NullPtr,
815 ObjCId,
816 ObjCClass,
817 ObjCSel,
818 OCLSampler,
819 OCLEvent,
820 OCLClkEvent,
821 OCLQueue,
822 OCLReserveID,
823 Dependent,
824 Overload,
825 BoundMember,
826 PseudoObject,
827 UnknownAny,
828 BuiltinFn,
829 ARCUnbridgedCast,
830 OMPArraySection,
831};
832
833pub const ZigClangCallingConv = extern enum {
834 C,
835 X86StdCall,
836 X86FastCall,
837 X86ThisCall,
838 X86VectorCall,
839 X86Pascal,
840 Win64,
841 X86_64SysV,
842 X86RegCall,
843 AAPCS,
844 AAPCS_VFP,
845 IntelOclBicc,
846 SpirFunction,
847 OpenCLKernel,
848 Swift,
849 PreserveMost,
850 PreserveAll,
851 AArch64VectorCall,
852};
853
854pub const ZigClangStorageClass = extern enum {
855 None,
856 Extern,
857 Static,
858 PrivateExtern,
859 Auto,
860 Register,
861};
862
863pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt;
864
865pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
866pub extern fn ZigClangCompoundStmt_body_end(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
src-self-hosted/compilation.zig+4-6
...@@ -569,9 +569,9 @@ pub const Compilation = struct {...@@ -569,9 +569,9 @@ pub const Compilation = struct {
569 'i', 'u' => blk: {569 'i', 'u' => blk: {
570 for (name[1..]) |byte|570 for (name[1..]) |byte|
571 switch (byte) {571 switch (byte) {
572 '0'...'9' => {},572 '0'...'9' => {},
573 else => break :blk,573 else => break :blk,
574 };574 };
575 const is_signed = name[0] == 'i';575 const is_signed = name[0] == 'i';
576 const bit_count = std.fmt.parseUnsigned(u32, name[1..], 10) catch |err| switch (err) {576 const bit_count = std.fmt.parseUnsigned(u32, name[1..], 10) catch |err| switch (err) {
577 error.Overflow => return error.Overflow,577 error.Overflow => return error.Overflow,
...@@ -841,11 +841,9 @@ pub const Compilation = struct {...@@ -841,11 +841,9 @@ pub const Compilation = struct {
841 };841 };
842 errdefer self.gpa().free(source_code);842 errdefer self.gpa().free(source_code);
843843
844 const tree = try self.gpa().create(ast.Tree);844 const tree = try std.zig.parse(self.gpa(), source_code);
845 tree.* = try std.zig.parse(self.gpa(), source_code);
846 errdefer {845 errdefer {
847 tree.deinit();846 tree.deinit();
848 self.gpa().destroy(tree);
849 }847 }
850848
851 break :blk try Scope.AstTree.create(self, tree, root_scope);849 break :blk try Scope.AstTree.create(self, tree, root_scope);
src-self-hosted/main.zig+9-9
...@@ -625,7 +625,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -625,7 +625,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
625 const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size);625 const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size);
626 defer allocator.free(source_code);626 defer allocator.free(source_code);
627627
628 var tree = std.zig.parse(allocator, source_code) catch |err| {628 const tree = std.zig.parse(allocator, source_code) catch |err| {
629 try stderr.print("error parsing stdin: {}\n", err);629 try stderr.print("error parsing stdin: {}\n", err);
630 os.exit(1);630 os.exit(1);
631 };631 };
...@@ -633,7 +633,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -633,7 +633,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
633633
634 var error_it = tree.errors.iterator(0);634 var error_it = tree.errors.iterator(0);
635 while (error_it.next()) |parse_error| {635 while (error_it.next()) |parse_error| {
636 const msg = try errmsg.Msg.createFromParseError(allocator, parse_error, &tree, "<stdin>");636 const msg = try errmsg.Msg.createFromParseError(allocator, parse_error, tree, "<stdin>");
637 defer msg.destroy();637 defer msg.destroy();
638638
639 try msg.printToFile(stderr_file, color);639 try msg.printToFile(stderr_file, color);
...@@ -642,12 +642,12 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -642,12 +642,12 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
642 os.exit(1);642 os.exit(1);
643 }643 }
644 if (flags.present("check")) {644 if (flags.present("check")) {
645 const anything_changed = try std.zig.render(allocator, io.null_out_stream, &tree);645 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
646 const code = if (anything_changed) u8(1) else u8(0);646 const code = if (anything_changed) u8(1) else u8(0);
647 os.exit(code);647 os.exit(code);
648 }648 }
649649
650 _ = try std.zig.render(allocator, stdout, &tree);650 _ = try std.zig.render(allocator, stdout, tree);
651 return;651 return;
652 }652 }
653653
...@@ -768,7 +768,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro...@@ -768,7 +768,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
768 };768 };
769 defer fmt.loop.allocator.free(source_code);769 defer fmt.loop.allocator.free(source_code);
770770
771 var tree = std.zig.parse(fmt.loop.allocator, source_code) catch |err| {771 const tree = std.zig.parse(fmt.loop.allocator, source_code) catch |err| {
772 try stderr.print("error parsing file '{}': {}\n", file_path, err);772 try stderr.print("error parsing file '{}': {}\n", file_path, err);
773 fmt.any_error = true;773 fmt.any_error = true;
774 return;774 return;
...@@ -777,7 +777,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro...@@ -777,7 +777,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
777777
778 var error_it = tree.errors.iterator(0);778 var error_it = tree.errors.iterator(0);
779 while (error_it.next()) |parse_error| {779 while (error_it.next()) |parse_error| {
780 const msg = try errmsg.Msg.createFromParseError(fmt.loop.allocator, parse_error, &tree, file_path);780 const msg = try errmsg.Msg.createFromParseError(fmt.loop.allocator, parse_error, tree, file_path);
781 defer fmt.loop.allocator.destroy(msg);781 defer fmt.loop.allocator.destroy(msg);
782782
783 try msg.printToFile(stderr_file, fmt.color);783 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...@@ -788,7 +788,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
788 }788 }
789789
790 if (check_mode) {790 if (check_mode) {
791 const anything_changed = try std.zig.render(fmt.loop.allocator, io.null_out_stream, &tree);791 const anything_changed = try std.zig.render(fmt.loop.allocator, io.null_out_stream, tree);
792 if (anything_changed) {792 if (anything_changed) {
793 try stderr.print("{}\n", file_path);793 try stderr.print("{}\n", file_path);
794 fmt.any_error = true;794 fmt.any_error = true;
...@@ -798,7 +798,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro...@@ -798,7 +798,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
798 const baf = try io.BufferedAtomicFile.create(fmt.loop.allocator, file_path);798 const baf = try io.BufferedAtomicFile.create(fmt.loop.allocator, file_path);
799 defer baf.destroy();799 defer baf.destroy();
800800
801 const anything_changed = try std.zig.render(fmt.loop.allocator, baf.stream(), &tree);801 const anything_changed = try std.zig.render(fmt.loop.allocator, baf.stream(), tree);
802 if (anything_changed) {802 if (anything_changed) {
803 try stderr.print("{}\n", file_path);803 try stderr.print("{}\n", file_path);
804 try baf.finish();804 try baf.finish();
...@@ -858,7 +858,7 @@ fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {...@@ -858,7 +858,7 @@ fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
858 try stdout.write(usage);858 try stdout.write(usage);
859}859}
860860
861const info_zen =861pub const info_zen =
862 \\862 \\
863 \\ * Communicate intent precisely.863 \\ * Communicate intent precisely.
864 \\ * Edge cases matter.864 \\ * Edge cases matter.
src-self-hosted/scope.zig-1
...@@ -163,7 +163,6 @@ pub const Scope = struct {...@@ -163,7 +163,6 @@ pub const Scope = struct {
163 pub fn destroy(self: *AstTree, comp: *Compilation) void {163 pub fn destroy(self: *AstTree, comp: *Compilation) void {
164 comp.gpa().free(self.tree.source);164 comp.gpa().free(self.tree.source);
165 self.tree.deinit();165 self.tree.deinit();
166 comp.gpa().destroy(self.tree);
167 comp.gpa().destroy(self);166 comp.gpa().destroy(self);
168 }167 }
169168
src-self-hosted/stage1.zig created+397
...@@ -0,0 +1,397 @@
1// This is Zig code that is used by both stage1 and stage2.
2// The prototypes in src/userland.h must match these definitions.
3
4const std = @import("std");
5const builtin = @import("builtin");
6
7// ABI warning
8export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
9 const info_zen = @import("main.zig").info_zen;
10 ptr.* = &info_zen;
11 len.* = info_zen.len;
12}
13
14// ABI warning
15export fn stage2_panic(ptr: [*]const u8, len: usize) void {
16 @panic(ptr[0..len]);
17}
18
19// ABI warning
20const TranslateMode = extern enum {
21 import,
22 translate,
23};
24
25// ABI warning
26const Error = extern enum {
27 None,
28 OutOfMemory,
29 InvalidFormat,
30 SemanticAnalyzeFail,
31 AccessDenied,
32 Interrupted,
33 SystemResources,
34 FileNotFound,
35 FileSystem,
36 FileTooBig,
37 DivByZero,
38 Overflow,
39 PathAlreadyExists,
40 Unexpected,
41 ExactDivRemainder,
42 NegativeDenominator,
43 ShiftedOutOneBits,
44 CCompileErrors,
45 EndOfFile,
46 IsDir,
47 NotDir,
48 UnsupportedOperatingSystem,
49 SharingViolation,
50 PipeBusy,
51 PrimitiveTypeNotFound,
52 CacheUnavailable,
53 PathTooLong,
54 CCompilerCannotFindFile,
55 ReadingDepFile,
56 InvalidDepFile,
57 MissingArchitecture,
58 MissingOperatingSystem,
59 UnknownArchitecture,
60 UnknownOperatingSystem,
61 UnknownABI,
62 InvalidFilename,
63 DiskQuota,
64 DiskSpace,
65 UnexpectedWriteFailure,
66 UnexpectedSeekFailure,
67 UnexpectedFileTruncationFailure,
68 Unimplemented,
69 OperationAborted,
70 BrokenPipe,
71 NoSpaceLeft,
72};
73
74const FILE = std.c.FILE;
75const ast = std.zig.ast;
76const translate_c = @import("translate_c.zig");
77
78/// Args should have a null terminating last arg.
79export fn stage2_translate_c(
80 out_ast: **ast.Tree,
81 out_errors_ptr: *[*]translate_c.ClangErrMsg,
82 out_errors_len: *usize,
83 args_begin: [*]?[*]const u8,
84 args_end: [*]?[*]const u8,
85 mode: TranslateMode,
86 resources_path: [*]const u8,
87) Error {
88 var errors: []translate_c.ClangErrMsg = undefined;
89 out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, switch (mode) {
90 .import => translate_c.Mode.import,
91 .translate => translate_c.Mode.translate,
92 }, &errors, resources_path) catch |err| switch (err) {
93 // TODO after https://github.com/ziglang/zig/issues/769 we can remove error.UnsupportedType
94 error.SemanticAnalyzeFail, error.UnsupportedType => {
95 out_errors_ptr.* = errors.ptr;
96 out_errors_len.* = errors.len;
97 return Error.CCompileErrors;
98 },
99 error.OutOfMemory => return Error.OutOfMemory,
100 };
101 return Error.None;
102}
103
104export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void {
105 translate_c.freeErrors(errors_ptr[0..errors_len]);
106}
107
108export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
109 const c_out_stream = &std.io.COutStream.init(output_file).stream;
110 _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {
111 error.SystemResources => return Error.SystemResources,
112 error.OperationAborted => return Error.OperationAborted,
113 error.BrokenPipe => return Error.BrokenPipe,
114 error.DiskQuota => return Error.DiskQuota,
115 error.FileTooBig => return Error.FileTooBig,
116 error.NoSpaceLeft => return Error.NoSpaceLeft,
117 error.AccessDenied => return Error.AccessDenied,
118 error.OutOfMemory => return Error.OutOfMemory,
119 error.Unexpected => return Error.Unexpected,
120 error.InputOutput => return Error.FileSystem,
121 };
122 return Error.None;
123}
124
125// TODO: just use the actual self-hosted zig fmt. Until the coroutine rewrite, we use a blocking implementation.
126export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int {
127 if (std.debug.runtime_safety) {
128 fmtMain(argc, argv) catch unreachable;
129 } else {
130 fmtMain(argc, argv) catch |e| {
131 std.debug.warn("{}\n", @errorName(e));
132 return -1;
133 };
134 }
135 return 0;
136}
137
138fn fmtMain(argc: c_int, argv: [*]const [*]const u8) !void {
139 const allocator = std.heap.c_allocator;
140 var args_list = std.ArrayList([]const u8).init(allocator);
141 const argc_usize = @intCast(usize, argc);
142 var arg_i: usize = 0;
143 while (arg_i < argc_usize) : (arg_i += 1) {
144 try args_list.append(std.mem.toSliceConst(u8, argv[arg_i]));
145 }
146
147 var stdout_file = try std.io.getStdOut();
148 var stdout_out_stream = stdout_file.outStream();
149 stdout = &stdout_out_stream.stream;
150
151 stderr_file = try std.io.getStdErr();
152 var stderr_out_stream = stderr_file.outStream();
153 stderr = &stderr_out_stream.stream;
154
155 const args = args_list.toSliceConst();
156 var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args[2..]);
157 defer flags.deinit();
158
159 if (flags.present("help")) {
160 try stdout.write(self_hosted_main.usage_fmt);
161 os.exit(0);
162 }
163
164 const color = blk: {
165 if (flags.single("color")) |color_flag| {
166 if (mem.eql(u8, color_flag, "auto")) {
167 break :blk errmsg.Color.Auto;
168 } else if (mem.eql(u8, color_flag, "on")) {
169 break :blk errmsg.Color.On;
170 } else if (mem.eql(u8, color_flag, "off")) {
171 break :blk errmsg.Color.Off;
172 } else unreachable;
173 } else {
174 break :blk errmsg.Color.Auto;
175 }
176 };
177
178 if (flags.present("stdin")) {
179 if (flags.positionals.len != 0) {
180 try stderr.write("cannot use --stdin with positional arguments\n");
181 os.exit(1);
182 }
183
184 var stdin_file = try io.getStdIn();
185 var stdin = stdin_file.inStream();
186
187 const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
188 defer allocator.free(source_code);
189
190 const tree = std.zig.parse(allocator, source_code) catch |err| {
191 try stderr.print("error parsing stdin: {}\n", err);
192 os.exit(1);
193 };
194 defer tree.deinit();
195
196 var error_it = tree.errors.iterator(0);
197 while (error_it.next()) |parse_error| {
198 try printErrMsgToFile(allocator, parse_error, tree, "<stdin>", stderr_file, color);
199 }
200 if (tree.errors.len != 0) {
201 os.exit(1);
202 }
203 if (flags.present("check")) {
204 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
205 const code = if (anything_changed) u8(1) else u8(0);
206 os.exit(code);
207 }
208
209 _ = try std.zig.render(allocator, stdout, tree);
210 return;
211 }
212
213 if (flags.positionals.len == 0) {
214 try stderr.write("expected at least one source file argument\n");
215 os.exit(1);
216 }
217
218 var fmt = Fmt{
219 .seen = Fmt.SeenMap.init(allocator),
220 .any_error = false,
221 .color = color,
222 .allocator = allocator,
223 };
224
225 const check_mode = flags.present("check");
226
227 for (flags.positionals.toSliceConst()) |file_path| {
228 try fmtPath(&fmt, file_path, check_mode);
229 }
230 if (fmt.any_error) {
231 os.exit(1);
232 }
233}
234
235const FmtError = error{
236 SystemResources,
237 OperationAborted,
238 IoPending,
239 BrokenPipe,
240 Unexpected,
241 WouldBlock,
242 FileClosed,
243 DestinationAddressRequired,
244 DiskQuota,
245 FileTooBig,
246 InputOutput,
247 NoSpaceLeft,
248 AccessDenied,
249 OutOfMemory,
250 RenameAcrossMountPoints,
251 ReadOnlyFileSystem,
252 LinkQuotaExceeded,
253 FileBusy,
254} || os.File.OpenError;
255
256fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
257 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
258 defer fmt.allocator.free(file_path);
259
260 if (try fmt.seen.put(file_path, {})) |_| return;
261
262 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
263 error.IsDir, error.AccessDenied => {
264 // TODO make event based (and dir.next())
265 var dir = try std.os.Dir.open(fmt.allocator, file_path);
266 defer dir.close();
267
268 while (try dir.next()) |entry| {
269 if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
270 const full_path = try os.path.join(fmt.allocator, [][]const u8{ file_path, entry.name });
271 try fmtPath(fmt, full_path, check_mode);
272 }
273 }
274 return;
275 },
276 else => {
277 // TODO lock stderr printing
278 try stderr.print("unable to open '{}': {}\n", file_path, err);
279 fmt.any_error = true;
280 return;
281 },
282 };
283 defer fmt.allocator.free(source_code);
284
285 const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
286 try stderr.print("error parsing file '{}': {}\n", file_path, err);
287 fmt.any_error = true;
288 return;
289 };
290 defer tree.deinit();
291
292 var error_it = tree.errors.iterator(0);
293 while (error_it.next()) |parse_error| {
294 try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color);
295 }
296 if (tree.errors.len != 0) {
297 fmt.any_error = true;
298 return;
299 }
300
301 if (check_mode) {
302 const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree);
303 if (anything_changed) {
304 try stderr.print("{}\n", file_path);
305 fmt.any_error = true;
306 }
307 } else {
308 const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
309 defer baf.destroy();
310
311 const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree);
312 if (anything_changed) {
313 try stderr.print("{}\n", file_path);
314 try baf.finish();
315 }
316 }
317}
318
319const Fmt = struct {
320 seen: SeenMap,
321 any_error: bool,
322 color: errmsg.Color,
323 allocator: *mem.Allocator,
324
325 const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
326};
327
328fn printErrMsgToFile(
329 allocator: *mem.Allocator,
330 parse_error: *const ast.Error,
331 tree: *ast.Tree,
332 path: []const u8,
333 file: os.File,
334 color: errmsg.Color,
335) !void {
336 const color_on = switch (color) {
337 errmsg.Color.Auto => file.isTty(),
338 errmsg.Color.On => true,
339 errmsg.Color.Off => false,
340 };
341 const lok_token = parse_error.loc();
342 const span = errmsg.Span{
343 .first = lok_token,
344 .last = lok_token,
345 };
346
347 const first_token = tree.tokens.at(span.first);
348 const last_token = tree.tokens.at(span.last);
349 const start_loc = tree.tokenLocationPtr(0, first_token);
350 const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
351
352 var text_buf = try std.Buffer.initSize(allocator, 0);
353 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
354 try parse_error.render(&tree.tokens, out_stream);
355 const text = text_buf.toOwnedSlice();
356
357 const stream = &file.outStream().stream;
358 if (!color_on) {
359 try stream.print(
360 "{}:{}:{}: error: {}\n",
361 path,
362 start_loc.line + 1,
363 start_loc.column + 1,
364 text,
365 );
366 return;
367 }
368
369 try stream.print(
370 "{}:{}:{}: error: {}\n{}\n",
371 path,
372 start_loc.line + 1,
373 start_loc.column + 1,
374 text,
375 tree.source[start_loc.line_start..start_loc.line_end],
376 );
377 try stream.writeByteNTimes(' ', start_loc.column);
378 try stream.writeByteNTimes('~', last_token.end - first_token.start);
379 try stream.write("\n");
380}
381
382const os = std.os;
383const io = std.io;
384const mem = std.mem;
385const Allocator = mem.Allocator;
386const ArrayList = std.ArrayList;
387const Buffer = std.Buffer;
388
389const arg = @import("arg.zig");
390const self_hosted_main = @import("main.zig");
391const Args = arg.Args;
392const Flag = arg.Flag;
393const errmsg = @import("errmsg.zig");
394
395var stderr_file: os.File = undefined;
396var stderr: *io.OutStream(os.File.WriteError) = undefined;
397var stdout: *io.OutStream(os.File.WriteError) = undefined;
src-self-hosted/translate_c.zig created+682
...@@ -0,0 +1,682 @@
1// This is the userland implementation of translate-c which will be used by both stage1
2// and stage2. Currently the only way it is used is with `zig translate-c-2`.
3
4const std = @import("std");
5const builtin = @import("builtin");
6const assert = std.debug.assert;
7const ast = std.zig.ast;
8const Token = std.zig.Token;
9use @import("clang.zig");
10
11pub const Mode = enum {
12 import,
13 translate,
14};
15
16// TODO merge with Type.Fn.CallingConvention
17const CallingConvention = builtin.TypeInfo.CallingConvention;
18
19pub const ClangErrMsg = Stage2ErrorMsg;
20
21pub const Error = error{
22 OutOfMemory,
23 UnsupportedType,
24};
25pub const TransError = error{
26 OutOfMemory,
27 UnsupportedTranslation,
28};
29
30const DeclTable = std.HashMap(usize, void, addrHash, addrEql);
31
32fn addrHash(x: usize) u32 {
33 switch (@typeInfo(usize).Int.bits) {
34 32 => return x,
35 // pointers are usually aligned so we ignore the bits that are probably all 0 anyway
36 // usually the larger bits of addr space are unused so we just chop em off
37 64 => return @truncate(u32, x >> 4),
38 else => @compileError("unreachable"),
39 }
40}
41
42fn addrEql(a: usize, b: usize) bool {
43 return a == b;
44}
45
46const Scope = struct {
47 id: Id,
48 parent: ?*Scope,
49
50 const Id = enum {
51 Switch,
52 Var,
53 Block,
54 Root,
55 While,
56 };
57 const Switch = struct {
58 base: Scope,
59 };
60
61 const Var = struct {
62 base: Scope,
63 c_name: []const u8,
64 zig_name: []const u8,
65 };
66
67 const Block = struct {
68 base: Scope,
69 block_node: *ast.Node.Block,
70
71 /// Don't forget to set rbrace token later
72 fn create(c: *Context, parent: *Scope, lbrace_tok: ast.TokenIndex) !*Block {
73 const block = try c.a().create(Block);
74 block.* = Block{
75 .base = Scope{
76 .id = Id.Block,
77 .parent = parent,
78 },
79 .block_node = try c.a().create(ast.Node.Block),
80 };
81 block.block_node.* = ast.Node.Block{
82 .base = ast.Node{ .id = ast.Node.Id.Block },
83 .label = null,
84 .lbrace = lbrace_tok,
85 .statements = ast.Node.Block.StatementList.init(c.a()),
86 .rbrace = undefined,
87 };
88 return block;
89 }
90 };
91
92 const Root = struct {
93 base: Scope,
94 };
95
96 const While = struct {
97 base: Scope,
98 };
99};
100
101const TransResult = struct {
102 node: *ast.Node,
103 node_scope: *Scope,
104 child_scope: *Scope,
105};
106
107const Context = struct {
108 tree: *ast.Tree,
109 source_buffer: *std.Buffer,
110 err: Error,
111 source_manager: *ZigClangSourceManager,
112 decl_table: DeclTable,
113 global_scope: *Scope.Root,
114 mode: Mode,
115
116 fn a(c: *Context) *std.mem.Allocator {
117 return &c.tree.arena_allocator.allocator;
118 }
119
120 /// Convert a null-terminated C string to a slice allocated in the arena
121 fn str(c: *Context, s: [*]const u8) ![]u8 {
122 return std.mem.dupe(c.a(), u8, std.mem.toSliceConst(u8, s));
123 }
124
125 /// Convert a clang source location to a file:line:column string
126 fn locStr(c: *Context, loc: ZigClangSourceLocation) ![]u8 {
127 const spelling_loc = ZigClangSourceManager_getSpellingLoc(c.source_manager, loc);
128 const filename_c = ZigClangSourceManager_getFilename(c.source_manager, spelling_loc);
129 const filename = if (filename_c) |s| try c.str(s) else ([]const u8)("(no file)");
130
131 const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc);
132 const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc);
133 return std.fmt.allocPrint(c.a(), "{}:{}:{}", filename, line, column);
134 }
135};
136
137pub fn translate(
138 backing_allocator: *std.mem.Allocator,
139 args_begin: [*]?[*]const u8,
140 args_end: [*]?[*]const u8,
141 mode: Mode,
142 errors: *[]ClangErrMsg,
143 resources_path: [*]const u8,
144) !*ast.Tree {
145 const ast_unit = ZigClangLoadFromCommandLine(
146 args_begin,
147 args_end,
148 &errors.ptr,
149 &errors.len,
150 resources_path,
151 ) orelse {
152 if (errors.len == 0) return error.OutOfMemory;
153 return error.SemanticAnalyzeFail;
154 };
155 defer ZigClangASTUnit_delete(ast_unit);
156
157 var tree_arena = std.heap.ArenaAllocator.init(backing_allocator);
158 errdefer tree_arena.deinit();
159 var arena = &tree_arena.allocator;
160
161 const root_node = try arena.create(ast.Node.Root);
162 root_node.* = ast.Node.Root{
163 .base = ast.Node{ .id = ast.Node.Id.Root },
164 .decls = ast.Node.Root.DeclList.init(arena),
165 .doc_comments = null,
166 // initialized with the eof token at the end
167 .eof_token = undefined,
168 };
169
170 const tree = try arena.create(ast.Tree);
171 tree.* = ast.Tree{
172 .source = undefined, // need to use Buffer.toOwnedSlice later
173 .root_node = root_node,
174 .arena_allocator = undefined,
175 .tokens = ast.Tree.TokenList.init(arena),
176 .errors = ast.Tree.ErrorList.init(arena),
177 };
178 tree.arena_allocator = tree_arena;
179 arena = &tree.arena_allocator.allocator;
180
181 var source_buffer = try std.Buffer.initSize(arena, 0);
182
183 var context = Context{
184 .tree = tree,
185 .source_buffer = &source_buffer,
186 .source_manager = ZigClangASTUnit_getSourceManager(ast_unit),
187 .err = undefined,
188 .decl_table = DeclTable.init(arena),
189 .global_scope = try arena.create(Scope.Root),
190 .mode = mode,
191 };
192 context.global_scope.* = Scope.Root{
193 .base = Scope{
194 .id = Scope.Id.Root,
195 .parent = null,
196 },
197 };
198
199 if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) {
200 return context.err;
201 }
202
203 _ = try appendToken(&context, .Eof, "");
204 tree.source = source_buffer.toOwnedSlice();
205 if (false) {
206 std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source);
207 var i: usize = 0;
208 while (i < tree.tokens.len) : (i += 1) {
209 const token = tree.tokens.at(i);
210 std.debug.warn("{}\n", token);
211 }
212 }
213 return tree;
214}
215
216extern fn declVisitorC(context: ?*c_void, decl: *const ZigClangDecl) bool {
217 const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
218 declVisitor(c, decl) catch |err| {
219 c.err = err;
220 return false;
221 };
222 return true;
223}
224
225fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
226 switch (ZigClangDecl_getKind(decl)) {
227 .Function => {
228 return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
229 },
230 .Typedef => {
231 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs");
232 },
233 .Enum => {
234 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums");
235 },
236 .Record => {
237 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs");
238 },
239 .Var => {
240 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for variables");
241 },
242 else => {
243 const decl_name = try c.str(ZigClangDecl_getDeclKindName(decl));
244 try emitWarning(c, ZigClangDecl_getLocation(decl), "ignoring {} declaration", decl_name);
245 },
246 }
247}
248
249fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
250 if (try c.decl_table.put(@ptrToInt(fn_decl), {})) |_| return; // Avoid processing this decl twice
251 const rp = makeRestorePoint(c);
252 const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));
253 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
254 const fn_qt = ZigClangFunctionDecl_getType(fn_decl);
255 const fn_type = ZigClangQualType_getTypePtr(fn_qt);
256 var scope = &c.global_scope.base;
257 const has_body = ZigClangFunctionDecl_hasBody(fn_decl);
258 const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl);
259 const decl_ctx = FnDeclContext{
260 .fn_name = fn_name,
261 .has_body = has_body,
262 .storage_class = storage_class,
263 .scope = &scope,
264 .is_export = switch (storage_class) {
265 .None => has_body,
266 .Extern, .Static => false,
267 .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern"),
268 .Auto => unreachable, // Not legal on functions
269 .Register => unreachable, // Not legal on functions
270 },
271 };
272 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
273 .FunctionProto => blk: {
274 const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);
275 break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
276 error.UnsupportedType => {
277 return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
278 },
279 error.OutOfMemory => return error.OutOfMemory,
280 };
281 },
282 .FunctionNoProto => blk: {
283 const fn_no_proto_type = @ptrCast(*const ZigClangFunctionType, fn_type);
284 break :blk transFnNoProto(rp, fn_no_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
285 error.UnsupportedType => {
286 return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
287 },
288 error.OutOfMemory => return error.OutOfMemory,
289 };
290 },
291 else => unreachable,
292 };
293
294 if (!decl_ctx.has_body) {
295 const semi_tok = try appendToken(c, .Semicolon, ";");
296 return addTopLevelDecl(c, fn_name, &proto_node.base);
297 }
298
299 // actual function definition with body
300 const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
301 const result = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) {
302 error.OutOfMemory => return error.OutOfMemory,
303 error.UnsupportedTranslation => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"),
304 };
305 assert(result.node.id == ast.Node.Id.Block);
306 proto_node.body_node = result.node;
307
308 return addTopLevelDecl(c, fn_name, &proto_node.base);
309}
310
311const ResultUsed = enum {
312 used,
313 unused,
314};
315
316const LRValue = enum {
317 l_value,
318 r_value,
319};
320
321fn transStmt(
322 rp: RestorePoint,
323 scope: *Scope,
324 stmt: *const ZigClangStmt,
325 result_used: ResultUsed,
326 lrvalue: LRValue,
327) !TransResult {
328 const sc = ZigClangStmt_getStmtClass(stmt);
329 switch (sc) {
330 .CompoundStmtClass => return transCompoundStmt(rp, scope, @ptrCast(*const ZigClangCompoundStmt, stmt)),
331 else => {
332 return revertAndWarn(
333 rp,
334 error.UnsupportedTranslation,
335 ZigClangStmt_getBeginLoc(stmt),
336 "TODO implement translation of stmt class {}",
337 @tagName(sc),
338 );
339 },
340 }
341}
342
343fn transCompoundStmtInline(
344 rp: RestorePoint,
345 parent_scope: *Scope,
346 stmt: *const ZigClangCompoundStmt,
347 block_node: *ast.Node.Block,
348) TransError!TransResult {
349 var it = ZigClangCompoundStmt_body_begin(stmt);
350 const end_it = ZigClangCompoundStmt_body_end(stmt);
351 var scope = parent_scope;
352 while (it != end_it) : (it += 1) {
353 const result = try transStmt(rp, scope, it.*, .unused, .r_value);
354 scope = result.child_scope;
355 try block_node.statements.push(result.node);
356 }
357 return TransResult{
358 .node = &block_node.base,
359 .child_scope = scope,
360 .node_scope = scope,
361 };
362}
363
364fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) !TransResult {
365 const lbrace_tok = try appendToken(rp.c, .LBrace, "{");
366 const block_scope = try Scope.Block.create(rp.c, scope, lbrace_tok);
367 const inline_result = try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node);
368 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
369 return TransResult{
370 .node = &block_scope.block_node.base,
371 .node_scope = inline_result.node_scope,
372 .child_scope = inline_result.child_scope,
373 };
374}
375
376fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void {
377 try c.tree.root_node.decls.push(decl_node);
378}
379
380fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) Error!*ast.Node {
381 return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
382}
383
384fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType {
385 const canon = ZigClangQualType_getCanonicalType(qt);
386 return ZigClangQualType_getTypePtr(canon);
387}
388
389const RestorePoint = struct {
390 c: *Context,
391 token_index: ast.TokenIndex,
392 src_buf_index: usize,
393
394 fn activate(self: RestorePoint) void {
395 self.c.tree.tokens.shrink(self.token_index);
396 self.c.source_buffer.shrink(self.src_buf_index);
397 }
398};
399
400fn makeRestorePoint(c: *Context) RestorePoint {
401 return RestorePoint{
402 .c = c,
403 .token_index = c.tree.tokens.len,
404 .src_buf_index = c.source_buffer.len(),
405 };
406}
407
408fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSourceLocation) Error!*ast.Node {
409 switch (ZigClangType_getTypeClass(ty)) {
410 .Builtin => {
411 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
412 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
413 .Void => return appendIdentifier(rp.c, "c_void"),
414 .Bool => return appendIdentifier(rp.c, "bool"),
415 .Char_U, .UChar, .Char_S, .Char8 => return appendIdentifier(rp.c, "u8"),
416 .SChar => return appendIdentifier(rp.c, "i8"),
417 .UShort => return appendIdentifier(rp.c, "c_ushort"),
418 .UInt => return appendIdentifier(rp.c, "c_uint"),
419 .ULong => return appendIdentifier(rp.c, "c_ulong"),
420 .ULongLong => return appendIdentifier(rp.c, "c_ulonglong"),
421 .Short => return appendIdentifier(rp.c, "c_short"),
422 .Int => return appendIdentifier(rp.c, "c_int"),
423 .Long => return appendIdentifier(rp.c, "c_long"),
424 .LongLong => return appendIdentifier(rp.c, "c_longlong"),
425 .UInt128 => return appendIdentifier(rp.c, "u128"),
426 .Int128 => return appendIdentifier(rp.c, "i128"),
427 .Float => return appendIdentifier(rp.c, "f32"),
428 .Double => return appendIdentifier(rp.c, "f64"),
429 .Float128 => return appendIdentifier(rp.c, "f128"),
430 .Float16 => return appendIdentifier(rp.c, "f16"),
431 .LongDouble => return appendIdentifier(rp.c, "c_longdouble"),
432 else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type"),
433 }
434 },
435 .FunctionProto => {
436 const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
437 const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null);
438 return &fn_proto.base;
439 },
440 else => {
441 const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
442 return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", type_name);
443 },
444 }
445}
446
447const FnDeclContext = struct {
448 fn_name: []const u8,
449 has_body: bool,
450 storage_class: ZigClangStorageClass,
451 scope: **Scope,
452 is_export: bool,
453};
454
455fn transCC(
456 rp: RestorePoint,
457 fn_ty: *const ZigClangFunctionType,
458 source_loc: ZigClangSourceLocation,
459) !CallingConvention {
460 const clang_cc = ZigClangFunctionType_getCallConv(fn_ty);
461 switch (clang_cc) {
462 .C => return CallingConvention.C,
463 .X86StdCall => return CallingConvention.Stdcall,
464 else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: {}", @tagName(clang_cc)),
465 }
466}
467
468fn transFnProto(
469 rp: RestorePoint,
470 fn_proto_ty: *const ZigClangFunctionProtoType,
471 source_loc: ZigClangSourceLocation,
472 fn_decl_context: ?FnDeclContext,
473) !*ast.Node.FnProto {
474 const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);
475 const cc = try transCC(rp, fn_ty, source_loc);
476 const is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty);
477 const param_count: usize = ZigClangFunctionProtoType_getNumParams(fn_proto_ty);
478 var i: usize = 0;
479 while (i < param_count) : (i += 1) {
480 return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO: implement parameters for FunctionProto in transType");
481 }
482
483 return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
484}
485
486fn transFnNoProto(
487 rp: RestorePoint,
488 fn_ty: *const ZigClangFunctionType,
489 source_loc: ZigClangSourceLocation,
490 fn_decl_context: ?FnDeclContext,
491) !*ast.Node.FnProto {
492 const cc = try transCC(rp, fn_ty, source_loc);
493 const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true;
494 return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
495}
496
497fn finishTransFnProto(
498 rp: RestorePoint,
499 fn_ty: *const ZigClangFunctionType,
500 source_loc: ZigClangSourceLocation,
501 fn_decl_context: ?FnDeclContext,
502 is_var_args: bool,
503 cc: CallingConvention,
504) !*ast.Node.FnProto {
505 const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
506
507 // TODO check for always_inline attribute
508 // TODO check for align attribute
509
510 // pub extern fn name(...) T
511 const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub");
512 const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;
513 const extern_export_inline_tok = if (is_export)
514 try appendToken(rp.c, .Keyword_export, "export")
515 else if (cc == .C)
516 try appendToken(rp.c, .Keyword_extern, "extern")
517 else
518 null;
519 const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn");
520 const name_tok = if (fn_decl_context) |ctx| try appendToken(rp.c, .Identifier, ctx.fn_name) else null;
521 const lparen_tok = try appendToken(rp.c, .LParen, "(");
522 const var_args_tok = if (is_var_args) try appendToken(rp.c, .Ellipsis3, "...") else null;
523 const rparen_tok = try appendToken(rp.c, .RParen, ")");
524
525 const return_type_node = blk: {
526 if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) {
527 break :blk try appendIdentifier(rp.c, "noreturn");
528 } else {
529 const return_qt = ZigClangFunctionType_getReturnType(fn_ty);
530 if (ZigClangType_isVoidType(qualTypeCanon(return_qt))) {
531 break :blk try appendIdentifier(rp.c, "void");
532 } else {
533 break :blk transQualType(rp, return_qt, source_loc) catch |err| switch (err) {
534 error.UnsupportedType => {
535 try emitWarning(rp.c, source_loc, "unsupported function proto return type");
536 return err;
537 },
538 error.OutOfMemory => return error.OutOfMemory,
539 };
540 }
541 }
542 };
543
544 const fn_proto = try rp.c.a().create(ast.Node.FnProto);
545 fn_proto.* = ast.Node.FnProto{
546 .base = ast.Node{ .id = ast.Node.Id.FnProto },
547 .doc_comments = null,
548 .visib_token = pub_tok,
549 .fn_token = fn_tok,
550 .name_token = name_tok,
551 .params = ast.Node.FnProto.ParamList.init(rp.c.a()),
552 .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node },
553 .var_args_token = null, // TODO this field is broken in the AST data model
554 .extern_export_inline_token = extern_export_inline_tok,
555 .cc_token = cc_tok,
556 .async_attr = null,
557 .body_node = null,
558 .lib_name = null,
559 .align_expr = null,
560 .section_expr = null,
561 };
562 if (is_var_args) {
563 const var_arg_node = try rp.c.a().create(ast.Node.ParamDecl);
564 var_arg_node.* = ast.Node.ParamDecl{
565 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
566 .doc_comments = null,
567 .comptime_token = null,
568 .noalias_token = null,
569 .name_token = null,
570 .type_node = undefined,
571 .var_args_token = var_args_tok,
572 };
573 try fn_proto.params.push(&var_arg_node.base);
574 }
575 return fn_proto;
576}
577
578fn revertAndWarn(
579 rp: RestorePoint,
580 err: var,
581 source_loc: ZigClangSourceLocation,
582 comptime format: []const u8,
583 args: ...,
584) (@typeOf(err) || error{OutOfMemory}) {
585 rp.activate();
586 try emitWarning(rp.c, source_loc, format, args);
587 return err;
588}
589
590fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []const u8, args: ...) !void {
591 _ = try appendTokenFmt(c, .LineComment, "// {}: warning: " ++ format, c.locStr(loc), args);
592}
593
594fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: ...) !void {
595 // const name = @compileError(msg);
596 const const_tok = try appendToken(c, .Keyword_const, "const");
597 const name_tok = try appendToken(c, .Identifier, name);
598 const eq_tok = try appendToken(c, .Equal, "=");
599 const builtin_tok = try appendToken(c, .Builtin, "@compileError");
600 const lparen_tok = try appendToken(c, .LParen, "(");
601 const msg_tok = try appendTokenFmt(c, .StringLiteral, "\"" ++ format ++ "\"", args);
602 const rparen_tok = try appendToken(c, .RParen, ")");
603 const semi_tok = try appendToken(c, .Semicolon, ";");
604
605 const msg_node = try c.a().create(ast.Node.StringLiteral);
606 msg_node.* = ast.Node.StringLiteral{
607 .base = ast.Node{ .id = ast.Node.Id.StringLiteral },
608 .token = msg_tok,
609 };
610
611 const call_node = try c.a().create(ast.Node.BuiltinCall);
612 call_node.* = ast.Node.BuiltinCall{
613 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
614 .builtin_token = builtin_tok,
615 .params = ast.Node.BuiltinCall.ParamList.init(c.a()),
616 .rparen_token = rparen_tok,
617 };
618 try call_node.params.push(&msg_node.base);
619
620 const var_decl_node = try c.a().create(ast.Node.VarDecl);
621 var_decl_node.* = ast.Node.VarDecl{
622 .base = ast.Node{ .id = ast.Node.Id.VarDecl },
623 .doc_comments = null,
624 .visib_token = null,
625 .thread_local_token = null,
626 .name_token = name_tok,
627 .eq_token = eq_tok,
628 .mut_token = const_tok,
629 .comptime_token = null,
630 .extern_export_token = null,
631 .lib_name = null,
632 .type_node = null,
633 .align_node = null,
634 .section_node = null,
635 .init_node = &call_node.base,
636 .semicolon_token = semi_tok,
637 };
638 try c.tree.root_node.decls.push(&var_decl_node.base);
639}
640
641fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex {
642 return appendTokenFmt(c, token_id, "{}", bytes);
643}
644
645fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !ast.TokenIndex {
646 const S = struct {
647 fn callback(context: *Context, bytes: []const u8) error{OutOfMemory}!void {
648 return context.source_buffer.append(bytes);
649 }
650 };
651 const start_index = c.source_buffer.len();
652 errdefer c.source_buffer.shrink(start_index);
653
654 try std.fmt.format(c, error{OutOfMemory}, S.callback, format, args);
655 const end_index = c.source_buffer.len();
656 const token_index = c.tree.tokens.len;
657 const new_token = try c.tree.tokens.addOne();
658 errdefer c.tree.tokens.shrink(token_index);
659
660 new_token.* = Token{
661 .id = token_id,
662 .start = start_index,
663 .end = end_index,
664 };
665 try c.source_buffer.appendByte('\n');
666
667 return token_index;
668}
669
670fn appendIdentifier(c: *Context, name: []const u8) !*ast.Node {
671 const token_index = try appendToken(c, .Identifier, name);
672 const identifier = try c.a().create(ast.Node.Identifier);
673 identifier.* = ast.Node.Identifier{
674 .base = ast.Node{ .id = ast.Node.Id.Identifier },
675 .token = token_index,
676 };
677 return &identifier.base;
678}
679
680pub fn freeErrors(errors: []ClangErrMsg) void {
681 ZigClangErrorMsg_delete(errors.ptr, errors.len);
682}
src-self-hosted/value.zig+4-4
...@@ -538,21 +538,21 @@ pub const Value = struct {...@@ -538,21 +538,21 @@ pub const Value = struct {
538 switch (self.base.typ.id) {538 switch (self.base.typ.id) {
539 Type.Id.Int => {539 Type.Id.Int => {
540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
541 if (self.big_int.len == 0) {541 if (self.big_int.len() == 0) {
542 return llvm.ConstNull(type_ref);542 return llvm.ConstNull(type_ref);
543 }543 }
544 const unsigned_val = if (self.big_int.len == 1) blk: {544 const unsigned_val = if (self.big_int.len() == 1) blk: {
545 break :blk llvm.ConstInt(type_ref, self.big_int.limbs[0], @boolToInt(false));545 break :blk llvm.ConstInt(type_ref, self.big_int.limbs[0], @boolToInt(false));
546 } else if (@sizeOf(std.math.big.Limb) == @sizeOf(u64)) blk: {546 } else if (@sizeOf(std.math.big.Limb) == @sizeOf(u64)) blk: {
547 break :blk llvm.ConstIntOfArbitraryPrecision(547 break :blk llvm.ConstIntOfArbitraryPrecision(
548 type_ref,548 type_ref,
549 @intCast(c_uint, self.big_int.len),549 @intCast(c_uint, self.big_int.len()),
550 @ptrCast([*]u64, self.big_int.limbs.ptr),550 @ptrCast([*]u64, self.big_int.limbs.ptr),
551 );551 );
552 } else {552 } else {
553 @compileError("std.math.Big.Int.Limb size does not match LLVM");553 @compileError("std.math.Big.Int.Limb size does not match LLVM");
554 };554 };
555 return if (self.big_int.positive) unsigned_val else llvm.ConstNeg(unsigned_val);555 return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val);
556 },556 },
557 Type.Id.ComptimeInt => unreachable,557 Type.Id.ComptimeInt => unreachable,
558 else => unreachable,558 else => unreachable,
src/all_types.hpp+12-1
...@@ -55,7 +55,7 @@ struct IrExecutable {...@@ -55,7 +55,7 @@ struct IrExecutable {
55 size_t mem_slot_count;55 size_t mem_slot_count;
56 size_t next_debug_id;56 size_t next_debug_id;
57 size_t *backward_branch_count;57 size_t *backward_branch_count;
58 size_t backward_branch_quota;58 size_t *backward_branch_quota;
59 ZigFn *fn_entry;59 ZigFn *fn_entry;
60 Buf *c_import_buf;60 Buf *c_import_buf;
61 AstNode *source_node;61 AstNode *source_node;
...@@ -1350,6 +1350,7 @@ struct ZigFn {...@@ -1350,6 +1350,7 @@ struct ZigFn {
1350 IrExecutable ir_executable;1350 IrExecutable ir_executable;
1351 IrExecutable analyzed_executable;1351 IrExecutable analyzed_executable;
1352 size_t prealloc_bbc;1352 size_t prealloc_bbc;
1353 size_t prealloc_backward_branch_quota;
1353 AstNode **param_source_nodes;1354 AstNode **param_source_nodes;
1354 Buf **param_names;1355 Buf **param_names;
13551356
...@@ -1855,10 +1856,13 @@ struct CodeGen {...@@ -1855,10 +1856,13 @@ struct CodeGen {
1855 bool strip_debug_symbols;1856 bool strip_debug_symbols;
1856 bool is_test_build;1857 bool is_test_build;
1857 bool is_single_threaded;1858 bool is_single_threaded;
1859 bool want_single_threaded;
1858 bool linker_rdynamic;1860 bool linker_rdynamic;
1859 bool each_lib_rpath;1861 bool each_lib_rpath;
1860 bool is_dummy_so;1862 bool is_dummy_so;
1861 bool disable_gen_h;1863 bool disable_gen_h;
1864 bool bundle_compiler_rt;
1865 bool disable_stack_probing;
18621866
1863 Buf *mmacosx_version_min;1867 Buf *mmacosx_version_min;
1864 Buf *mios_version_min;1868 Buf *mios_version_min;
...@@ -2291,6 +2295,7 @@ enum IrInstructionId {...@@ -2291,6 +2295,7 @@ enum IrInstructionId {
2291 IrInstructionIdVectorToArray,2295 IrInstructionIdVectorToArray,
2292 IrInstructionIdArrayToVector,2296 IrInstructionIdArrayToVector,
2293 IrInstructionIdAssertZero,2297 IrInstructionIdAssertZero,
2298 IrInstructionIdAssertNonNull,
2294};2299};
22952300
2296struct IrInstruction {2301struct IrInstruction {
...@@ -3480,6 +3485,12 @@ struct IrInstructionAssertZero {...@@ -3480,6 +3485,12 @@ struct IrInstructionAssertZero {
3480 IrInstruction *target;3485 IrInstruction *target;
3481};3486};
34823487
3488struct IrInstructionAssertNonNull {
3489 IrInstruction base;
3490
3491 IrInstruction *target;
3492};
3493
3483static const size_t slice_ptr_index = 0;3494static const size_t slice_ptr_index = 0;
3484static const size_t slice_len_index = 1;3495static const size_t slice_len_index = 1;
34853496
src/analyze.cpp+94-59
...@@ -969,8 +969,9 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no...@@ -969,8 +969,9 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no
969 Buf *type_name)969 Buf *type_name)
970{970{
971 size_t backward_branch_count = 0;971 size_t backward_branch_count = 0;
972 size_t backward_branch_quota = default_backward_branch_quota;
972 return ir_eval_const_value(g, scope, node, type_entry,973 return ir_eval_const_value(g, scope, node, type_entry,
973 &backward_branch_count, default_backward_branch_quota,974 &backward_branch_count, &backward_branch_quota,
974 nullptr, nullptr, node, type_name, nullptr, nullptr);975 nullptr, nullptr, node, type_name, nullptr, nullptr);
975}976}
976977
...@@ -1907,6 +1908,18 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {...@@ -1907,6 +1908,18 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
1907 return ErrorNone;1908 return ErrorNone;
1908}1909}
19091910
1911static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) {
1912 // Only integer types are allowed by the C ABI
1913 if(ty->id != ZigTypeIdInt)
1914 return false;
1915
1916 // According to the ANSI C standard the enumeration type should be either a
1917 // signed char, a signed integer or an unsigned one. But GCC/Clang allow
1918 // other integral types as a compiler extension so let's accomodate them
1919 // aswell.
1920 return type_allowed_in_extern(g, ty);
1921}
1922
1910static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {1923static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
1911 assert(enum_type->id == ZigTypeIdEnum);1924 assert(enum_type->id == ZigTypeIdEnum);
19121925
...@@ -1964,7 +1977,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -1964,7 +1977,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
1964 enum_type->abi_size = tag_int_type->abi_size;1977 enum_type->abi_size = tag_int_type->abi_size;
1965 enum_type->abi_align = tag_int_type->abi_align;1978 enum_type->abi_align = tag_int_type->abi_align;
19661979
1967 // TODO: Are extern enums allowed to have an init_arg_expr?
1968 if (decl_node->data.container_decl.init_arg_expr != nullptr) {1980 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
1969 ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);1981 ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
1970 if (type_is_invalid(wanted_tag_int_type)) {1982 if (type_is_invalid(wanted_tag_int_type)) {
...@@ -1973,24 +1985,29 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -1973,24 +1985,29 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
1973 enum_type->data.enumeration.is_invalid = true;1985 enum_type->data.enumeration.is_invalid = true;
1974 add_node_error(g, decl_node->data.container_decl.init_arg_expr,1986 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
1975 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));1987 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
1976 } else if (wanted_tag_int_type->data.integral.is_signed) {1988 } else if (enum_type->data.enumeration.layout == ContainerLayoutExtern &&
1977 enum_type->data.enumeration.is_invalid = true;1989 !type_is_valid_extern_enum_tag(g, wanted_tag_int_type)) {
1978 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
1979 buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
1980 } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) {
1981 enum_type->data.enumeration.is_invalid = true;1990 enum_type->data.enumeration.is_invalid = true;
1982 add_node_error(g, decl_node->data.container_decl.init_arg_expr,1991 ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr,
1983 buf_sprintf("'%s' too small to hold all bits; must be at least '%s'",1992 buf_sprintf("'%s' is not a valid tag type for an extern enum",
1984 buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name)));1993 buf_ptr(&wanted_tag_int_type->name)));
1994 add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr,
1995 buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid"));
1985 } else {1996 } else {
1986 tag_int_type = wanted_tag_int_type;1997 tag_int_type = wanted_tag_int_type;
1987 }1998 }
1988 }1999 }
2000
1989 enum_type->data.enumeration.tag_int_type = tag_int_type;2001 enum_type->data.enumeration.tag_int_type = tag_int_type;
1990 enum_type->size_in_bits = tag_int_type->size_in_bits;2002 enum_type->size_in_bits = tag_int_type->size_in_bits;
1991 enum_type->abi_size = tag_int_type->abi_size;2003 enum_type->abi_size = tag_int_type->abi_size;
1992 enum_type->abi_align = tag_int_type->abi_align;2004 enum_type->abi_align = tag_int_type->abi_align;
19932005
2006 BigInt bi_one;
2007 bigint_init_unsigned(&bi_one, 1);
2008
2009 TypeEnumField *last_enum_field = nullptr;
2010
1994 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {2011 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
1995 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);2012 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
1996 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];2013 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) {...@@ -2016,60 +2033,58 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
20162033
2017 AstNode *tag_value = field_node->data.struct_field.value;2034 AstNode *tag_value = field_node->data.struct_field.value;
20182035
2019 // In this first pass we resolve explicit tag values.
2020 // In a second pass we will fill in the unspecified ones.
2021 if (tag_value != nullptr) {2036 if (tag_value != nullptr) {
2037 // A user-specified value is available
2022 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);2038 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2023 if (type_is_invalid(result->type)) {2039 if (type_is_invalid(result->type)) {
2024 enum_type->data.enumeration.is_invalid = true;2040 enum_type->data.enumeration.is_invalid = true;
2025 continue;2041 continue;
2026 }2042 }
2043
2027 assert(result->special != ConstValSpecialRuntime);2044 assert(result->special != ConstValSpecialRuntime);
2028 assert(result->type->id == ZigTypeIdInt ||2045 assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt);
2029 result->type->id == ZigTypeIdComptimeInt);2046
2030 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);2047 bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
2031 if (entry == nullptr) {2048 } else {
2032 bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);2049 // No value was explicitly specified: allocate the last value + 1
2050 // or, if this is the first element, zero
2051 if (last_enum_field != nullptr) {
2052 bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one);
2033 } else {2053 } else {
2034 Buf *val_buf = buf_alloc();2054 bigint_init_unsigned(&type_enum_field->value, 0);
2035 bigint_append_buf(val_buf, &result->data.x_bigint, 10);2055 }
20362056
2037 ErrorMsg *msg = add_node_error(g, tag_value,2057 // Make sure we can represent this number with tag_int_type
2038 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));2058 if (!bigint_fits_in_bits(&type_enum_field->value,
2039 add_error_note(g, msg, entry->value,2059 tag_int_type->size_in_bits,
2040 buf_sprintf("other occurrence here"));2060 tag_int_type->data.integral.is_signed)) {
2041 enum_type->data.enumeration.is_invalid = true;2061 enum_type->data.enumeration.is_invalid = true;
2042 continue;2062
2063 Buf *val_buf = buf_alloc();
2064 bigint_append_buf(val_buf, &type_enum_field->value, 10);
2065 add_node_error(g, field_node,
2066 buf_sprintf("enumeration value %s too large for type '%s'",
2067 buf_ptr(val_buf), buf_ptr(&tag_int_type->name)));
2068
2069 break;
2043 }2070 }
2044 }2071 }
2045 }
20462072
2047 // Now iterate again and populate the unspecified tag values2073 // Make sure the value is unique
2048 uint32_t next_maybe_unoccupied_index = 0;2074 auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
2075 if (entry != nullptr) {
2076 enum_type->data.enumeration.is_invalid = true;
20492077
2050 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {2078 Buf *val_buf = buf_alloc();
2051 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);2079 bigint_append_buf(val_buf, &type_enum_field->value, 10);
2052 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
2053 AstNode *tag_value = field_node->data.struct_field.value;
20542080
2055 if (tag_value == nullptr) {2081 ErrorMsg *msg = add_node_error(g, field_node,
2056 if (occupied_tag_values.size() == 0) {2082 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
2057 bigint_init_unsigned(&type_enum_field->value, next_maybe_unoccupied_index);2083 add_error_note(g, msg, entry->value,
2058 next_maybe_unoccupied_index += 1;2084 buf_sprintf("other occurrence here"));
2059 } else {
2060 BigInt proposed_value;
2061 for (;;) {
2062 bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index);
2063 next_maybe_unoccupied_index += 1;
2064 auto entry = occupied_tag_values.put_unique(proposed_value, field_node);
2065 if (entry != nullptr) {
2066 continue;
2067 }
2068 break;
2069 }
2070 bigint_init_bigint(&type_enum_field->value, &proposed_value);
2071 }
2072 }2085 }
2086
2087 last_enum_field = type_enum_field;
2073 }2088 }
20742089
2075 enum_type->data.enumeration.zero_bits_loop_flag = false;2090 enum_type->data.enumeration.zero_bits_loop_flag = false;
...@@ -2607,7 +2622,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2607,7 +2622,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2607 return ErrorNone;2622 return ErrorNone;
2608}2623}
26092624
2610static void get_fully_qualified_decl_name(Buf *buf, Tld *tld) {2625static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, bool is_test) {
2611 buf_resize(buf, 0);2626 buf_resize(buf, 0);
26122627
2613 Scope *scope = tld->parent_scope;2628 Scope *scope = tld->parent_scope;
...@@ -2617,15 +2632,23 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld) {...@@ -2617,15 +2632,23 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld) {
2617 ScopeDecls *decls_scope = reinterpret_cast<ScopeDecls *>(scope);2632 ScopeDecls *decls_scope = reinterpret_cast<ScopeDecls *>(scope);
2618 buf_append_buf(buf, &decls_scope->container_type->name);2633 buf_append_buf(buf, &decls_scope->container_type->name);
2619 if (buf_len(buf) != 0) buf_append_char(buf, NAMESPACE_SEP_CHAR);2634 if (buf_len(buf) != 0) buf_append_char(buf, NAMESPACE_SEP_CHAR);
2620 buf_append_buf(buf, tld->name);2635 if (is_test) {
2636 buf_append_str(buf, "test \"");
2637 buf_append_buf(buf, tld->name);
2638 buf_append_char(buf, '"');
2639 } else {
2640 buf_append_buf(buf, tld->name);
2641 }
2621}2642}
26222643
2623ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) {2644ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) {
2624 ZigFn *fn_entry = allocate<ZigFn>(1);2645 ZigFn *fn_entry = allocate<ZigFn>(1);
26252646
2647 fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota;
2648
2626 fn_entry->codegen = g;2649 fn_entry->codegen = g;
2627 fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc;2650 fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc;
2628 fn_entry->analyzed_executable.backward_branch_quota = default_backward_branch_quota;2651 fn_entry->analyzed_executable.backward_branch_quota = &fn_entry->prealloc_backward_branch_quota;
2629 fn_entry->analyzed_executable.fn_entry = fn_entry;2652 fn_entry->analyzed_executable.fn_entry = fn_entry;
2630 fn_entry->ir_executable.fn_entry = fn_entry;2653 fn_entry->ir_executable.fn_entry = fn_entry;
2631 fn_entry->fn_inline = inline_value;2654 fn_entry->fn_inline = inline_value;
...@@ -2726,7 +2749,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -2726,7 +2749,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
2726 if (fn_proto->is_export || is_extern) {2749 if (fn_proto->is_export || is_extern) {
2727 buf_init_from_buf(&fn_table_entry->symbol_name, tld_fn->base.name);2750 buf_init_from_buf(&fn_table_entry->symbol_name, tld_fn->base.name);
2728 } else {2751 } else {
2729 get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base);2752 get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, false);
2730 }2753 }
27312754
2732 if (fn_proto->is_export) {2755 if (fn_proto->is_export) {
...@@ -2787,7 +2810,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -2787,7 +2810,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
2787 } else if (source_node->type == NodeTypeTestDecl) {2810 } else if (source_node->type == NodeTypeTestDecl) {
2788 ZigFn *fn_table_entry = create_fn_raw(g, FnInlineAuto);2811 ZigFn *fn_table_entry = create_fn_raw(g, FnInlineAuto);
27892812
2790 get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base);2813 get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, true);
27912814
2792 tld_fn->fn_entry = fn_table_entry;2815 tld_fn->fn_entry = fn_table_entry;
27932816
...@@ -3722,7 +3745,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {...@@ -3722,7 +3745,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
3722 }3745 }
3723 if (g->verbose_ir) {3746 if (g->verbose_ir) {
3724 fprintf(stderr, "\n");3747 fprintf(stderr, "\n");
3725 ast_render(g, stderr, fn_table_entry->body_node, 4);3748 ast_render(stderr, fn_table_entry->body_node, 4);
3726 fprintf(stderr, "\n{ // (IR)\n");3749 fprintf(stderr, "\n{ // (IR)\n");
3727 ir_print(g, stderr, &fn_table_entry->ir_executable, 4);3750 ir_print(g, stderr, &fn_table_entry->ir_executable, 4);
3728 fprintf(stderr, "}\n");3751 fprintf(stderr, "}\n");
...@@ -5155,11 +5178,10 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {...@@ -5155,11 +5178,10 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
5155 if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {5178 if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {
5156 TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);5179 TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);
5157 assert(field != nullptr);5180 assert(field != nullptr);
5158 if (type_has_bits(field->type_entry)) {5181 if (!type_has_bits(field->type_entry))
5159 zig_panic("TODO const expr analyze union field value for equality");
5160 } else {
5161 return true;5182 return true;
5162 }5183 assert(find_union_field_by_tag(a->type, &union2->tag) != nullptr);
5184 return const_values_equal(g, union1->payload, union2->payload);
5163 }5185 }
5164 return false;5186 return false;
5165 }5187 }
...@@ -6070,7 +6092,7 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents) {...@@ -6070,7 +6092,7 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents) {
6070 if (g->enable_cache) {6092 if (g->enable_cache) {
6071 return cache_add_file_fetch(&g->cache_hash, resolved_path, contents);6093 return cache_add_file_fetch(&g->cache_hash, resolved_path, contents);
6072 } else {6094 } else {
6073 return os_fetch_file_path(resolved_path, contents, false);6095 return os_fetch_file_path(resolved_path, contents);
6074 }6096 }
6075}6097}
60766098
...@@ -7222,3 +7244,16 @@ ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type) {...@@ -7222,3 +7244,16 @@ ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type) {
7222 assertNoError(type_resolve(g, type, ResolveStatusLLVMFull));7244 assertNoError(type_resolve(g, type, ResolveStatusLLVMFull));
7223 return type->llvm_di_type;7245 return type->llvm_di_type;
7224}7246}
7247
7248void src_assert(bool ok, AstNode *source_node) {
7249 if (ok) return;
7250 if (source_node == nullptr) {
7251 fprintf(stderr, "when analyzing (unknown source location): ");
7252 } else {
7253 fprintf(stderr, "when analyzing %s:%u:%u: ",
7254 buf_ptr(source_node->owner->data.structure.root_struct->path),
7255 (unsigned)source_node->line + 1, (unsigned)source_node->column + 1);
7256 }
7257 const char *msg = "assertion failed";
7258 stage2_panic(msg, strlen(msg));
7259}
src/analyze.hpp+4
...@@ -247,4 +247,8 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose...@@ -247,4 +247,8 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
247LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type);247LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type);
248ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);248ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);
249249
250void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c);
251
252void src_assert(bool ok, AstNode *source_node);
253
250#endif254#endif
src/ast_render.cpp+2-4
...@@ -296,7 +296,6 @@ void ast_print(FILE *f, AstNode *node, int indent) {...@@ -296,7 +296,6 @@ void ast_print(FILE *f, AstNode *node, int indent) {
296296
297297
298struct AstRender {298struct AstRender {
299 CodeGen *codegen;
300 int indent;299 int indent;
301 int indent_size;300 int indent_size;
302 FILE *f;301 FILE *f;
...@@ -633,7 +632,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -633,7 +632,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
633 if (is_printable(c)) {632 if (is_printable(c)) {
634 fprintf(ar->f, "'%c'", c);633 fprintf(ar->f, "'%c'", c);
635 } else {634 } else {
636 fprintf(ar->f, "'\\x%x'", (int)c);635 fprintf(ar->f, "'\\x%02x'", (int)c);
637 }636 }
638 break;637 break;
639 }638 }
...@@ -1170,9 +1169,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -1170,9 +1169,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
1170}1169}
11711170
11721171
1173void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size) {1172void ast_render(FILE *f, AstNode *node, int indent_size) {
1174 AstRender ar = {0};1173 AstRender ar = {0};
1175 ar.codegen = codegen;
1176 ar.f = f;1174 ar.f = f;
1177 ar.indent_size = indent_size;1175 ar.indent_size = indent_size;
1178 ar.indent = 0;1176 ar.indent = 0;
src/ast_render.hpp+1-1
...@@ -15,6 +15,6 @@...@@ -15,6 +15,6 @@
1515
16void ast_print(FILE *f, AstNode *node, int indent);16void ast_print(FILE *f, AstNode *node, int indent);
1717
18void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);18void ast_render(FILE *f, AstNode *node, int indent_size);
1919
20#endif20#endif
src/bigint.cpp+10-3
...@@ -1395,7 +1395,7 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {...@@ -1395,7 +1395,7 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1395 uint64_t shift_amt = bigint_as_unsigned(op2);1395 uint64_t shift_amt = bigint_as_unsigned(op2);
13961396
1397 if (op1->digit_count == 1) {1397 if (op1->digit_count == 1) {
1398 dest->data.digit = op1_digits[0] >> shift_amt;1398 dest->data.digit = (shift_amt < 64) ? op1_digits[0] >> shift_amt : 0;
1399 dest->digit_count = 1;1399 dest->digit_count = 1;
1400 dest->is_negative = op1->is_negative;1400 dest->is_negative = op1->is_negative;
1401 bigint_normalize(dest);1401 bigint_normalize(dest);
...@@ -1410,12 +1410,19 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {...@@ -1410,12 +1410,19 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1410 }1410 }
14111411
1412 dest->digit_count = op1->digit_count - digit_shift_count;1412 dest->digit_count = op1->digit_count - digit_shift_count;
1413 dest->data.digits = allocate<uint64_t>(dest->digit_count);1413 uint64_t *digits;
1414 if (dest->digit_count == 1) {
1415 digits = &dest->data.digit;
1416 } else {
1417 digits = allocate<uint64_t>(dest->digit_count);
1418 dest->data.digits = digits;
1419 }
1420
1414 uint64_t carry = 0;1421 uint64_t carry = 0;
1415 for (size_t op_digit_index = op1->digit_count - 1;;) {1422 for (size_t op_digit_index = op1->digit_count - 1;;) {
1416 uint64_t digit = op1_digits[op_digit_index];1423 uint64_t digit = op1_digits[op_digit_index];
1417 size_t dest_digit_index = op_digit_index - digit_shift_count;1424 size_t dest_digit_index = op_digit_index - digit_shift_count;
1418 dest->data.digits[dest_digit_index] = carry | (digit >> leftover_shift_count);1425 digits[dest_digit_index] = carry | (digit >> leftover_shift_count);
1419 carry = digit << (64 - leftover_shift_count);1426 carry = digit << (64 - leftover_shift_count);
14201427
1421 if (dest_digit_index == 0) { break; }1428 if (dest_digit_index == 0) { break; }
src/buffer.hpp-1
...@@ -10,7 +10,6 @@...@@ -10,7 +10,6 @@
1010
11#include "list.hpp"11#include "list.hpp"
1212
13#include <assert.h>
14#include <stdint.h>13#include <stdint.h>
15#include <ctype.h>14#include <ctype.h>
16#include <stdarg.h>15#include <stdarg.h>
src/c_tokenizer.cpp+20
...@@ -124,6 +124,8 @@ static void begin_token(CTokenize *ctok, CTokId id) {...@@ -124,6 +124,8 @@ static void begin_token(CTokenize *ctok, CTokId id) {
124 case CTokIdAsterisk:124 case CTokIdAsterisk:
125 case CTokIdBang:125 case CTokIdBang:
126 case CTokIdTilde:126 case CTokIdTilde:
127 case CTokIdShl:
128 case CTokIdLt:
127 break;129 break;
128 }130 }
129}131}
...@@ -223,6 +225,10 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {...@@ -223,6 +225,10 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
223 begin_token(ctok, CTokIdDot);225 begin_token(ctok, CTokIdDot);
224 end_token(ctok);226 end_token(ctok);
225 break;227 break;
228 case '<':
229 begin_token(ctok, CTokIdLt);
230 ctok->state = CTokStateGotLt;
231 break;
226 case '(':232 case '(':
227 begin_token(ctok, CTokIdLParen);233 begin_token(ctok, CTokIdLParen);
228 end_token(ctok);234 end_token(ctok);
...@@ -251,6 +257,19 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {...@@ -251,6 +257,19 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
251 return mark_error(ctok);257 return mark_error(ctok);
252 }258 }
253 break;259 break;
260 case CTokStateGotLt:
261 switch (*c) {
262 case '<':
263 ctok->cur_tok->id = CTokIdShl;
264 end_token(ctok);
265 ctok->state = CTokStateStart;
266 break;
267 default:
268 end_token(ctok);
269 ctok->state = CTokStateStart;
270 continue;
271 }
272 break;
254 case CTokStateFloat:273 case CTokStateFloat:
255 switch (*c) {274 switch (*c) {
256 case '.':275 case '.':
...@@ -791,6 +810,7 @@ found_end_of_macro:...@@ -791,6 +810,7 @@ found_end_of_macro:
791 case CTokStateNumLitIntSuffixL:810 case CTokStateNumLitIntSuffixL:
792 case CTokStateNumLitIntSuffixUL:811 case CTokStateNumLitIntSuffixUL:
793 case CTokStateNumLitIntSuffixLL:812 case CTokStateNumLitIntSuffixLL:
813 case CTokStateGotLt:
794 end_token(ctok);814 end_token(ctok);
795 break;815 break;
796 case CTokStateFloat:816 case CTokStateFloat:
src/c_tokenizer.hpp+3
...@@ -25,6 +25,8 @@ enum CTokId {...@@ -25,6 +25,8 @@ enum CTokId {
25 CTokIdAsterisk,25 CTokIdAsterisk,
26 CTokIdBang,26 CTokIdBang,
27 CTokIdTilde,27 CTokIdTilde,
28 CTokIdShl,
29 CTokIdLt,
28};30};
2931
30enum CNumLitSuffix {32enum CNumLitSuffix {
...@@ -78,6 +80,7 @@ enum CTokState {...@@ -78,6 +80,7 @@ enum CTokState {
78 CTokStateNumLitIntSuffixL,80 CTokStateNumLitIntSuffixL,
79 CTokStateNumLitIntSuffixLL,81 CTokStateNumLitIntSuffixLL,
80 CTokStateNumLitIntSuffixUL,82 CTokStateNumLitIntSuffixUL,
83 CTokStateGotLt,
81};84};
8285
83struct CTokenize {86struct CTokenize {
src/cache_hash.cpp+14-14
...@@ -256,10 +256,10 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents...@@ -256,10 +256,10 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents
256 }256 }
257257
258 if ((err = hash_file(chf->bin_digest, this_file, contents))) {258 if ((err = hash_file(chf->bin_digest, this_file, contents))) {
259 os_file_close(this_file);259 os_file_close(&this_file);
260 return err;260 return err;
261 }261 }
262 os_file_close(this_file);262 os_file_close(&this_file);
263263
264 blake2b_update(&ch->blake, chf->bin_digest, 48);264 blake2b_update(&ch->blake, chf->bin_digest, 48);
265265
...@@ -300,7 +300,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -300,7 +300,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
300 Buf line_buf = BUF_INIT;300 Buf line_buf = BUF_INIT;
301 buf_resize(&line_buf, 512);301 buf_resize(&line_buf, 512);
302 if ((err = os_file_read_all(ch->manifest_file, &line_buf))) {302 if ((err = os_file_read_all(ch->manifest_file, &line_buf))) {
303 os_file_close(ch->manifest_file);303 os_file_close(&ch->manifest_file);
304 return err;304 return err;
305 }305 }
306306
...@@ -389,14 +389,14 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -389,14 +389,14 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
389 OsFileAttr actual_attr;389 OsFileAttr actual_attr;
390 if ((err = os_file_open_r(chf->path, &this_file, &actual_attr))) {390 if ((err = os_file_open_r(chf->path, &this_file, &actual_attr))) {
391 fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));391 fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));
392 os_file_close(ch->manifest_file);392 os_file_close(&ch->manifest_file);
393 return ErrorCacheUnavailable;393 return ErrorCacheUnavailable;
394 }394 }
395 if (chf->attr.mtime.sec == actual_attr.mtime.sec &&395 if (chf->attr.mtime.sec == actual_attr.mtime.sec &&
396 chf->attr.mtime.nsec == actual_attr.mtime.nsec &&396 chf->attr.mtime.nsec == actual_attr.mtime.nsec &&
397 chf->attr.inode == actual_attr.inode)397 chf->attr.inode == actual_attr.inode)
398 {398 {
399 os_file_close(this_file);399 os_file_close(&this_file);
400 } else {400 } else {
401 // we have to recompute the digest.401 // we have to recompute the digest.
402 // later we'll rewrite the manifest with the new mtime/digest values402 // later we'll rewrite the manifest with the new mtime/digest values
...@@ -411,11 +411,11 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -411,11 +411,11 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
411411
412 uint8_t actual_digest[48];412 uint8_t actual_digest[48];
413 if ((err = hash_file(actual_digest, this_file, nullptr))) {413 if ((err = hash_file(actual_digest, this_file, nullptr))) {
414 os_file_close(this_file);414 os_file_close(&this_file);
415 os_file_close(ch->manifest_file);415 os_file_close(&ch->manifest_file);
416 return err;416 return err;
417 }417 }
418 os_file_close(this_file);418 os_file_close(&this_file);
419 if (memcmp(chf->bin_digest, actual_digest, 48) != 0) {419 if (memcmp(chf->bin_digest, actual_digest, 48) != 0) {
420 memcpy(chf->bin_digest, actual_digest, 48);420 memcpy(chf->bin_digest, actual_digest, 48);
421 // keep going until we have the input file digests421 // keep going until we have the input file digests
...@@ -433,12 +433,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -433,12 +433,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
433 CacheHashFile *chf = &ch->files.at(file_i);433 CacheHashFile *chf = &ch->files.at(file_i);
434 if ((err = populate_file_hash(ch, chf, nullptr))) {434 if ((err = populate_file_hash(ch, chf, nullptr))) {
435 fprintf(stderr, "Unable to hash %s: %s\n", buf_ptr(chf->path), err_str(err));435 fprintf(stderr, "Unable to hash %s: %s\n", buf_ptr(chf->path), err_str(err));
436 os_file_close(ch->manifest_file);436 os_file_close(&ch->manifest_file);
437 return ErrorCacheUnavailable;437 return ErrorCacheUnavailable;
438 }438 }
439 }439 }
440 if (return_code != ErrorNone) {440 if (return_code != ErrorNone && return_code != ErrorInvalidFormat) {
441 os_file_close(ch->manifest_file);441 os_file_close(&ch->manifest_file);
442 }442 }
443 return return_code;443 return return_code;
444 }444 }
...@@ -453,7 +453,7 @@ Error cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents) {...@@ -453,7 +453,7 @@ Error cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents) {
453 CacheHashFile *chf = ch->files.add_one();453 CacheHashFile *chf = ch->files.add_one();
454 chf->path = resolved_path;454 chf->path = resolved_path;
455 if ((err = populate_file_hash(ch, chf, contents))) {455 if ((err = populate_file_hash(ch, chf, contents))) {
456 os_file_close(ch->manifest_file);456 os_file_close(&ch->manifest_file);
457 return err;457 return err;
458 }458 }
459459
...@@ -469,7 +469,7 @@ Error cache_add_file(CacheHash *ch, Buf *path) {...@@ -469,7 +469,7 @@ Error cache_add_file(CacheHash *ch, Buf *path) {
469Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {469Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {
470 Error err;470 Error err;
471 Buf *contents = buf_alloc();471 Buf *contents = buf_alloc();
472 if ((err = os_fetch_file_path(dep_file_path, contents, false))) {472 if ((err = os_fetch_file_path(dep_file_path, contents))) {
473 if (verbose) {473 if (verbose) {
474 fprintf(stderr, "unable to read .d file: %s\n", err_str(err));474 fprintf(stderr, "unable to read .d file: %s\n", err_str(err));
475 }475 }
...@@ -586,6 +586,6 @@ void cache_release(CacheHash *ch) {...@@ -586,6 +586,6 @@ void cache_release(CacheHash *ch) {
586 }586 }
587 }587 }
588588
589 os_file_close(ch->manifest_file);589 os_file_close(&ch->manifest_file);
590}590}
591591
src/codegen.cpp+353-156
...@@ -19,6 +19,7 @@...@@ -19,6 +19,7 @@
19#include "target.hpp"19#include "target.hpp"
20#include "util.hpp"20#include "util.hpp"
21#include "zig_llvm.h"21#include "zig_llvm.h"
22#include "userland.h"
2223
23#include <stdio.h>24#include <stdio.h>
24#include <errno.h>25#include <errno.h>
...@@ -92,7 +93,7 @@ static const char *symbols_that_llvm_depends_on[] = {...@@ -92,7 +93,7 @@ static const char *symbols_that_llvm_depends_on[] = {
92};93};
9394
94CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,95CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
95 OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir,96 OutType out_type, BuildMode build_mode, Buf *override_lib_dir, Buf *override_std_dir,
96 ZigLibCInstallation *libc, Buf *cache_dir)97 ZigLibCInstallation *libc, Buf *cache_dir)
97{98{
98 CodeGen *g = allocate<CodeGen>(1);99 CodeGen *g = allocate<CodeGen>(1);
...@@ -100,19 +101,24 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget...@@ -100,19 +101,24 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
100 codegen_add_time_event(g, "Initialize");101 codegen_add_time_event(g, "Initialize");
101102
102 g->libc = libc;103 g->libc = libc;
103 g->zig_lib_dir = zig_lib_dir;
104 g->zig_target = target;104 g->zig_target = target;
105 g->cache_dir = cache_dir;105 g->cache_dir = cache_dir;
106106
107 if (override_lib_dir == nullptr) {
108 g->zig_lib_dir = get_zig_lib_dir();
109 } else {
110 g->zig_lib_dir = override_lib_dir;
111 }
112
107 if (override_std_dir == nullptr) {113 if (override_std_dir == nullptr) {
108 g->zig_std_dir = buf_alloc();114 g->zig_std_dir = buf_alloc();
109 os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);115 os_path_join(g->zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
110 } else {116 } else {
111 g->zig_std_dir = override_std_dir;117 g->zig_std_dir = override_std_dir;
112 }118 }
113119
114 g->zig_c_headers_dir = buf_alloc();120 g->zig_c_headers_dir = buf_alloc();
115 os_path_join(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir);121 os_path_join(g->zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir);
116122
117 g->build_mode = build_mode;123 g->build_mode = build_mode;
118 g->out_type = out_type;124 g->out_type = out_type;
...@@ -393,6 +399,15 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {...@@ -393,6 +399,15 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
393 }399 }
394}400}
395401
402static void add_probe_stack_attr(CodeGen *g, LLVMValueRef fn_val) {
403 // Windows already emits its own stack probes
404 if (!g->disable_stack_probing && g->zig_target->os != OsWindows &&
405 (g->zig_target->arch == ZigLLVM_x86 ||
406 g->zig_target->arch == ZigLLVM_x86_64)) {
407 addLLVMFnAttrStr(fn_val, "probe-stack", "__zig_probe_stack");
408 }
409}
410
396static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {411static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {
397 switch (id) {412 switch (id) {
398 case GlobalLinkageIdInternal:413 case GlobalLinkageIdInternal:
...@@ -424,7 +439,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {...@@ -424,7 +439,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
424}439}
425440
426static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {441static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
427 if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) {442 if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows && g->is_dynamic) {
428 LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);443 LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
429 }444 }
430}445}
...@@ -495,6 +510,14 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -495,6 +510,14 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
495 auto entry = g->exported_symbol_names.maybe_get(symbol_name);510 auto entry = g->exported_symbol_names.maybe_get(symbol_name);
496 if (entry == nullptr) {511 if (entry == nullptr) {
497 fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);512 fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);
513
514 if (target_is_wasm(g->zig_target)) {
515 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
516 AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto;
517 if (fn_proto-> is_extern && fn_proto->lib_name != nullptr ) {
518 addLLVMFnAttrStr(fn_table_entry->llvm_value, "wasm-import-module", buf_ptr(fn_proto->lib_name));
519 }
520 }
498 } else {521 } else {
499 assert(entry->value->id == TldIdFn);522 assert(entry->value->id == TldIdFn);
500 TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value);523 TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value);
...@@ -573,6 +596,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -573,6 +596,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
573 addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");596 addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");
574 addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");597 addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");
575 }598 }
599
600 add_probe_stack_attr(g, fn_table_entry->llvm_value);
576 }601 }
577 } else {602 } else {
578 maybe_import_dll(g, fn_table_entry->llvm_value, linkage);603 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...@@ -983,10 +1008,19 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace
983 LLVMBuildUnreachable(g->builder);1008 LLVMBuildUnreachable(g->builder);
984}1009}
9851010
1011// TODO update most callsites to call gen_assertion instead of this
986static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) {1012static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) {
987 gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr);1013 gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr);
988}1014}
9891015
1016static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstruction *source_instruction) {
1017 if (ir_want_runtime_safety(g, source_instruction)) {
1018 gen_safety_crash(g, msg_id);
1019 } else {
1020 LLVMBuildUnreachable(g->builder);
1021 }
1022}
1023
990static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {1024static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
991 if (g->stacksave_fn_val)1025 if (g->stacksave_fn_val)
992 return g->stacksave_fn_val;1026 return g->stacksave_fn_val;
...@@ -1022,7 +1056,7 @@ static LLVMValueRef get_write_register_fn_val(CodeGen *g) {...@@ -1022,7 +1056,7 @@ static LLVMValueRef get_write_register_fn_val(CodeGen *g) {
1022 // !0 = !{!"sp\00"}1056 // !0 = !{!"sp\00"}
10231057
1024 LLVMTypeRef param_types[] = {1058 LLVMTypeRef param_types[] = {
1025 LLVMMetadataTypeInContext(LLVMGetGlobalContext()), 1059 LLVMMetadataTypeInContext(LLVMGetGlobalContext()),
1026 LLVMIntType(g->pointer_size_bytes * 8),1060 LLVMIntType(g->pointer_size_bytes * 8),
1027 };1061 };
10281062
...@@ -1541,11 +1575,19 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {...@@ -1541,11 +1575,19 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
1541 LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_array, offset_ptr_indices, 2);1575 LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_array, offset_ptr_indices, 2);
15421576
1543 Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false);1577 Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false);
1544 LLVMTypeRef arg_types[] = {1578 LLVMTypeRef fn_type_ref;
1545 get_llvm_type(g, g->ptr_to_stack_trace_type),1579 if (g->have_err_ret_tracing) {
1546 get_llvm_type(g, g->err_tag_type),1580 LLVMTypeRef arg_types[] = {
1547 };1581 get_llvm_type(g, g->ptr_to_stack_trace_type),
1548 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);1582 get_llvm_type(g, g->err_tag_type),
1583 };
1584 fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
1585 } else {
1586 LLVMTypeRef arg_types[] = {
1587 get_llvm_type(g, g->err_tag_type),
1588 };
1589 fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);
1590 }
1549 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);1591 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);
1550 addLLVMFnAttr(fn_val, "noreturn");1592 addLLVMFnAttr(fn_val, "noreturn");
1551 addLLVMFnAttr(fn_val, "cold");1593 addLLVMFnAttr(fn_val, "cold");
...@@ -1567,7 +1609,15 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {...@@ -1567,7 +1609,15 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
1567 LLVMPositionBuilderAtEnd(g->builder, entry_block);1609 LLVMPositionBuilderAtEnd(g->builder, entry_block);
1568 ZigLLVMClearCurrentDebugLocation(g->builder);1610 ZigLLVMClearCurrentDebugLocation(g->builder);
15691611
1570 LLVMValueRef err_val = LLVMGetParam(fn_val, 1);1612 LLVMValueRef err_ret_trace_arg;
1613 LLVMValueRef err_val;
1614 if (g->have_err_ret_tracing) {
1615 err_ret_trace_arg = LLVMGetParam(fn_val, 0);
1616 err_val = LLVMGetParam(fn_val, 1);
1617 } else {
1618 err_ret_trace_arg = nullptr;
1619 err_val = LLVMGetParam(fn_val, 0);
1620 }
15711621
1572 LLVMValueRef err_table_indices[] = {1622 LLVMValueRef err_table_indices[] = {
1573 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),1623 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
...@@ -1589,7 +1639,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {...@@ -1589,7 +1639,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
1589 LLVMValueRef global_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, global_slice, slice_len_index, "");1639 LLVMValueRef global_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, global_slice, slice_len_index, "");
1590 gen_store(g, full_buf_len, global_slice_len_field_ptr, u8_ptr_type);1640 gen_store(g, full_buf_len, global_slice_len_field_ptr, u8_ptr_type);
15911641
1592 gen_panic(g, global_slice, LLVMGetParam(fn_val, 0));1642 gen_panic(g, global_slice, err_ret_trace_arg);
15931643
1594 LLVMPositionBuilderAtEnd(g->builder, prev_block);1644 LLVMPositionBuilderAtEnd(g->builder, prev_block);
1595 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);1645 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
...@@ -1625,17 +1675,26 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) {...@@ -1625,17 +1675,26 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) {
16251675
1626static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {1676static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {
1627 LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);1677 LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);
1628 LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);1678 LLVMValueRef call_instruction;
1629 if (err_ret_trace_val == nullptr) {1679 if (g->have_err_ret_tracing) {
1630 ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);1680 LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);
1631 err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type));1681 if (err_ret_trace_val == nullptr) {
1682 ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
1683 err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type));
1684 }
1685 LLVMValueRef args[] = {
1686 err_ret_trace_val,
1687 err_val,
1688 };
1689 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2,
1690 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
1691 } else {
1692 LLVMValueRef args[] = {
1693 err_val,
1694 };
1695 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 1,
1696 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
1632 }1697 }
1633 LLVMValueRef args[] = {
1634 err_ret_trace_val,
1635 err_val,
1636 };
1637 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2, get_llvm_cc(g, CallingConventionUnspecified),
1638 ZigLLVM_FnInlineAuto, "");
1639 LLVMSetTailCall(call_instruction, true);1698 LLVMSetTailCall(call_instruction, true);
1640 LLVMBuildUnreachable(g->builder);1699 LLVMBuildUnreachable(g->builder);
1641}1700}
...@@ -3452,6 +3511,15 @@ static bool want_valgrind_support(CodeGen *g) {...@@ -3452,6 +3511,15 @@ static bool want_valgrind_support(CodeGen *g) {
3452 zig_unreachable();3511 zig_unreachable();
3453}3512}
34543513
3514static void gen_valgrind_undef(CodeGen *g, LLVMValueRef dest_ptr, LLVMValueRef byte_count) {
3515 static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
3516 ZigType *usize = g->builtin_types.entry_usize;
3517 LLVMValueRef zero = LLVMConstInt(usize->llvm_type, 0, false);
3518 LLVMValueRef req = LLVMConstInt(usize->llvm_type, VG_USERREQ__MAKE_MEM_UNDEFINED, false);
3519 LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->llvm_type, "");
3520 gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero);
3521}
3522
3455static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {3523static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
3456 assert(type_has_bits(value_type));3524 assert(type_has_bits(value_type));
3457 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, value_type));3525 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_...@@ -3466,11 +3534,7 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_
3466 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);3534 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
3467 // then tell valgrind that the memory is undefined even though we just memset it3535 // then tell valgrind that the memory is undefined even though we just memset it
3468 if (want_valgrind_support(g)) {3536 if (want_valgrind_support(g)) {
3469 static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;3537 gen_valgrind_undef(g, dest_ptr, byte_count);
3470 LLVMValueRef zero = LLVMConstInt(usize->llvm_type, 0, false);
3471 LLVMValueRef req = LLVMConstInt(usize->llvm_type, VG_USERREQ__MAKE_MEM_UNDEFINED, false);
3472 LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->llvm_type, "");
3473 gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero);
3474 }3538 }
3475}3539}
34763540
...@@ -3480,14 +3544,14 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir...@@ -3480,14 +3544,14 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
3480 if (!type_has_bits(ptr_type))3544 if (!type_has_bits(ptr_type))
3481 return nullptr;3545 return nullptr;
34823546
3483 bool have_init_expr = !value_is_all_undef(&instruction->value->value); 3547 bool have_init_expr = !value_is_all_undef(&instruction->value->value);
3484 if (have_init_expr) {3548 if (have_init_expr) {
3485 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);3549 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3486 LLVMValueRef value = ir_llvm_value(g, instruction->value);3550 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3487 gen_assign_raw(g, ptr, ptr_type, value);3551 gen_assign_raw(g, ptr, ptr_type, value);
3488 } else if (ir_want_runtime_safety(g, &instruction->base)) {3552 } else if (ir_want_runtime_safety(g, &instruction->base)) {
3489 gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,3553 gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
3490 ir_llvm_value(g, instruction->ptr)); 3554 ir_llvm_value(g, instruction->ptr));
3491 }3555 }
3492 return nullptr;3556 return nullptr;
3493}3557}
...@@ -3690,7 +3754,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3690,7 +3754,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3690 }3754 }
3691 FnWalk fn_walk = {};3755 FnWalk fn_walk = {};
3692 fn_walk.id = FnWalkIdCall;3756 fn_walk.id = FnWalkIdCall;
3693 fn_walk.data.call.inst = instruction; 3757 fn_walk.data.call.inst = instruction;
3694 fn_walk.data.call.is_var_args = is_var_args;3758 fn_walk.data.call.is_var_args = is_var_args;
3695 fn_walk.data.call.gen_param_values = &gen_param_values;3759 fn_walk.data.call.gen_param_values = &gen_param_values;
3696 walk_function_params(g, fn_type, &fn_walk);3760 walk_function_params(g, fn_type, &fn_walk);
...@@ -3710,7 +3774,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3710,7 +3774,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
37103774
3711 LLVMCallConv llvm_cc = get_llvm_cc(g, cc);3775 LLVMCallConv llvm_cc = get_llvm_cc(g, cc);
3712 LLVMValueRef result;3776 LLVMValueRef result;
3713 3777
3714 if (instruction->new_stack == nullptr) {3778 if (instruction->new_stack == nullptr) {
3715 result = ZigLLVMBuildCall(g->builder, fn_val,3779 result = ZigLLVMBuildCall(g->builder, fn_val,
3716 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");3780 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...@@ -3968,19 +4032,19 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
3968}4032}
39694033
3970static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueRef maybe_handle) {4034static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueRef maybe_handle) {
3971 assert(maybe_type->id == ZigTypeIdOptional);4035 assert(maybe_type->id == ZigTypeIdOptional ||
4036 (maybe_type->id == ZigTypeIdPointer && maybe_type->data.pointer.allow_zero));
4037
3972 ZigType *child_type = maybe_type->data.maybe.child_type;4038 ZigType *child_type = maybe_type->data.maybe.child_type;
3973 if (!type_has_bits(child_type)) {4039 if (!type_has_bits(child_type))
3974 return maybe_handle;4040 return maybe_handle;
3975 } else {4041
3976 bool is_scalar = !handle_is_ptr(maybe_type);4042 bool is_scalar = !handle_is_ptr(maybe_type);
3977 if (is_scalar) {4043 if (is_scalar)
3978 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), "");4044 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), "");
3979 } else {4045
3980 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");4046 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
3981 return gen_load_untyped(g, maybe_field_ptr, 0, false, "");4047 return gen_load_untyped(g, maybe_field_ptr, 0, false, "");
3982 }
3983 }
3984}4048}
39854049
3986static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable,4050static 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...@@ -4001,8 +4065,8 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec
4001 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {4065 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
4002 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);4066 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
4003 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);4067 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
4004 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
4005 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");4068 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
4069 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
4006 LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);4070 LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);
40074071
4008 LLVMPositionBuilderAtEnd(g->builder, fail_block);4072 LLVMPositionBuilderAtEnd(g->builder, fail_block);
...@@ -4190,7 +4254,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {...@@ -4190,7 +4254,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
4190 LLVMTypeRef tag_int_llvm_type = get_llvm_type(g, tag_int_type);4254 LLVMTypeRef tag_int_llvm_type = get_llvm_type(g, tag_int_type);
4191 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0),4255 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0),
4192 &tag_int_llvm_type, 1, false);4256 &tag_int_llvm_type, 1, false);
4193 4257
4194 Buf *fn_name = get_mangled_name(g, buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name)), false);4258 Buf *fn_name = get_mangled_name(g, buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name)), false);
4195 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);4259 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);
4196 LLVMSetLinkage(fn_val, LLVMInternalLinkage);4260 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
...@@ -4490,17 +4554,27 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrI...@@ -4490,17 +4554,27 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrI
44904554
4491static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrInstructionMemset *instruction) {4555static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrInstructionMemset *instruction) {
4492 LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr);4556 LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr);
4493 LLVMValueRef char_val = ir_llvm_value(g, instruction->byte);
4494 LLVMValueRef len_val = ir_llvm_value(g, instruction->count);4557 LLVMValueRef len_val = ir_llvm_value(g, instruction->count);
44954558
4496 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);4559 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
4497
4498 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");4560 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
44994561
4500 ZigType *ptr_type = instruction->dest_ptr->value.type;4562 ZigType *ptr_type = instruction->dest_ptr->value.type;
4501 assert(ptr_type->id == ZigTypeIdPointer);4563 assert(ptr_type->id == ZigTypeIdPointer);
45024564
4503 ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, char_val, len_val, get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile);4565 bool val_is_undef = value_is_all_undef(&instruction->byte->value);
4566 LLVMValueRef fill_char;
4567 if (val_is_undef) {
4568 fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
4569 } else {
4570 fill_char = ir_llvm_value(g, instruction->byte);
4571 }
4572 ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, fill_char, len_val, get_ptr_align(g, ptr_type),
4573 ptr_type->data.pointer.is_volatile);
4574
4575 if (val_is_undef && want_valgrind_support(g)) {
4576 gen_valgrind_undef(g, dest_ptr_casted, len_val);
4577 }
4504 return nullptr;4578 return nullptr;
4505}4579}
45064580
...@@ -5422,6 +5496,31 @@ static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,...@@ -5422,6 +5496,31 @@ static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,
5422 return nullptr;5496 return nullptr;
5423}5497}
54245498
5499static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutable *executable,
5500 IrInstructionAssertNonNull *instruction)
5501{
5502 LLVMValueRef target = ir_llvm_value(g, instruction->target);
5503 ZigType *target_type = instruction->target->value.type;
5504
5505 if (target_type->id == ZigTypeIdPointer) {
5506 assert(target_type->data.pointer.ptr_len == PtrLenC);
5507 LLVMValueRef non_null_bit = LLVMBuildICmp(g->builder, LLVMIntNE, target,
5508 LLVMConstNull(get_llvm_type(g, target_type)), "");
5509
5510 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "AssertNonNullFail");
5511 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "AssertNonNullOk");
5512 LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);
5513
5514 LLVMPositionBuilderAtEnd(g->builder, fail_block);
5515 gen_assertion(g, PanicMsgIdUnwrapOptionalFail, &instruction->base);
5516
5517 LLVMPositionBuilderAtEnd(g->builder, ok_block);
5518 } else {
5519 zig_unreachable();
5520 }
5521 return nullptr;
5522}
5523
5425static void set_debug_location(CodeGen *g, IrInstruction *instruction) {5524static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
5426 AstNode *source_node = instruction->source_node;5525 AstNode *source_node = instruction->source_node;
5427 Scope *scope = instruction->scope;5526 Scope *scope = instruction->scope;
...@@ -5676,6 +5775,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5676,6 +5775,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5676 return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);5775 return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
5677 case IrInstructionIdAssertZero:5776 case IrInstructionIdAssertZero:
5678 return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction);5777 return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction);
5778 case IrInstructionIdAssertNonNull:
5779 return ir_render_assert_non_null(g, executable, (IrInstructionAssertNonNull *)instruction);
5679 case IrInstructionIdResizeSlice:5780 case IrInstructionIdResizeSlice:
5680 return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);5781 return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);
5681 }5782 }
...@@ -6585,7 +6686,7 @@ static void validate_inline_fns(CodeGen *g) {...@@ -6585,7 +6686,7 @@ static void validate_inline_fns(CodeGen *g) {
6585}6686}
65866687
6587static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {6688static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
6588 if (var->is_thread_local && !g->is_single_threaded) {6689 if (var->is_thread_local && (!g->is_single_threaded || var->linkage != VarLinkageInternal)) {
6589 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);6690 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
6590 }6691 }
6591}6692}
...@@ -6905,7 +7006,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6905,7 +7006,7 @@ static void do_code_gen(CodeGen *g) {
6905 ir_render(g, fn_table_entry);7006 ir_render(g, fn_table_entry);
69067007
6907 }7008 }
6908 7009
6909 assert(!g->errors.length);7010 assert(!g->errors.length);
69107011
6911 if (buf_len(&g->global_asm) != 0) {7012 if (buf_len(&g->global_asm) != 0) {
...@@ -6942,6 +7043,11 @@ static void zig_llvm_emit_output(CodeGen *g) {...@@ -6942,6 +7043,11 @@ static void zig_llvm_emit_output(CodeGen *g) {
6942 }7043 }
6943 validate_inline_fns(g);7044 validate_inline_fns(g);
6944 g->link_objects.append(output_path);7045 g->link_objects.append(output_path);
7046 if (g->bundle_compiler_rt && (g->out_type == OutTypeObj ||
7047 (g->out_type == OutTypeLib && !g->is_dynamic)))
7048 {
7049 zig_link_add_compiler_rt(g);
7050 }
6945 break;7051 break;
69467052
6947 case EmitFileTypeAssembly:7053 case EmitFileTypeAssembly:
...@@ -7337,9 +7443,26 @@ static bool detect_pic(CodeGen *g) {...@@ -7337,9 +7443,26 @@ static bool detect_pic(CodeGen *g) {
7337 zig_unreachable();7443 zig_unreachable();
7338}7444}
73397445
7446static bool detect_single_threaded(CodeGen *g) {
7447 if (g->want_single_threaded)
7448 return true;
7449 if (target_is_single_threaded(g->zig_target)) {
7450 return true;
7451 }
7452 return false;
7453}
7454
7455static bool detect_err_ret_tracing(CodeGen *g) {
7456 return !target_is_wasm(g->zig_target) &&
7457 g->build_mode != BuildModeFastRelease &&
7458 g->build_mode != BuildModeSmallRelease;
7459}
7460
7340Buf *codegen_generate_builtin_source(CodeGen *g) {7461Buf *codegen_generate_builtin_source(CodeGen *g) {
7341 g->have_dynamic_link = detect_dynamic_link(g);7462 g->have_dynamic_link = detect_dynamic_link(g);
7342 g->have_pic = detect_pic(g);7463 g->have_pic = detect_pic(g);
7464 g->is_single_threaded = detect_single_threaded(g);
7465 g->have_err_ret_tracing = detect_err_ret_tracing(g);
73437466
7344 Buf *contents = buf_alloc();7467 Buf *contents = buf_alloc();
73457468
...@@ -7696,7 +7819,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7696,7 +7819,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7696 assert(ContainerLayoutAuto == 0);7819 assert(ContainerLayoutAuto == 0);
7697 assert(ContainerLayoutExtern == 1);7820 assert(ContainerLayoutExtern == 1);
7698 assert(ContainerLayoutPacked == 2);7821 assert(ContainerLayoutPacked == 2);
7699 7822
7700 assert(CallingConventionUnspecified == 0);7823 assert(CallingConventionUnspecified == 0);
7701 assert(CallingConventionC == 1);7824 assert(CallingConventionC == 1);
7702 assert(CallingConventionCold == 2);7825 assert(CallingConventionCold == 2);
...@@ -7814,7 +7937,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -7814,7 +7937,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
7814 Buf *contents;7937 Buf *contents;
7815 if (hit) {7938 if (hit) {
7816 contents = buf_alloc();7939 contents = buf_alloc();
7817 if ((err = os_fetch_file_path(builtin_zig_path, contents, false))) {7940 if ((err = os_fetch_file_path(builtin_zig_path, contents))) {
7818 fprintf(stderr, "Unable to open '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err));7941 fprintf(stderr, "Unable to open '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err));
7819 exit(1);7942 exit(1);
7820 }7943 }
...@@ -7844,6 +7967,12 @@ static void init(CodeGen *g) {...@@ -7844,6 +7967,12 @@ static void init(CodeGen *g) {
78447967
7845 g->have_dynamic_link = detect_dynamic_link(g);7968 g->have_dynamic_link = detect_dynamic_link(g);
7846 g->have_pic = detect_pic(g);7969 g->have_pic = detect_pic(g);
7970 g->is_single_threaded = detect_single_threaded(g);
7971 g->have_err_ret_tracing = detect_err_ret_tracing(g);
7972
7973 if (target_is_single_threaded(g->zig_target)) {
7974 g->is_single_threaded = true;
7975 }
78477976
7848 if (g->is_test_build) {7977 if (g->is_test_build) {
7849 g->subsystem = TargetSubsystemConsole;7978 g->subsystem = TargetSubsystemConsole;
...@@ -7953,8 +8082,6 @@ static void init(CodeGen *g) {...@@ -7953,8 +8082,6 @@ static void init(CodeGen *g) {
7953 }8082 }
7954 }8083 }
79558084
7956 g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease && g->build_mode != BuildModeSmallRelease;
7957
7958 define_builtin_fns(g);8085 define_builtin_fns(g);
7959 Error err;8086 Error err;
7960 if ((err = define_builtin_compile_vars(g))) {8087 if ((err = define_builtin_compile_vars(g))) {
...@@ -8093,7 +8220,126 @@ static void detect_libc(CodeGen *g) {...@@ -8093,7 +8220,126 @@ static void detect_libc(CodeGen *g) {
8093 }8220 }
8094}8221}
80958222
8096AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {8223// does not add the "cc" arg
8224void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c) {
8225 if (translate_c) {
8226 args.append("-x");
8227 args.append("c");
8228 }
8229
8230 if (out_dep_path != nullptr) {
8231 args.append("-MD");
8232 args.append("-MV");
8233 args.append("-MF");
8234 args.append(out_dep_path);
8235 }
8236
8237 args.append("-nostdinc");
8238 args.append("-fno-spell-checking");
8239
8240 if (translate_c) {
8241 // this gives us access to preprocessing entities, presumably at
8242 // the cost of performance
8243 args.append("-Xclang");
8244 args.append("-detailed-preprocessing-record");
8245 } else {
8246 switch (g->err_color) {
8247 case ErrColorAuto:
8248 break;
8249 case ErrColorOff:
8250 args.append("-fno-color-diagnostics");
8251 args.append("-fno-caret-diagnostics");
8252 break;
8253 case ErrColorOn:
8254 args.append("-fcolor-diagnostics");
8255 args.append("-fcaret-diagnostics");
8256 break;
8257 }
8258 }
8259
8260 args.append("-isystem");
8261 args.append(buf_ptr(g->zig_c_headers_dir));
8262
8263 for (size_t i = 0; i < g->libc_include_dir_len; i += 1) {
8264 Buf *include_dir = g->libc_include_dir_list[i];
8265 args.append("-isystem");
8266 args.append(buf_ptr(include_dir));
8267 }
8268
8269 if (g->zig_target->is_native) {
8270 args.append("-march=native");
8271 } else {
8272 args.append("-target");
8273 args.append(buf_ptr(&g->triple_str));
8274 }
8275 if (g->zig_target->os == OsFreestanding) {
8276 args.append("-ffreestanding");
8277 }
8278
8279 if (!g->strip_debug_symbols) {
8280 args.append("-g");
8281 }
8282
8283 switch (g->build_mode) {
8284 case BuildModeDebug:
8285 // windows c runtime requires -D_DEBUG if using debug libraries
8286 args.append("-D_DEBUG");
8287
8288 if (g->libc_link_lib != nullptr) {
8289 args.append("-fstack-protector-strong");
8290 args.append("--param");
8291 args.append("ssp-buffer-size=4");
8292 } else {
8293 args.append("-fno-stack-protector");
8294 }
8295 args.append("-fno-omit-frame-pointer");
8296 break;
8297 case BuildModeSafeRelease:
8298 // See the comment in the BuildModeFastRelease case for why we pass -O2 rather
8299 // than -O3 here.
8300 args.append("-O2");
8301 if (g->libc_link_lib != nullptr) {
8302 args.append("-D_FORTIFY_SOURCE=2");
8303 args.append("-fstack-protector-strong");
8304 args.append("--param");
8305 args.append("ssp-buffer-size=4");
8306 } else {
8307 args.append("-fno-stack-protector");
8308 }
8309 args.append("-fomit-frame-pointer");
8310 break;
8311 case BuildModeFastRelease:
8312 args.append("-DNDEBUG");
8313 // Here we pass -O2 rather than -O3 because, although we do the equivalent of
8314 // -O3 in Zig code, the justification for the difference here is that Zig
8315 // has better detection and prevention of undefined behavior, so -O3 is safer for
8316 // Zig code than it is for C code. Also, C programmers are used to their code
8317 // running in -O2 and thus the -O3 path has been tested less.
8318 args.append("-O2");
8319 args.append("-fno-stack-protector");
8320 args.append("-fomit-frame-pointer");
8321 break;
8322 case BuildModeSmallRelease:
8323 args.append("-DNDEBUG");
8324 args.append("-Os");
8325 args.append("-fno-stack-protector");
8326 args.append("-fomit-frame-pointer");
8327 break;
8328 }
8329
8330 if (target_supports_fpic(g->zig_target) && g->have_pic) {
8331 args.append("-fPIC");
8332 }
8333
8334 for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
8335 args.append(g->clang_argv[arg_i]);
8336 }
8337
8338
8339}
8340
8341void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation) {
8342 Error err;
8097 Buf *src_basename = buf_alloc();8343 Buf *src_basename = buf_alloc();
8098 Buf *src_dirname = buf_alloc();8344 Buf *src_dirname = buf_alloc();
8099 os_path_split(full_path, src_dirname, src_basename);8345 os_path_split(full_path, src_dirname, src_basename);
...@@ -8105,13 +8351,47 @@ AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {...@@ -8105,13 +8351,47 @@ AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {
81058351
8106 init(g);8352 init(g);
81078353
8108 ZigList<ErrorMsg *> errors = {0};8354 Stage2TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ?
8355 Stage2TranslateModeImport : Stage2TranslateModeTranslate;
8356
8357
8358 ZigList<const char *> clang_argv = {0};
8359 add_cc_args(g, clang_argv, nullptr, true);
8360
8361 clang_argv.append(buf_ptr(full_path));
8362
8363 if (g->verbose_cc) {
8364 fprintf(stderr, "clang");
8365 for (size_t i = 0; i < clang_argv.length; i += 1) {
8366 fprintf(stderr, " %s", clang_argv.at(i));
8367 }
8368 fprintf(stderr, "\n");
8369 }
8370
8371 clang_argv.append(nullptr); // to make the [start...end] argument work
8372
8373 const char *resources_path = buf_ptr(g->zig_c_headers_dir);
8374 Stage2ErrorMsg *errors_ptr;
8375 size_t errors_len;
8376 Stage2Ast *ast;
8109 AstNode *root_node;8377 AstNode *root_node;
8110 Error err = parse_h_file(&root_node, &errors, buf_ptr(full_path), g, nullptr);
81118378
8112 if (err == ErrorCCompileErrors && errors.length > 0) {8379 if (use_userland_implementation) {
8113 for (size_t i = 0; i < errors.length; i += 1) {8380 err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
8114 ErrorMsg *err_msg = errors.at(i);8381 &clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path);
8382 } else {
8383 err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(),
8384 trans_mode, resources_path);
8385 }
8386
8387 if (err == ErrorCCompileErrors && errors_len > 0) {
8388 for (size_t i = 0; i < errors_len; i += 1) {
8389 Stage2ErrorMsg *clang_err = &errors_ptr[i];
8390 ErrorMsg *err_msg = err_msg_create_with_offset(
8391 clang_err->filename_ptr ?
8392 buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(),
8393 clang_err->line, clang_err->column, clang_err->offset, clang_err->source,
8394 buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len));
8115 print_err_msg(err_msg, g->err_color);8395 print_err_msg(err_msg, g->err_color);
8116 }8396 }
8117 exit(1);8397 exit(1);
...@@ -8122,7 +8402,12 @@ AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {...@@ -8122,7 +8402,12 @@ AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {
8122 exit(1);8402 exit(1);
8123 }8403 }
81248404
8125 return root_node;8405
8406 if (use_userland_implementation) {
8407 stage2_render_ast(ast, out_file);
8408 } else {
8409 ast_render(out_file, root_node, 4);
8410 }
8126}8411}
81278412
8128static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) {8413static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) {
...@@ -8233,7 +8518,7 @@ static void gen_root_source(CodeGen *g) {...@@ -8233,7 +8518,7 @@ static void gen_root_source(CodeGen *g) {
8233 Error err;8518 Error err;
8234 // No need for using the caching system for this file fetch because it is handled8519 // No need for using the caching system for this file fetch because it is handled
8235 // separately.8520 // separately.
8236 if ((err = os_fetch_file_path(resolved_path, source_code, true))) {8521 if ((err = os_fetch_file_path(resolved_path, source_code))) {
8237 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(resolved_path), err_str(err));8522 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(resolved_path), err_str(err));
8238 exit(1);8523 exit(1);
8239 }8524 }
...@@ -8308,7 +8593,7 @@ static void gen_global_asm(CodeGen *g) {...@@ -8308,7 +8593,7 @@ static void gen_global_asm(CodeGen *g) {
8308 Buf *asm_file = g->assembly_files.at(i);8593 Buf *asm_file = g->assembly_files.at(i);
8309 // No need to use the caching system for these fetches because they8594 // No need to use the caching system for these fetches because they
8310 // are handled separately.8595 // are handled separately.
8311 if ((err = os_fetch_file_path(asm_file, &contents, false))) {8596 if ((err = os_fetch_file_path(asm_file, &contents))) {
8312 zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err));8597 zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err));
8313 }8598 }
8314 buf_append_buf(&g->global_asm, &contents);8599 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) {...@@ -8441,90 +8726,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
8441 args.append("cc");8726 args.append("cc");
84428727
8443 Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));8728 Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));
8444 args.append("-MD");8729 add_cc_args(g, args, buf_ptr(out_dep_path), false);
8445 args.append("-MV");
8446 args.append("-MF");
8447 args.append(buf_ptr(out_dep_path));
8448
8449 args.append("-nostdinc");
8450 args.append("-fno-spell-checking");
8451
8452 switch (g->err_color) {
8453 case ErrColorAuto:
8454 break;
8455 case ErrColorOff:
8456 args.append("-fno-color-diagnostics");
8457 args.append("-fno-caret-diagnostics");
8458 break;
8459 case ErrColorOn:
8460 args.append("-fcolor-diagnostics");
8461 args.append("-fcaret-diagnostics");
8462 break;
8463 }
8464
8465 args.append("-isystem");
8466 args.append(buf_ptr(g->zig_c_headers_dir));
8467
8468 for (size_t i = 0; i < g->libc_include_dir_len; i += 1) {
8469 Buf *include_dir = g->libc_include_dir_list[i];
8470 args.append("-isystem");
8471 args.append(buf_ptr(include_dir));
8472 }
8473
8474 if (g->zig_target->is_native) {
8475 args.append("-march=native");
8476 } else {
8477 args.append("-target");
8478 args.append(buf_ptr(&g->triple_str));
8479 }
8480
8481 if (!g->strip_debug_symbols) {
8482 args.append("-g");
8483 }
8484
8485 switch (g->build_mode) {
8486 case BuildModeDebug:
8487 if (g->libc_link_lib != nullptr) {
8488 args.append("-fstack-protector-strong");
8489 args.append("--param");
8490 args.append("ssp-buffer-size=4");
8491 } else {
8492 args.append("-fno-stack-protector");
8493 }
8494 args.append("-fno-omit-frame-pointer");
8495 break;
8496 case BuildModeSafeRelease:
8497 // See the comment in the BuildModeFastRelease case for why we pass -O2 rather
8498 // than -O3 here.
8499 args.append("-O2");
8500 if (g->libc_link_lib != nullptr) {
8501 args.append("-D_FORTIFY_SOURCE=2");
8502 args.append("-fstack-protector-strong");
8503 args.append("--param");
8504 args.append("ssp-buffer-size=4");
8505 } else {
8506 args.append("-fno-stack-protector");
8507 }
8508 args.append("-fomit-frame-pointer");
8509 break;
8510 case BuildModeFastRelease:
8511 args.append("-DNDEBUG");
8512 // Here we pass -O2 rather than -O3 because, although we do the equivalent of
8513 // -O3 in Zig code, the justification for the difference here is that Zig
8514 // has better detection and prevention of undefined behavior, so -O3 is safer for
8515 // Zig code than it is for C code. Also, C programmers are used to their code
8516 // running in -O2 and thus the -O3 path has been tested less.
8517 args.append("-O2");
8518 args.append("-fno-stack-protector");
8519 args.append("-fomit-frame-pointer");
8520 break;
8521 case BuildModeSmallRelease:
8522 args.append("-DNDEBUG");
8523 args.append("-Os");
8524 args.append("-fno-stack-protector");
8525 args.append("-fomit-frame-pointer");
8526 break;
8527 }
85288730
8529 args.append("-o");8731 args.append("-o");
8530 args.append(buf_ptr(out_obj_path));8732 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) {...@@ -8532,19 +8734,10 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
8532 args.append("-c");8734 args.append("-c");
8533 args.append(buf_ptr(c_source_file));8735 args.append(buf_ptr(c_source_file));
85348736
8535 if (target_supports_fpic(g->zig_target) && g->have_pic) {
8536 args.append("-fPIC");
8537 }
8538
8539 for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
8540 args.append(g->clang_argv[arg_i]);
8541 }
8542
8543 for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {8737 for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {
8544 args.append(c_file->args.at(arg_i));8738 args.append(c_file->args.at(arg_i));
8545 }8739 }
85468740
8547
8548 if (g->verbose_cc) {8741 if (g->verbose_cc) {
8549 print_zig_cc_cmd("zig", &args);8742 print_zig_cc_cmd("zig", &args);
8550 }8743 }
...@@ -9158,6 +9351,8 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -9158,6 +9351,8 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
9158 cache_bool(ch, g->linker_rdynamic);9351 cache_bool(ch, g->linker_rdynamic);
9159 cache_bool(ch, g->each_lib_rpath);9352 cache_bool(ch, g->each_lib_rpath);
9160 cache_bool(ch, g->disable_gen_h);9353 cache_bool(ch, g->disable_gen_h);
9354 cache_bool(ch, g->bundle_compiler_rt);
9355 cache_bool(ch, g->disable_stack_probing);
9161 cache_bool(ch, want_valgrind_support(g));9356 cache_bool(ch, want_valgrind_support(g));
9162 cache_bool(ch, g->have_pic);9357 cache_bool(ch, g->have_pic);
9163 cache_bool(ch, g->have_dynamic_link);9358 cache_bool(ch, g->have_dynamic_link);
...@@ -9268,6 +9463,8 @@ void codegen_build_and_link(CodeGen *g) {...@@ -9268,6 +9463,8 @@ void codegen_build_and_link(CodeGen *g) {
92689463
9269 g->have_dynamic_link = detect_dynamic_link(g);9464 g->have_dynamic_link = detect_dynamic_link(g);
9270 g->have_pic = detect_pic(g);9465 g->have_pic = detect_pic(g);
9466 g->is_single_threaded = detect_single_threaded(g);
9467 g->have_err_ret_tracing = detect_err_ret_tracing(g);
9271 detect_libc(g);9468 detect_libc(g);
9272 detect_dynamic_linker(g);9469 detect_dynamic_linker(g);
92739470
src/codegen.hpp+3-1
...@@ -12,6 +12,7 @@...@@ -12,6 +12,7 @@
12#include "errmsg.hpp"12#include "errmsg.hpp"
13#include "target.hpp"13#include "target.hpp"
14#include "libc_installation.hpp"14#include "libc_installation.hpp"
15#include "userland.h"
1516
16#include <stdio.h>17#include <stdio.h>
1718
...@@ -43,6 +44,7 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc...@@ -43,6 +44,7 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc
43void codegen_add_time_event(CodeGen *g, const char *name);44void codegen_add_time_event(CodeGen *g, const char *name);
44void codegen_print_timing_report(CodeGen *g, FILE *f);45void codegen_print_timing_report(CodeGen *g, FILE *f);
45void codegen_link(CodeGen *g);46void codegen_link(CodeGen *g);
47void zig_link_add_compiler_rt(CodeGen *g);
46void codegen_build_and_link(CodeGen *g);48void codegen_build_and_link(CodeGen *g);
4749
48ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path,50ZigPackage *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...@@ -50,7 +52,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
50void codegen_add_assembly(CodeGen *g, Buf *path);52void codegen_add_assembly(CodeGen *g, Buf *path);
51void codegen_add_object(CodeGen *g, Buf *object_path);53void codegen_add_object(CodeGen *g, Buf *object_path);
5254
53AstNode *codegen_translate_c(CodeGen *g, Buf *path);55void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation);
5456
55Buf *codegen_generate_builtin_source(CodeGen *g);57Buf *codegen_generate_builtin_source(CodeGen *g);
5658
src/compiler.cpp+4-4
...@@ -179,24 +179,24 @@ Buf *get_zig_lib_dir(void) {...@@ -179,24 +179,24 @@ Buf *get_zig_lib_dir(void) {
179 return &saved_lib_dir;179 return &saved_lib_dir;
180}180}
181181
182Buf *get_zig_std_dir() {182Buf *get_zig_std_dir(Buf *zig_lib_dir) {
183 if (saved_std_dir.list.length != 0) {183 if (saved_std_dir.list.length != 0) {
184 return &saved_std_dir;184 return &saved_std_dir;
185 }185 }
186 buf_resize(&saved_std_dir, 0);186 buf_resize(&saved_std_dir, 0);
187187
188 os_path_join(get_zig_lib_dir(), buf_create_from_str("std"), &saved_std_dir);188 os_path_join(zig_lib_dir, buf_create_from_str("std"), &saved_std_dir);
189189
190 return &saved_std_dir;190 return &saved_std_dir;
191}191}
192192
193Buf *get_zig_special_dir() {193Buf *get_zig_special_dir(Buf *zig_lib_dir) {
194 if (saved_special_dir.list.length != 0) {194 if (saved_special_dir.list.length != 0) {
195 return &saved_special_dir;195 return &saved_special_dir;
196 }196 }
197 buf_resize(&saved_special_dir, 0);197 buf_resize(&saved_special_dir, 0);
198198
199 os_path_join(get_zig_std_dir(), buf_sprintf("special"), &saved_special_dir);199 os_path_join(get_zig_std_dir(zig_lib_dir), buf_sprintf("special"), &saved_special_dir);
200200
201 return &saved_special_dir;201 return &saved_special_dir;
202}202}
src/compiler.hpp+2-2
...@@ -16,7 +16,7 @@ Error get_compiler_id(Buf **result);...@@ -16,7 +16,7 @@ Error get_compiler_id(Buf **result);
16Buf *get_self_dynamic_linker_path(void);16Buf *get_self_dynamic_linker_path(void);
1717
18Buf *get_zig_lib_dir(void);18Buf *get_zig_lib_dir(void);
19Buf *get_zig_special_dir(void);19Buf *get_zig_special_dir(Buf *zig_lib_dir);
20Buf *get_zig_std_dir(void);20Buf *get_zig_std_dir(Buf *zig_lib_dir);
2121
22#endif22#endif
src/error.cpp+4
...@@ -50,6 +50,10 @@ const char *err_str(Error err) {...@@ -50,6 +50,10 @@ const char *err_str(Error err) {
50 case ErrorUnexpectedWriteFailure: return "unexpected write failure";50 case ErrorUnexpectedWriteFailure: return "unexpected write failure";
51 case ErrorUnexpectedSeekFailure: return "unexpected seek failure";51 case ErrorUnexpectedSeekFailure: return "unexpected seek failure";
52 case ErrorUnexpectedFileTruncationFailure: return "unexpected file truncation failure";52 case ErrorUnexpectedFileTruncationFailure: return "unexpected file truncation failure";
53 case ErrorUnimplemented: return "unimplemented";
54 case ErrorOperationAborted: return "operation aborted";
55 case ErrorBrokenPipe: return "broken pipe";
56 case ErrorNoSpaceLeft: return "no space left";
53 }57 }
54 return "(invalid error)";58 return "(invalid error)";
55}59}
src/error.hpp+2-48
...@@ -8,56 +8,10 @@...@@ -8,56 +8,10 @@
8#ifndef ERROR_HPP8#ifndef ERROR_HPP
9#define ERROR_HPP9#define ERROR_HPP
1010
11#include <assert.h>11#include "userland.h"
12
13enum Error {
14 ErrorNone,
15 ErrorNoMem,
16 ErrorInvalidFormat,
17 ErrorSemanticAnalyzeFail,
18 ErrorAccess,
19 ErrorInterrupted,
20 ErrorSystemResources,
21 ErrorFileNotFound,
22 ErrorFileSystem,
23 ErrorFileTooBig,
24 ErrorDivByZero,
25 ErrorOverflow,
26 ErrorPathAlreadyExists,
27 ErrorUnexpected,
28 ErrorExactDivRemainder,
29 ErrorNegativeDenominator,
30 ErrorShiftedOutOneBits,
31 ErrorCCompileErrors,
32 ErrorEndOfFile,
33 ErrorIsDir,
34 ErrorNotDir,
35 ErrorUnsupportedOperatingSystem,
36 ErrorSharingViolation,
37 ErrorPipeBusy,
38 ErrorPrimitiveTypeNotFound,
39 ErrorCacheUnavailable,
40 ErrorPathTooLong,
41 ErrorCCompilerCannotFindFile,
42 ErrorReadingDepFile,
43 ErrorInvalidDepFile,
44 ErrorMissingArchitecture,
45 ErrorMissingOperatingSystem,
46 ErrorUnknownArchitecture,
47 ErrorUnknownOperatingSystem,
48 ErrorUnknownABI,
49 ErrorInvalidFilename,
50 ErrorDiskQuota,
51 ErrorDiskSpace,
52 ErrorUnexpectedWriteFailure,
53 ErrorUnexpectedSeekFailure,
54 ErrorUnexpectedFileTruncationFailure,
55};
5612
57const char *err_str(Error err);13const char *err_str(Error err);
5814
59static inline void assertNoError(Error err) {15#define assertNoError(err) assert((err) == ErrorNone);
60 assert(err == ErrorNone);
61}
6216
63#endif17#endif
src/ir.cpp+291-88
...@@ -188,6 +188,19 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -188,6 +188,19 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
188 assert(get_src_ptr_type(const_val->type) != nullptr);188 assert(get_src_ptr_type(const_val->type) != nullptr);
189 assert(const_val->special == ConstValSpecialStatic);189 assert(const_val->special == ConstValSpecialStatic);
190 ConstExprValue *result;190 ConstExprValue *result;
191
192 switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {
193 case OnePossibleValueInvalid:
194 zig_unreachable();
195 case OnePossibleValueYes:
196 result = create_const_vals(1);
197 result->type = const_val->type->data.pointer.child_type;
198 result->special = ConstValSpecialStatic;
199 return result;
200 case OnePossibleValueNo:
201 break;
202 }
203
191 switch (const_val->data.x_ptr.special) {204 switch (const_val->data.x_ptr.special) {
192 case ConstPtrSpecialInvalid:205 case ConstPtrSpecialInvalid:
193 zig_unreachable();206 zig_unreachable();
...@@ -356,6 +369,18 @@ static void ir_ref_var(ZigVar *var) {...@@ -356,6 +369,18 @@ static void ir_ref_var(ZigVar *var) {
356 var->ref_count += 1;369 var->ref_count += 1;
357}370}
358371
372ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) {
373 ConstExprValue *result = ir_eval_const_value(ira->codegen, scope, node, ira->codegen->builtin_types.entry_type,
374 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, nullptr,
375 node, nullptr, ira->new_irb.exec, nullptr);
376
377 if (type_is_invalid(result->type))
378 return ira->codegen->builtin_types.entry_invalid;
379
380 assert(result->special != ConstValSpecialRuntime);
381 return result->data.x_type;
382}
383
359static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) {384static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) {
360 IrBasicBlock *result = allocate<IrBasicBlock>(1);385 IrBasicBlock *result = allocate<IrBasicBlock>(1);
361 result->scope = scope;386 result->scope = scope;
...@@ -978,6 +1003,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertZero *) {...@@ -978,6 +1003,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertZero *) {
978 return IrInstructionIdAssertZero;1003 return IrInstructionIdAssertZero;
979}1004}
9801005
1006static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *) {
1007 return IrInstructionIdAssertNonNull;
1008}
1009
981template<typename T>1010template<typename T>
982static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {1011static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
983 T *special_instruction = allocate<T>(1);1012 T *special_instruction = allocate<T>(1);
...@@ -3012,6 +3041,19 @@ static IrInstruction *ir_build_assert_zero(IrAnalyze *ira, IrInstruction *source...@@ -3012,6 +3041,19 @@ static IrInstruction *ir_build_assert_zero(IrAnalyze *ira, IrInstruction *source
3012 return &instruction->base;3041 return &instruction->base;
3013}3042}
30143043
3044static IrInstruction *ir_build_assert_non_null(IrAnalyze *ira, IrInstruction *source_instruction,
3045 IrInstruction *target)
3046{
3047 IrInstructionAssertNonNull *instruction = ir_build_instruction<IrInstructionAssertNonNull>(&ira->new_irb,
3048 source_instruction->scope, source_instruction->source_node);
3049 instruction->base.value.type = ira->codegen->builtin_types.entry_void;
3050 instruction->target = target;
3051
3052 ir_ref_instruction(target, ira->new_irb.current_basic_block);
3053
3054 return &instruction->base;
3055}
3056
3015static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {3057static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
3016 results[ReturnKindUnconditional] = 0;3058 results[ReturnKindUnconditional] = 0;
3017 results[ReturnKindError] = 0;3059 results[ReturnKindError] = 0;
...@@ -5391,10 +5433,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5391,10 +5433,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5391 add_node_error(irb->codegen, variable_declaration->section_expr,5433 add_node_error(irb->codegen, variable_declaration->section_expr,
5392 buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol)));5434 buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol)));
5393 }5435 }
5394 if (variable_declaration->threadlocal_tok != nullptr) {5436
5395 add_token_error(irb->codegen, node->owner, variable_declaration->threadlocal_tok,5437 // Parser should ensure that this never happens
5396 buf_sprintf("function-local variable '%s' cannot be threadlocal", buf_ptr(variable_declaration->symbol)));5438 assert(variable_declaration->threadlocal_tok == nullptr);
5397 }
53985439
5399 // Temporarily set the name of the IrExecutable to the VariableDeclaration5440 // Temporarily set the name of the IrExecutable to the VariableDeclaration
5400 // so that the struct or enum from the init expression inherits the name.5441 // 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...@@ -5767,8 +5808,10 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
57675808
5768 IrInstruction *body_result = ir_gen_node(irb, body_node, &loop_scope->base);5809 IrInstruction *body_result = ir_gen_node(irb, body_node, &loop_scope->base);
57695810
5770 if (!instr_is_unreachable(body_result))5811 if (!instr_is_unreachable(body_result)) {
5812 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result));
5771 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));5813 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));
5814 }
57725815
5773 ir_set_cursor_at_end_and_append_block(irb, continue_block);5816 ir_set_cursor_at_end_and_append_block(irb, continue_block);
5774 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);5817 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,...@@ -7891,6 +7934,11 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction,
7891 return ir_add_error_node(ira, source_instruction->source_node, msg);7934 return ir_add_error_node(ira, source_instruction->source_node, msg);
7892}7935}
78937936
7937static void ir_assert(bool ok, IrInstruction *source_instruction) {
7938 if (ok) return;
7939 src_assert(ok, source_instruction->source_node);
7940}
7941
7894// This function takes a comptime ptr and makes the child const value conform to the type7942// This function takes a comptime ptr and makes the child const value conform to the type
7895// described by the pointer.7943// described by the pointer.
7896static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,7944static 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...@@ -7943,7 +7991,7 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
7943 return &codegen->invalid_instruction->value;7991 return &codegen->invalid_instruction->value;
7944 }7992 }
7945 }7993 }
7946 return &codegen->invalid_instruction->value;7994 zig_unreachable();
7947}7995}
79487996
7949static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {7997static 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) {...@@ -8088,6 +8136,8 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) {
8088 case 64:8136 case 64:
8089 dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);8137 dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);
8090 break;8138 break;
8139 case 80:
8140 zig_panic("TODO");
8091 case 128:8141 case 128:
8092 dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);8142 dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);
8093 break;8143 break;
...@@ -9904,6 +9954,7 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *t...@@ -9904,6 +9954,7 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *t
99049954
9905static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {9955static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {
9906 ConstGlobalRefs *global_refs = dest->global_refs;9956 ConstGlobalRefs *global_refs = dest->global_refs;
9957 assert(!same_global_refs || src->global_refs != nullptr);
9907 *dest = *src;9958 *dest = *src;
9908 if (!same_global_refs) {9959 if (!same_global_refs) {
9909 dest->global_refs = global_refs;9960 dest->global_refs = global_refs;
...@@ -9949,6 +10000,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -9949,6 +10000,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
9949 case 64:10000 case 64:
9950 const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);10001 const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);
9951 break;10002 break;
10003 case 80:
10004 zig_panic("TODO");
9952 case 128:10005 case 128:
9953 const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);10006 const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);
9954 break;10007 break;
...@@ -9978,6 +10031,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -9978,6 +10031,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
9978 case 64:10031 case 64:
9979 const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);10032 const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);
9980 break;10033 break;
10034 case 80:
10035 zig_panic("TODO");
9981 case 128:10036 case 128:
9982 const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);10037 const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);
9983 break;10038 break;
...@@ -10170,6 +10225,7 @@ static void ir_finish_bb(IrAnalyze *ira) {...@@ -10170,6 +10225,7 @@ static void ir_finish_bb(IrAnalyze *ira) {
10170 ira->instruction_index += 1;10225 ira->instruction_index += 1;
10171 }10226 }
1017210227
10228 size_t my_old_bb_index = ira->old_bb_index;
10173 ira->old_bb_index += 1;10229 ira->old_bb_index += 1;
1017410230
10175 bool need_repeat = true;10231 bool need_repeat = true;
...@@ -10180,7 +10236,7 @@ static void ir_finish_bb(IrAnalyze *ira) {...@@ -10180,7 +10236,7 @@ static void ir_finish_bb(IrAnalyze *ira) {
10180 ira->old_bb_index += 1;10236 ira->old_bb_index += 1;
10181 continue;10237 continue;
10182 }10238 }
10183 if (old_bb->other->instruction_list.length != 0) {10239 if (old_bb->other->instruction_list.length != 0 || ira->old_bb_index == my_old_bb_index) {
10184 ira->old_bb_index += 1;10240 ira->old_bb_index += 1;
10185 continue;10241 continue;
10186 }10242 }
...@@ -10205,16 +10261,18 @@ static IrInstruction *ir_unreach_error(IrAnalyze *ira) {...@@ -10205,16 +10261,18 @@ static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
1020510261
10206static bool ir_emit_backward_branch(IrAnalyze *ira, IrInstruction *source_instruction) {10262static bool ir_emit_backward_branch(IrAnalyze *ira, IrInstruction *source_instruction) {
10207 size_t *bbc = ira->new_irb.exec->backward_branch_count;10263 size_t *bbc = ira->new_irb.exec->backward_branch_count;
10208 size_t quota = ira->new_irb.exec->backward_branch_quota;10264 size_t *quota = ira->new_irb.exec->backward_branch_quota;
1020910265
10210 // If we're already over quota, we've already given an error message for this.10266 // If we're already over quota, we've already given an error message for this.
10211 if (*bbc > quota) {10267 if (*bbc > *quota) {
10268 assert(ira->codegen->errors.length > 0);
10212 return false;10269 return false;
10213 }10270 }
1021410271
10215 *bbc += 1;10272 *bbc += 1;
10216 if (*bbc > quota) {10273 if (*bbc > *quota) {
10217 ir_add_error(ira, source_instruction, buf_sprintf("evaluation exceeded %" ZIG_PRI_usize " backwards branches", quota));10274 ir_add_error(ira, source_instruction,
10275 buf_sprintf("evaluation exceeded %" ZIG_PRI_usize " backwards branches", *quota));
10218 return false;10276 return false;
10219 }10277 }
10220 return true;10278 return true;
...@@ -10249,6 +10307,12 @@ static IrInstruction *ir_const_bool(IrAnalyze *ira, IrInstruction *source_instru...@@ -10249,6 +10307,12 @@ static IrInstruction *ir_const_bool(IrAnalyze *ira, IrInstruction *source_instru
10249 return result;10307 return result;
10250}10308}
1025110309
10310static IrInstruction *ir_const_undef(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
10311 IrInstruction *result = ir_const(ira, source_instruction, ty);
10312 result->value.special = ConstValSpecialUndef;
10313 return result;
10314}
10315
10252static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) {10316static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) {
10253 return ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_void);10317 return ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_void);
10254}10318}
...@@ -10295,7 +10359,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un...@@ -10295,7 +10359,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
10295}10359}
1029610360
10297ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,10361ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
10298 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,10362 ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
10299 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,10363 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
10300 IrExecutable *parent_exec, AstNode *expected_type_source_node)10364 IrExecutable *parent_exec, AstNode *expected_type_source_node)
10301{10365{
...@@ -10317,7 +10381,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod...@@ -10317,7 +10381,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
1031710381
10318 if (codegen->verbose_ir) {10382 if (codegen->verbose_ir) {
10319 fprintf(stderr, "\nSource: ");10383 fprintf(stderr, "\nSource: ");
10320 ast_render(codegen, stderr, node, 4);10384 ast_render(stderr, node, 4);
10321 fprintf(stderr, "\n{ // (IR)\n");10385 fprintf(stderr, "\n{ // (IR)\n");
10322 ir_print(codegen, stderr, ir_executable, 2);10386 ir_print(codegen, stderr, ir_executable, 2);
10323 fprintf(stderr, "}\n");10387 fprintf(stderr, "}\n");
...@@ -10562,19 +10626,34 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so...@@ -10562,19 +10626,34 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
10562 assert(instr_is_comptime(value));10626 assert(instr_is_comptime(value));
1056310627
10564 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);10628 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
10565 assert(val);10629 assert(val != nullptr);
1056610630
10567 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);10631 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10568 const_instruction->base.value.special = ConstValSpecialStatic;10632 result->value.special = ConstValSpecialStatic;
10569 if (get_codegen_ptr_type(wanted_type) != nullptr) {10633 if (get_codegen_ptr_type(wanted_type) != nullptr) {
10570 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull;10634 result->value.data.x_ptr.special = ConstPtrSpecialNull;
10571 } else if (is_opt_err_set(wanted_type)) {10635 } else if (is_opt_err_set(wanted_type)) {
10572 const_instruction->base.value.data.x_err_set = nullptr;10636 result->value.data.x_err_set = nullptr;
10573 } else {10637 } else {
10574 const_instruction->base.value.data.x_optional = nullptr;10638 result->value.data.x_optional = nullptr;
10575 }10639 }
10576 const_instruction->base.value.type = wanted_type;10640 return result;
10577 return &const_instruction->base;10641}
10642
10643static IrInstruction *ir_analyze_null_to_c_pointer(IrAnalyze *ira, IrInstruction *source_instr,
10644 IrInstruction *value, ZigType *wanted_type)
10645{
10646 assert(wanted_type->id == ZigTypeIdPointer);
10647 assert(wanted_type->data.pointer.ptr_len == PtrLenC);
10648 assert(instr_is_comptime(value));
10649
10650 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
10651 assert(val != nullptr);
10652
10653 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10654 result->value.data.x_ptr.special = ConstPtrSpecialNull;
10655 result->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
10656 return result;
10578}10657}
1057910658
10580static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,10659static 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...@@ -11576,6 +11655,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11576 return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);11655 return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
11577 }11656 }
1157811657
11658 // cast from null literal to C pointer
11659 if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC &&
11660 actual_type->id == ZigTypeIdNull)
11661 {
11662 return ir_analyze_null_to_c_pointer(ira, source_instr, value, wanted_type);
11663 }
11664
11579 // cast from [N]T to E![]const T11665 // cast from [N]T to E![]const T
11580 if (wanted_type->id == ZigTypeIdErrorUnion &&11666 if (wanted_type->id == ZigTypeIdErrorUnion &&
11581 is_slice(wanted_type->data.error_union.payload_type) &&11667 is_slice(wanted_type->data.error_union.payload_type) &&
...@@ -12193,14 +12279,12 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -12193,14 +12279,12 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1219312279
12194 IrBinOp op_id = bin_op_instruction->op_id;12280 IrBinOp op_id = bin_op_instruction->op_id;
12195 bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);12281 bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
12196 if (is_equality_cmp &&12282 if (is_equality_cmp && op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull) {
12283 return ir_const_bool(ira, &bin_op_instruction->base, (op_id == IrBinOpCmpEq));
12284 } else if (is_equality_cmp &&
12197 ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdOptional) ||12285 ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdOptional) ||
12198 (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdOptional) ||12286 (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdOptional)))
12199 (op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull)))
12200 {12287 {
12201 if (op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull) {
12202 return ir_const_bool(ira, &bin_op_instruction->base, (op_id == IrBinOpCmpEq));
12203 }
12204 IrInstruction *maybe_op;12288 IrInstruction *maybe_op;
12205 if (op1->value.type->id == ZigTypeIdNull) {12289 if (op1->value.type->id == ZigTypeIdNull) {
12206 maybe_op = op2;12290 maybe_op = op2;
...@@ -12222,6 +12306,44 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -12222,6 +12306,44 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
12222 source_node, maybe_op);12306 source_node, maybe_op);
12223 is_non_null->value.type = ira->codegen->builtin_types.entry_bool;12307 is_non_null->value.type = ira->codegen->builtin_types.entry_bool;
1222412308
12309 if (op_id == IrBinOpCmpEq) {
12310 IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope,
12311 bin_op_instruction->base.source_node, is_non_null);
12312 result->value.type = ira->codegen->builtin_types.entry_bool;
12313 return result;
12314 } else {
12315 return is_non_null;
12316 }
12317 } else if (is_equality_cmp &&
12318 ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdPointer &&
12319 op2->value.type->data.pointer.ptr_len == PtrLenC) ||
12320 (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdPointer &&
12321 op1->value.type->data.pointer.ptr_len == PtrLenC)))
12322 {
12323 IrInstruction *c_ptr_op;
12324 if (op1->value.type->id == ZigTypeIdNull) {
12325 c_ptr_op = op2;
12326 } else if (op2->value.type->id == ZigTypeIdNull) {
12327 c_ptr_op = op1;
12328 } else {
12329 zig_unreachable();
12330 }
12331 if (instr_is_comptime(c_ptr_op)) {
12332 ConstExprValue *c_ptr_val = ir_resolve_const(ira, c_ptr_op, UndefOk);
12333 if (!c_ptr_val)
12334 return ira->codegen->invalid_instruction;
12335 if (c_ptr_val->special == ConstValSpecialUndef)
12336 return ir_const_undef(ira, &bin_op_instruction->base, ira->codegen->builtin_types.entry_bool);
12337 bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull ||
12338 (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
12339 c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0);
12340 bool bool_result = (op_id == IrBinOpCmpEq) ? is_null : !is_null;
12341 return ir_const_bool(ira, &bin_op_instruction->base, bool_result);
12342 }
12343 IrInstruction *is_non_null = ir_build_test_nonnull(&ira->new_irb, bin_op_instruction->base.scope,
12344 source_node, c_ptr_op);
12345 is_non_null->value.type = ira->codegen->builtin_types.entry_bool;
12346
12225 if (op_id == IrBinOpCmpEq) {12347 if (op_id == IrBinOpCmpEq) {
12226 IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope,12348 IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope,
12227 bin_op_instruction->base.source_node, is_non_null);12349 bin_op_instruction->base.source_node, is_non_null);
...@@ -12231,8 +12353,9 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -12231,8 +12353,9 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
12231 return is_non_null;12353 return is_non_null;
12232 }12354 }
12233 } else if (op1->value.type->id == ZigTypeIdNull || op2->value.type->id == ZigTypeIdNull) {12355 } else if (op1->value.type->id == ZigTypeIdNull || op2->value.type->id == ZigTypeIdNull) {
12234 ir_add_error_node(ira, source_node, buf_sprintf("only optionals (not '%s') can compare to null",12356 ZigType *non_null_type = (op1->value.type->id == ZigTypeIdNull) ? op2->value.type : op1->value.type;
12235 buf_ptr(&(op1->value.type->id == ZigTypeIdNull ? op2->value.type->name : op1->value.type->name))));12357 ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null",
12358 buf_ptr(&non_null_type->name)));
12236 return ira->codegen->invalid_instruction;12359 return ira->codegen->invalid_instruction;
12237 }12360 }
1223812361
...@@ -13828,11 +13951,12 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i...@@ -13828,11 +13951,12 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
13828 zig_unreachable();13951 zig_unreachable();
13829}13952}
1383013953
13831static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry, ZigType *fn_type,13954static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry,
13832 IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst)13955 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
13956 IrInstruction *async_allocator_inst)
13833{13957{
13834 Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);13958 Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);
13835 assert(async_allocator_inst->value.type->id == ZigTypeIdPointer);13959 ir_assert(async_allocator_inst->value.type->id == ZigTypeIdPointer, &call_instruction->base);
13836 ZigType *container_type = async_allocator_inst->value.type->data.pointer.child_type;13960 ZigType *container_type = async_allocator_inst->value.type->data.pointer.child_type;
13837 IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, realloc_field_name, &call_instruction->base,13961 IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, realloc_field_name, &call_instruction->base,
13838 async_allocator_inst, container_type);13962 async_allocator_inst, container_type);
...@@ -13840,7 +13964,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c...@@ -13840,7 +13964,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c
13840 return ira->codegen->invalid_instruction;13964 return ira->codegen->invalid_instruction;
13841 }13965 }
13842 ZigType *ptr_to_realloc_fn_type = field_ptr_inst->value.type;13966 ZigType *ptr_to_realloc_fn_type = field_ptr_inst->value.type;
13843 assert(ptr_to_realloc_fn_type->id == ZigTypeIdPointer);13967 ir_assert(ptr_to_realloc_fn_type->id == ZigTypeIdPointer, &call_instruction->base);
1384413968
13845 ZigType *realloc_fn_type = ptr_to_realloc_fn_type->data.pointer.child_type;13969 ZigType *realloc_fn_type = ptr_to_realloc_fn_type->data.pointer.child_type;
13846 if (realloc_fn_type->id != ZigTypeIdFn) {13970 if (realloc_fn_type->id != ZigTypeIdFn) {
...@@ -13875,7 +13999,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node...@@ -13875,7 +13999,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
13875 IrInstruction *casted_arg;13999 IrInstruction *casted_arg;
13876 if (param_decl_node->data.param_decl.var_token == nullptr) {14000 if (param_decl_node->data.param_decl.var_token == nullptr) {
13877 AstNode *param_type_node = param_decl_node->data.param_decl.type;14001 AstNode *param_type_node = param_decl_node->data.param_decl.type;
13878 ZigType *param_type = analyze_type_expr(ira->codegen, *exec_scope, param_type_node);14002 ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node);
13879 if (type_is_invalid(param_type))14003 if (type_is_invalid(param_type))
13880 return false;14004 return false;
1388114005
...@@ -13915,7 +14039,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -13915,7 +14039,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
13915 } else {14039 } else {
13916 if (param_decl_node->data.param_decl.var_token == nullptr) {14040 if (param_decl_node->data.param_decl.var_token == nullptr) {
13917 AstNode *param_type_node = param_decl_node->data.param_decl.type;14041 AstNode *param_type_node = param_decl_node->data.param_decl.type;
13918 ZigType *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node);14042 ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node);
13919 if (type_is_invalid(param_type))14043 if (type_is_invalid(param_type))
13920 return false;14044 return false;
1392114045
...@@ -14296,7 +14420,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14296,7 +14420,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14296 }14420 }
1429714421
14298 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;14422 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
14299 ZigType *specified_return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node);14423 ZigType *specified_return_type = ir_analyze_type_expr(ira, exec_scope, return_type_node);
14300 if (type_is_invalid(specified_return_type))14424 if (type_is_invalid(specified_return_type))
14301 return ira->codegen->invalid_instruction;14425 return ira->codegen->invalid_instruction;
14302 ZigType *return_type;14426 ZigType *return_type;
...@@ -14532,7 +14656,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14532,7 +14656,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1453214656
14533 if (fn_proto_node->data.fn_proto.return_var_token == nullptr) {14657 if (fn_proto_node->data.fn_proto.return_var_token == nullptr) {
14534 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;14658 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
14535 ZigType *specified_return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node);14659 ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node);
14536 if (type_is_invalid(specified_return_type))14660 if (type_is_invalid(specified_return_type))
14537 return ira->codegen->invalid_instruction;14661 return ira->codegen->invalid_instruction;
14538 if (fn_proto_node->data.fn_proto.auto_err_set) {14662 if (fn_proto_node->data.fn_proto.auto_err_set) {
...@@ -14559,7 +14683,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14559,7 +14683,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14559 if (call_instruction->is_async) {14683 if (call_instruction->is_async) {
14560 AstNode *async_allocator_type_node = fn_proto_node->data.fn_proto.async_allocator_type;14684 AstNode *async_allocator_type_node = fn_proto_node->data.fn_proto.async_allocator_type;
14561 if (async_allocator_type_node != nullptr) {14685 if (async_allocator_type_node != nullptr) {
14562 ZigType *async_allocator_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, async_allocator_type_node);14686 ZigType *async_allocator_type = ir_analyze_type_expr(ira, impl_fn->child_scope, async_allocator_type_node);
14563 if (type_is_invalid(async_allocator_type))14687 if (type_is_invalid(async_allocator_type))
14564 return ira->codegen->invalid_instruction;14688 return ira->codegen->invalid_instruction;
14565 inst_fn_type_id.async_allocator_type = async_allocator_type;14689 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,...@@ -15822,7 +15946,7 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,
15822 }15946 }
15823 }15947 }
1582415948
15825 if (!is_libc && !ira->codegen->have_pic && !ira->codegen->reported_bad_link_libc_error) {15949 if (!is_libc && !target_is_wasm(ira->codegen->zig_target) && !ira->codegen->have_pic && !ira->codegen->reported_bad_link_libc_error) {
15826 ErrorMsg *msg = ir_add_error_node(ira, source_node,15950 ErrorMsg *msg = ir_add_error_node(ira, source_node,
15827 buf_sprintf("dependency on dynamic library '%s' requires enabling Position Independent Code",15951 buf_sprintf("dependency on dynamic library '%s' requires enabling Position Independent Code",
15828 buf_ptr(lib_name)));15952 buf_ptr(lib_name)));
...@@ -16696,16 +16820,16 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -16696,16 +16820,16 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
16696 case ZigTypeIdUnreachable:16820 case ZigTypeIdUnreachable:
16697 case ZigTypeIdUndefined:16821 case ZigTypeIdUndefined:
16698 case ZigTypeIdNull:16822 case ZigTypeIdNull:
16699 case ZigTypeIdComptimeFloat:
16700 case ZigTypeIdComptimeInt:
16701 case ZigTypeIdEnumLiteral:
16702 case ZigTypeIdBoundFn:16823 case ZigTypeIdBoundFn:
16703 case ZigTypeIdMetaType:
16704 case ZigTypeIdArgTuple:16824 case ZigTypeIdArgTuple:
16705 case ZigTypeIdOpaque:16825 case ZigTypeIdOpaque:
16706 ir_add_error_node(ira, size_of_instruction->base.source_node,16826 ir_add_error_node(ira, type_value->source_node,
16707 buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));16827 buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
16708 return ira->codegen->invalid_instruction;16828 return ira->codegen->invalid_instruction;
16829 case ZigTypeIdMetaType:
16830 case ZigTypeIdEnumLiteral:
16831 case ZigTypeIdComptimeFloat:
16832 case ZigTypeIdComptimeInt:
16709 case ZigTypeIdVoid:16833 case ZigTypeIdVoid:
16710 case ZigTypeIdBool:16834 case ZigTypeIdBool:
16711 case ZigTypeIdInt:16835 case ZigTypeIdInt:
...@@ -16732,11 +16856,30 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -16732,11 +16856,30 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
16732static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {16856static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
16733 ZigType *type_entry = value->value.type;16857 ZigType *type_entry = value->value.type;
1673416858
16735 if (type_entry->id == ZigTypeIdOptional) {16859 if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.allow_zero) {
16736 if (instr_is_comptime(value)) {16860 if (instr_is_comptime(value)) {
16737 ConstExprValue *maybe_val = ir_resolve_const(ira, value, UndefBad);16861 ConstExprValue *c_ptr_val = ir_resolve_const(ira, value, UndefOk);
16738 if (!maybe_val)16862 if (c_ptr_val == nullptr)
16863 return ira->codegen->invalid_instruction;
16864 if (c_ptr_val->special == ConstValSpecialUndef)
16865 return ir_const_undef(ira, source_inst, ira->codegen->builtin_types.entry_bool);
16866 bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull ||
16867 (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
16868 c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0);
16869 return ir_const_bool(ira, source_inst, !is_null);
16870 }
16871
16872 IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,
16873 source_inst->scope, source_inst->source_node, value);
16874 result->value.type = ira->codegen->builtin_types.entry_bool;
16875 return result;
16876 } else if (type_entry->id == ZigTypeIdOptional) {
16877 if (instr_is_comptime(value)) {
16878 ConstExprValue *maybe_val = ir_resolve_const(ira, value, UndefOk);
16879 if (maybe_val == nullptr)
16739 return ira->codegen->invalid_instruction;16880 return ira->codegen->invalid_instruction;
16881 if (maybe_val->special == ConstValSpecialUndef)
16882 return ir_const_undef(ira, source_inst, ira->codegen->builtin_types.entry_bool);
1674016883
16741 return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val));16884 return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val));
16742 }16885 }
...@@ -16770,6 +16913,32 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr...@@ -16770,6 +16913,32 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
16770 if (type_is_invalid(type_entry))16913 if (type_is_invalid(type_entry))
16771 return ira->codegen->invalid_instruction;16914 return ira->codegen->invalid_instruction;
1677216915
16916 if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.ptr_len == PtrLenC) {
16917 if (instr_is_comptime(base_ptr)) {
16918 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
16919 if (!val)
16920 return ira->codegen->invalid_instruction;
16921 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
16922 ConstExprValue *c_ptr_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
16923 if (c_ptr_val == nullptr)
16924 return ira->codegen->invalid_instruction;
16925 bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull ||
16926 (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
16927 c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0);
16928 if (is_null) {
16929 ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
16930 return ira->codegen->invalid_instruction;
16931 }
16932 return base_ptr;
16933 }
16934 }
16935 if (!safety_check_on)
16936 return base_ptr;
16937 IrInstruction *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr);
16938 ir_build_assert_non_null(ira, source_instr, c_ptr_val);
16939 return base_ptr;
16940 }
16941
16773 if (type_entry->id != ZigTypeIdOptional) {16942 if (type_entry->id != ZigTypeIdOptional) {
16774 ir_add_error_node(ira, base_ptr->source_node,16943 ir_add_error_node(ira, base_ptr->source_node,
16775 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));16944 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...@@ -16784,11 +16953,11 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
16784 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);16953 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
16785 if (!val)16954 if (!val)
16786 return ira->codegen->invalid_instruction;16955 return ira->codegen->invalid_instruction;
16787 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
16788 if (maybe_val == nullptr)
16789 return ira->codegen->invalid_instruction;
16790
16791 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {16956 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
16957 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
16958 if (maybe_val == nullptr)
16959 return ira->codegen->invalid_instruction;
16960
16792 if (optional_value_is_null(maybe_val)) {16961 if (optional_value_is_null(maybe_val)) {
16793 ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));16962 ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
16794 return ira->codegen->invalid_instruction;16963 return ira->codegen->invalid_instruction;
...@@ -17435,6 +17604,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -17435,6 +17604,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
17435 ConstExprValue const_val = {};17604 ConstExprValue const_val = {};
17436 const_val.special = ConstValSpecialStatic;17605 const_val.special = ConstValSpecialStatic;
17437 const_val.type = container_type;17606 const_val.type = container_type;
17607 // const_val.global_refs = allocate<ConstGlobalRefs>(1);
17438 const_val.data.x_struct.fields = create_const_vals(actual_field_count);17608 const_val.data.x_struct.fields = create_const_vals(actual_field_count);
17439 for (size_t i = 0; i < instr_field_count; i += 1) {17609 for (size_t i = 0; i < instr_field_count; i += 1) {
17440 IrInstructionContainerInitFieldsField *field = &fields[i];17610 IrInstructionContainerInitFieldsField *field = &fields[i];
...@@ -17498,7 +17668,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -17498,7 +17668,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
17498 if (const_val.special == ConstValSpecialStatic) {17668 if (const_val.special == ConstValSpecialStatic) {
17499 IrInstruction *result = ir_const(ira, instruction, nullptr);17669 IrInstruction *result = ir_const(ira, instruction, nullptr);
17500 ConstExprValue *out_val = &result->value;17670 ConstExprValue *out_val = &result->value;
17501 copy_const_val(out_val, &const_val, true);17671 copy_const_val(out_val, &const_val, false);
17502 out_val->type = container_type;17672 out_val->type = container_type;
1750317673
17504 for (size_t i = 0; i < instr_field_count; i += 1) {17674 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,...@@ -17570,6 +17740,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
17570 ConstExprValue const_val = {};17740 ConstExprValue const_val = {};
17571 const_val.special = ConstValSpecialStatic;17741 const_val.special = ConstValSpecialStatic;
17572 const_val.type = fixed_size_array_type;17742 const_val.type = fixed_size_array_type;
17743 // const_val.global_refs = allocate<ConstGlobalRefs>(1);
17573 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);17744 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
1757417745
17575 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);17746 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,...@@ -17606,8 +17777,6 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
17606 if (const_val.special == ConstValSpecialStatic) {17777 if (const_val.special == ConstValSpecialStatic) {
17607 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);17778 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
17608 ConstExprValue *out_val = &result->value;17779 ConstExprValue *out_val = &result->value;
17609 // Make sure to pass same_global_refs=false here in order not to
17610 // zero the global_refs field for `result` (#1608)
17611 copy_const_val(out_val, &const_val, false);17780 copy_const_val(out_val, &const_val, false);
17612 result->value.type = fixed_size_array_type;17781 result->value.type = fixed_size_array_type;
17613 for (size_t i = 0; i < elem_count; i += 1) {17782 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...@@ -18961,8 +19130,8 @@ static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ir
18961 if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))19130 if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))
18962 return ira->codegen->invalid_instruction;19131 return ira->codegen->invalid_instruction;
1896319132
18964 if (new_quota > ira->new_irb.exec->backward_branch_quota) {19133 if (new_quota > *ira->new_irb.exec->backward_branch_quota) {
18965 ira->new_irb.exec->backward_branch_quota = new_quota;19134 *ira->new_irb.exec->backward_branch_quota = new_quota;
18966 }19135 }
1896719136
18968 return ir_const_void(ira, &instruction->base);19137 return ir_const_void(ira, &instruction->base);
...@@ -19059,24 +19228,50 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -19059,24 +19228,50 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
19059 fprintf(stderr, "@cImport source: %s\n", buf_ptr(&tmp_c_file_path));19228 fprintf(stderr, "@cImport source: %s\n", buf_ptr(&tmp_c_file_path));
19060 }19229 }
1906119230
19062 ZigList<ErrorMsg *> errors = {0};
19063
19064 Buf *tmp_dep_file = buf_sprintf("%s.d", buf_ptr(&tmp_c_file_path));19231 Buf *tmp_dep_file = buf_sprintf("%s.d", buf_ptr(&tmp_c_file_path));
19232
19233 ZigList<const char *> clang_argv = {0};
19234
19235 add_cc_args(ira->codegen, clang_argv, buf_ptr(tmp_dep_file), true);
19236
19237 clang_argv.append(buf_ptr(&tmp_c_file_path));
19238
19239 if (ira->codegen->verbose_cc) {
19240 fprintf(stderr, "clang");
19241 for (size_t i = 0; i < clang_argv.length; i += 1) {
19242 fprintf(stderr, " %s", clang_argv.at(i));
19243 }
19244 fprintf(stderr, "\n");
19245 }
19246
19247 clang_argv.append(nullptr); // to make the [start...end] argument work
19248
19065 AstNode *root_node;19249 AstNode *root_node;
19066 if ((err = parse_h_file(&root_node, &errors, buf_ptr(&tmp_c_file_path), ira->codegen, tmp_dep_file))) {19250 Stage2ErrorMsg *errors_ptr;
19251 size_t errors_len;
19252
19253 const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir);
19254
19255 if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len,
19256 &clang_argv.at(0), &clang_argv.last(), Stage2TranslateModeImport, resources_path)))
19257 {
19067 if (err != ErrorCCompileErrors) {19258 if (err != ErrorCCompileErrors) {
19068 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));19259 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
19069 return ira->codegen->invalid_instruction;19260 return ira->codegen->invalid_instruction;
19070 }19261 }
19071 assert(errors.length > 0);
1907219262
19073 ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));19263 ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));
19074 if (ira->codegen->libc_link_lib == nullptr) {19264 if (ira->codegen->libc_link_lib == nullptr) {
19075 add_error_note(ira->codegen, parent_err_msg, node,19265 add_error_note(ira->codegen, parent_err_msg, node,
19076 buf_sprintf("libc headers not available; compilation does not link against libc"));19266 buf_sprintf("libc headers not available; compilation does not link against libc"));
19077 }19267 }
19078 for (size_t i = 0; i < errors.length; i += 1) {19268 for (size_t i = 0; i < errors_len; i += 1) {
19079 ErrorMsg *err_msg = errors.at(i);19269 Stage2ErrorMsg *clang_err = &errors_ptr[i];
19270 ErrorMsg *err_msg = err_msg_create_with_offset(
19271 clang_err->filename_ptr ?
19272 buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(),
19273 clang_err->line, clang_err->column, clang_err->offset, clang_err->source,
19274 buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len));
19080 err_msg_add_note(parent_err_msg, err_msg);19275 err_msg_add_note(parent_err_msg, err_msg);
19081 }19276 }
1908219277
...@@ -19106,7 +19301,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -19106,7 +19301,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
19106 buf_sprintf("C import failed: unable to open output file: %s", strerror(errno)));19301 buf_sprintf("C import failed: unable to open output file: %s", strerror(errno)));
19107 return ira->codegen->invalid_instruction;19302 return ira->codegen->invalid_instruction;
19108 }19303 }
19109 ast_render(ira->codegen, out_file, root_node, 4);19304 ast_render(out_file, root_node, 4);
19110 if (fclose(out_file) != 0) {19305 if (fclose(out_file) != 0) {
19111 ir_add_error_node(ira, node,19306 ir_add_error_node(ira, node,
19112 buf_sprintf("C import failed: unable to write to output file: %s", strerror(errno)));19307 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,...@@ -21026,18 +21221,24 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
21026 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {21221 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
21027 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];21222 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
2102821223
21029 IrInstruction *start_value = range->start->child;21224 IrInstruction *start_value_uncasted = range->start->child;
21225 if (type_is_invalid(start_value_uncasted->value.type))
21226 return ira->codegen->invalid_instruction;
21227 IrInstruction *start_value = ir_implicit_cast(ira, start_value_uncasted, switch_type);
21030 if (type_is_invalid(start_value->value.type))21228 if (type_is_invalid(start_value->value.type))
21031 return ira->codegen->invalid_instruction;21229 return ira->codegen->invalid_instruction;
2103221230
21033 IrInstruction *end_value = range->end->child;21231 IrInstruction *end_value_uncasted = range->end->child;
21232 if (type_is_invalid(end_value_uncasted->value.type))
21233 return ira->codegen->invalid_instruction;
21234 IrInstruction *end_value = ir_implicit_cast(ira, end_value_uncasted, switch_type);
21034 if (type_is_invalid(end_value->value.type))21235 if (type_is_invalid(end_value->value.type))
21035 return ira->codegen->invalid_instruction;21236 return ira->codegen->invalid_instruction;
2103621237
21037 assert(start_value->value.type->id == ZigTypeIdErrorSet);21238 ir_assert(start_value->value.type->id == ZigTypeIdErrorSet, &instruction->base);
21038 uint32_t start_index = start_value->value.data.x_err_set->value;21239 uint32_t start_index = start_value->value.data.x_err_set->value;
2103921240
21040 assert(end_value->value.type->id == ZigTypeIdErrorSet);21241 ir_assert(end_value->value.type->id == ZigTypeIdErrorSet, &instruction->base);
21041 uint32_t end_index = end_value->value.data.x_err_set->value;21242 uint32_t end_index = end_value->value.data.x_err_set->value;
2104221243
21043 if (start_index != end_index) {21244 if (start_index != end_index) {
...@@ -21260,7 +21461,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -21260,7 +21461,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
21260 }21461 }
2126121462
21262 IrInstruction *result = ir_const(ira, target, result_type);21463 IrInstruction *result = ir_const(ira, target, result_type);
21263 copy_const_val(&result->value, val, false);21464 copy_const_val(&result->value, val, true);
21264 result->value.type = result_type;21465 result->value.type = result_type;
21265 return result;21466 return result;
21266 }21467 }
...@@ -21330,7 +21531,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -21330,7 +21531,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
21330 }21531 }
2133121532
21332 IrInstruction *result = ir_const(ira, source_instr, dest_type);21533 IrInstruction *result = ir_const(ira, source_instr, dest_type);
21333 copy_const_val(&result->value, val, false);21534 copy_const_val(&result->value, val, true);
21334 result->value.type = dest_type;21535 result->value.type = dest_type;
2133521536
21336 // Keep the bigger alignment, it can only help-21537 // Keep the bigger alignment, it can only help-
...@@ -21562,7 +21763,7 @@ static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNod...@@ -21562,7 +21763,7 @@ static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNod
2156221763
21563static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {21764static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
21564 Error err;21765 Error err;
21565 assert(val->special == ConstValSpecialStatic);21766 src_assert(val->special == ConstValSpecialStatic, source_node);
21566 switch (val->type->id) {21767 switch (val->type->id) {
21567 case ZigTypeIdInvalid:21768 case ZigTypeIdInvalid:
21568 case ZigTypeIdMetaType:21769 case ZigTypeIdMetaType:
...@@ -21612,7 +21813,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -21612,7 +21813,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
21612 zig_panic("TODO buf_read_value_bytes enum packed");21813 zig_panic("TODO buf_read_value_bytes enum packed");
21613 case ContainerLayoutExtern: {21814 case ContainerLayoutExtern: {
21614 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;21815 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
21615 assert(tag_int_type->id == ZigTypeIdInt);21816 src_assert(tag_int_type->id == ZigTypeIdInt, source_node);
21616 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,21817 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
21617 codegen->is_big_endian, tag_int_type->data.integral.is_signed);21818 codegen->is_big_endian, tag_int_type->data.integral.is_signed);
21618 return ErrorNone;21819 return ErrorNone;
...@@ -21667,7 +21868,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -21667,7 +21868,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
21667 bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false);21868 bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false);
21668 while (src_i < src_field_count) {21869 while (src_i < src_field_count) {
21669 TypeStructField *field = &val->type->data.structure.fields[src_i];21870 TypeStructField *field = &val->type->data.structure.fields[src_i];
21670 assert(field->gen_index != SIZE_MAX);21871 src_assert(field->gen_index != SIZE_MAX, source_node);
21671 if (field->gen_index != gen_i)21872 if (field->gen_index != gen_i)
21672 break;21873 break;
21673 ConstExprValue *field_val = &val->data.x_struct.fields[src_i];21874 ConstExprValue *field_val = &val->data.x_struct.fields[src_i];
...@@ -21743,10 +21944,10 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -21743,10 +21944,10 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_
21743 Error err;21944 Error err;
2174421945
21745 ZigType *src_type = value->value.type;21946 ZigType *src_type = value->value.type;
21746 assert(get_codegen_ptr_type(src_type) == nullptr);21947 ir_assert(get_codegen_ptr_type(src_type) == nullptr, source_instr);
21747 assert(type_can_bit_cast(src_type));21948 ir_assert(type_can_bit_cast(src_type), source_instr);
21748 assert(get_codegen_ptr_type(dest_type) == nullptr);21949 ir_assert(get_codegen_ptr_type(dest_type) == nullptr, source_instr);
21749 assert(type_can_bit_cast(dest_type));21950 ir_assert(type_can_bit_cast(dest_type), source_instr);
2175021951
21751 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))21952 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
21752 return ira->codegen->invalid_instruction;21953 return ira->codegen->invalid_instruction;
...@@ -21836,8 +22037,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -21836,8 +22037,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
21836static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,22037static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
21837 ZigType *ptr_type)22038 ZigType *ptr_type)
21838{22039{
21839 assert(get_src_ptr_type(ptr_type) != nullptr);22040 ir_assert(get_src_ptr_type(ptr_type) != nullptr, source_instr);
21840 assert(type_has_bits(ptr_type));22041 ir_assert(type_has_bits(ptr_type), source_instr);
2184122042
21842 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);22043 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
21843 if (type_is_invalid(casted_int->value.type))22044 if (type_is_invalid(casted_int->value.type))
...@@ -21936,7 +22137,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,...@@ -21936,7 +22137,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
21936 case TldIdFn: {22137 case TldIdFn: {
21937 TldFn *tld_fn = (TldFn *)tld;22138 TldFn *tld_fn = (TldFn *)tld;
21938 ZigFn *fn_entry = tld_fn->fn_entry;22139 ZigFn *fn_entry = tld_fn->fn_entry;
21939 assert(fn_entry->type_entry);22140 ir_assert(fn_entry->type_entry, &instruction->base);
2194022141
21941 if (tld_fn->extern_lib_name != nullptr) {22142 if (tld_fn->extern_lib_name != nullptr) {
21942 add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, instruction->base.source_node);22143 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...@@ -22134,7 +22335,7 @@ static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruct
22134 ZigType *result_type = fn_type_id->param_info[arg_index].type;22335 ZigType *result_type = fn_type_id->param_info[arg_index].type;
22135 if (result_type == nullptr) {22336 if (result_type == nullptr) {
22136 // Args are only unresolved if our function is generic.22337 // Args are only unresolved if our function is generic.
22137 assert(fn_type->data.fn.is_generic);22338 ir_assert(fn_type->data.fn.is_generic, &instruction->base);
2213822339
22139 ir_add_error(ira, arg_index_inst,22340 ir_add_error(ira, arg_index_inst,
22140 buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic",22341 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...@@ -22220,7 +22421,7 @@ static IrInstruction *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstru
22220 return ira->codegen->invalid_instruction;22421 return ira->codegen->invalid_instruction;
2222122422
22222 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);22423 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
22223 assert(fn_entry != nullptr);22424 ir_assert(fn_entry != nullptr, &instruction->base);
22224 IrInstruction *result = ir_build_coro_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node,22425 IrInstruction *result = ir_build_coro_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
22225 coro_id, coro_mem_ptr);22426 coro_id, coro_mem_ptr);
22226 result->value.type = get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type);22427 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...@@ -22458,7 +22659,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr
22458 }22659 }
2245922660
22460 if (ordering == AtomicOrderRelease || ordering == AtomicOrderAcqRel) {22661 if (ordering == AtomicOrderRelease || ordering == AtomicOrderAcqRel) {
22461 assert(instruction->ordering != nullptr);22662 ir_assert(instruction->ordering != nullptr, &instruction->base);
22462 ir_add_error(ira, instruction->ordering,22663 ir_add_error(ira, instruction->ordering,
22463 buf_sprintf("@atomicLoad atomic ordering must not be Release or AcqRel"));22664 buf_sprintf("@atomicLoad atomic ordering must not be Release or AcqRel"));
22464 return ira->codegen->invalid_instruction;22665 return ira->codegen->invalid_instruction;
...@@ -22466,7 +22667,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr...@@ -22466,7 +22667,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr
2246622667
22467 if (instr_is_comptime(casted_ptr)) {22668 if (instr_is_comptime(casted_ptr)) {
22468 IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr);22669 IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr);
22469 assert(result->value.type != nullptr);22670 ir_assert(result->value.type != nullptr, &instruction->base);
22470 return result;22671 return result;
22471 }22672 }
2247222673
...@@ -22496,7 +22697,7 @@ static IrInstruction *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, I...@@ -22496,7 +22697,7 @@ static IrInstruction *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, I
22496 return ira->codegen->invalid_instruction;22697 return ira->codegen->invalid_instruction;
2249722698
22498 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);22699 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
22499 assert(fn_entry != nullptr);22700 ir_assert(fn_entry != nullptr, &instruction->base);
2250022701
22501 if (type_can_fail(promise_result_type)) {22702 if (type_can_fail(promise_result_type)) {
22502 fn_entry->calls_or_awaits_errorable_fn = true;22703 fn_entry->calls_or_awaits_errorable_fn = true;
...@@ -22512,9 +22713,9 @@ static IrInstruction *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ira...@@ -22512,9 +22713,9 @@ static IrInstruction *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ira
22512 if (type_is_invalid(coro_promise_ptr->value.type))22713 if (type_is_invalid(coro_promise_ptr->value.type))
22513 return ira->codegen->invalid_instruction;22714 return ira->codegen->invalid_instruction;
2251422715
22515 assert(coro_promise_ptr->value.type->id == ZigTypeIdPointer);22716 ir_assert(coro_promise_ptr->value.type->id == ZigTypeIdPointer, &instruction->base);
22516 ZigType *promise_frame_type = coro_promise_ptr->value.type->data.pointer.child_type;22717 ZigType *promise_frame_type = coro_promise_ptr->value.type->data.pointer.child_type;
22517 assert(promise_frame_type->id == ZigTypeIdStruct);22718 ir_assert(promise_frame_type->id == ZigTypeIdStruct, &instruction->base);
22518 ZigType *promise_result_type = promise_frame_type->data.structure.fields[1].type_entry;22719 ZigType *promise_result_type = promise_frame_type->data.structure.fields[1].type_entry;
2251922720
22520 if (!type_can_fail(promise_result_type)) {22721 if (!type_can_fail(promise_result_type)) {
...@@ -22606,7 +22807,7 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS...@@ -22606,7 +22807,7 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS
22606 return result;22807 return result;
22607 }22808 }
2260822809
22609 assert(float_type->id == ZigTypeIdFloat);22810 ir_assert(float_type->id == ZigTypeIdFloat, &instruction->base);
22610 if (float_type->data.floating.bit_count != 16 &&22811 if (float_type->data.floating.bit_count != 16 &&
22611 float_type->data.floating.bit_count != 32 &&22812 float_type->data.floating.bit_count != 32 &&
22612 float_type->data.floating.bit_count != 64) {22813 float_type->data.floating.bit_count != 64) {
...@@ -22817,6 +23018,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -22817,6 +23018,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
22817 case IrInstructionIdArrayToVector:23018 case IrInstructionIdArrayToVector:
22818 case IrInstructionIdVectorToArray:23019 case IrInstructionIdVectorToArray:
22819 case IrInstructionIdAssertZero:23020 case IrInstructionIdAssertZero:
23021 case IrInstructionIdAssertNonNull:
22820 case IrInstructionIdResizeSlice:23022 case IrInstructionIdResizeSlice:
22821 case IrInstructionIdLoadPtrGen:23023 case IrInstructionIdLoadPtrGen:
22822 case IrInstructionIdBitCastGen:23024 case IrInstructionIdBitCastGen:
...@@ -23096,7 +23298,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23096,7 +23298,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2309623298
23097static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *old_instruction) {23299static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *old_instruction) {
23098 IrInstruction *new_instruction = ir_analyze_instruction_nocast(ira, old_instruction);23300 IrInstruction *new_instruction = ir_analyze_instruction_nocast(ira, old_instruction);
23099 assert(new_instruction->value.type != nullptr);23301 ir_assert(new_instruction->value.type != nullptr, old_instruction);
23100 old_instruction->child = new_instruction;23302 old_instruction->child = new_instruction;
23101 return new_instruction;23303 return new_instruction;
23102}23304}
...@@ -23221,6 +23423,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23221,6 +23423,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23221 case IrInstructionIdCmpxchgGen:23423 case IrInstructionIdCmpxchgGen:
23222 case IrInstructionIdCmpxchgSrc:23424 case IrInstructionIdCmpxchgSrc:
23223 case IrInstructionIdAssertZero:23425 case IrInstructionIdAssertZero:
23426 case IrInstructionIdAssertNonNull:
23224 case IrInstructionIdResizeSlice:23427 case IrInstructionIdResizeSlice:
23225 case IrInstructionIdGlobalAsm:23428 case IrInstructionIdGlobalAsm:
23226 return true;23429 return true;
src/ir.hpp+1-1
...@@ -14,7 +14,7 @@ bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable...@@ -14,7 +14,7 @@ bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable
14bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);14bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
1515
16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,17 ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
19 IrExecutable *parent_exec, AstNode *expected_type_source_node);19 IrExecutable *parent_exec, AstNode *expected_type_source_node);
2020
src/ir_print.cpp+9
...@@ -1003,6 +1003,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct...@@ -1003,6 +1003,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct
1003 fprintf(irp->f, ")");1003 fprintf(irp->f, ")");
1004}1004}
10051005
1006static void ir_print_assert_non_null(IrPrint *irp, IrInstructionAssertNonNull *instruction) {
1007 fprintf(irp->f, "AssertNonNull(");
1008 ir_print_other_instruction(irp, instruction->target);
1009 fprintf(irp->f, ")");
1010}
1011
1006static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) {1012static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) {
1007 fprintf(irp->f, "@resizeSlice(");1013 fprintf(irp->f, "@resizeSlice(");
1008 ir_print_other_instruction(irp, instruction->operand);1014 ir_print_other_instruction(irp, instruction->operand);
...@@ -1880,6 +1886,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1880,6 +1886,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1880 case IrInstructionIdAssertZero:1886 case IrInstructionIdAssertZero:
1881 ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);1887 ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
1882 break;1888 break;
1889 case IrInstructionIdAssertNonNull:
1890 ir_print_assert_non_null(irp, (IrInstructionAssertNonNull *)instruction);
1891 break;
1883 case IrInstructionIdResizeSlice:1892 case IrInstructionIdResizeSlice:
1884 ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction);1893 ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction);
1885 break;1894 break;
src/libc_installation.cpp+30-6
...@@ -14,6 +14,7 @@ static const char *zig_libc_keys[] = {...@@ -14,6 +14,7 @@ static const char *zig_libc_keys[] = {
14 "include_dir",14 "include_dir",
15 "sys_include_dir",15 "sys_include_dir",
16 "crt_dir",16 "crt_dir",
17 "static_crt_dir",
17 "msvc_lib_dir",18 "msvc_lib_dir",
18 "kernel32_lib_dir",19 "kernel32_lib_dir",
19};20};
...@@ -34,6 +35,7 @@ static void zig_libc_init_empty(ZigLibCInstallation *libc) {...@@ -34,6 +35,7 @@ static void zig_libc_init_empty(ZigLibCInstallation *libc) {
34 buf_init_from_str(&libc->include_dir, "");35 buf_init_from_str(&libc->include_dir, "");
35 buf_init_from_str(&libc->sys_include_dir, "");36 buf_init_from_str(&libc->sys_include_dir, "");
36 buf_init_from_str(&libc->crt_dir, "");37 buf_init_from_str(&libc->crt_dir, "");
38 buf_init_from_str(&libc->static_crt_dir, "");
37 buf_init_from_str(&libc->msvc_lib_dir, "");39 buf_init_from_str(&libc->msvc_lib_dir, "");
38 buf_init_from_str(&libc->kernel32_lib_dir, "");40 buf_init_from_str(&libc->kernel32_lib_dir, "");
39}41}
...@@ -45,7 +47,7 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget...@@ -45,7 +47,7 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
45 bool found_keys[array_length(zig_libc_keys)] = {};47 bool found_keys[array_length(zig_libc_keys)] = {};
4648
47 Buf *contents = buf_alloc();49 Buf *contents = buf_alloc();
48 if ((err = os_fetch_file_path(libc_file, contents, false))) {50 if ((err = os_fetch_file_path(libc_file, contents))) {
49 if (err != ErrorFileNotFound && verbose) {51 if (err != ErrorFileNotFound && verbose) {
50 fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err));52 fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err));
51 }53 }
...@@ -74,8 +76,9 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget...@@ -74,8 +76,9 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
74 match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir);76 match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir);
75 match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->sys_include_dir);77 match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->sys_include_dir);
76 match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_dir);78 match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_dir);
77 match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->msvc_lib_dir);79 match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->static_crt_dir);
78 match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->kernel32_lib_dir);80 match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->msvc_lib_dir);
81 match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->kernel32_lib_dir);
79 }82 }
8083
81 for (size_t i = 0; i < zig_libc_keys_len; i += 1) {84 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...@@ -110,6 +113,15 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
110 }113 }
111 }114 }
112115
116 if (buf_len(&libc->static_crt_dir) == 0) {
117 if (target->os == OsWindows && target_abi_is_gnu(target->abi)) {
118 if (verbose) {
119 fprintf(stderr, "static_crt_dir may not be empty for %s\n", target_os_name(target->os));
120 }
121 return ErrorSemanticAnalyzeFail;
122 }
123 }
124
113 if (buf_len(&libc->msvc_lib_dir) == 0) {125 if (buf_len(&libc->msvc_lib_dir) == 0) {
114 if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) {126 if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) {
115 if (verbose) {127 if (verbose) {
...@@ -311,6 +323,10 @@ static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool...@@ -311,6 +323,10 @@ static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool
311#endif323#endif
312324
313#if defined(ZIG_OS_WINDOWS)325#if defined(ZIG_OS_WINDOWS)
326static Error zig_libc_find_native_static_crt_dir_posix(ZigLibCInstallation *self, bool verbose) {
327 return zig_libc_cc_print_file_name("crtbegin.o", &self->static_crt_dir, true, verbose);
328}
329
314static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {330static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
315 Error err;331 Error err;
316 if ((err = os_get_win32_ucrt_include_path(sdk, &self->include_dir))) {332 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,...@@ -322,7 +338,7 @@ static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self,
322 return ErrorNone;338 return ErrorNone;
323}339}
324340
325static Error zig_libc_find_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,341static Error zig_libc_find_native_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
326 bool verbose)342 bool verbose)
327{343{
328 Error err;344 Error err;
...@@ -398,11 +414,16 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) {...@@ -398,11 +414,16 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
398 "# On POSIX it's the directory that includes `sys/errno.h`.\n"414 "# On POSIX it's the directory that includes `sys/errno.h`.\n"
399 "sys_include_dir=%s\n"415 "sys_include_dir=%s\n"
400 "\n"416 "\n"
401 "# The directory that contains `crt1.o`.\n"417 "# The directory that contains `crt1.o` or `crt2.o`.\n"
402 "# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n"418 "# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n"
403 "# Not needed when targeting MacOS.\n"419 "# Not needed when targeting MacOS.\n"
404 "crt_dir=%s\n"420 "crt_dir=%s\n"
405 "\n"421 "\n"
422 "# The directory that contains `crtbegin.o`.\n"
423 "# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.\n"
424 "# Not needed when targeting MacOS.\n"
425 "static_crt_dir=%s\n"
426 "\n"
406 "# The directory that contains `vcruntime.lib`.\n"427 "# The directory that contains `vcruntime.lib`.\n"
407 "# Only needed when targeting MSVC on Windows.\n"428 "# Only needed when targeting MSVC on Windows.\n"
408 "msvc_lib_dir=%s\n"429 "msvc_lib_dir=%s\n"
...@@ -415,6 +436,7 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) {...@@ -415,6 +436,7 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
415 buf_ptr(&self->include_dir),436 buf_ptr(&self->include_dir),
416 buf_ptr(&self->sys_include_dir),437 buf_ptr(&self->sys_include_dir),
417 buf_ptr(&self->crt_dir),438 buf_ptr(&self->crt_dir),
439 buf_ptr(&self->static_crt_dir),
418 buf_ptr(&self->msvc_lib_dir),440 buf_ptr(&self->msvc_lib_dir),
419 buf_ptr(&self->kernel32_lib_dir)441 buf_ptr(&self->kernel32_lib_dir)
420 );442 );
...@@ -431,6 +453,8 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {...@@ -431,6 +453,8 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
431 return err;453 return err;
432 if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))454 if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))
433 return err;455 return err;
456 if ((err = zig_libc_find_native_static_crt_dir_posix(self, verbose)))
457 return err;
434 return ErrorNone;458 return ErrorNone;
435 } else {459 } else {
436 ZigWindowsSDK *sdk;460 ZigWindowsSDK *sdk;
...@@ -444,7 +468,7 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {...@@ -444,7 +468,7 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
444 return err;468 return err;
445 if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose)))469 if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose)))
446 return err;470 return err;
447 if ((err = zig_libc_find_crt_dir_windows(self, sdk, &native_target, verbose)))471 if ((err = zig_libc_find_native_crt_dir_windows(self, sdk, &native_target, verbose)))
448 return err;472 return err;
449 return ErrorNone;473 return ErrorNone;
450 case ZigFindWindowsSdkErrorOutOfMemory:474 case ZigFindWindowsSdkErrorOutOfMemory:
src/libc_installation.hpp+1-2
...@@ -19,6 +19,7 @@ struct ZigLibCInstallation {...@@ -19,6 +19,7 @@ struct ZigLibCInstallation {
19 Buf include_dir;19 Buf include_dir;
20 Buf sys_include_dir;20 Buf sys_include_dir;
21 Buf crt_dir;21 Buf crt_dir;
22 Buf static_crt_dir;
22 Buf msvc_lib_dir;23 Buf msvc_lib_dir;
23 Buf kernel32_lib_dir;24 Buf kernel32_lib_dir;
24};25};
...@@ -29,8 +30,6 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file);...@@ -29,8 +30,6 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file);
2930
30Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose);31Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose);
3132
32#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_WINDOWS)
33Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose);33Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose);
34#endif
3534
36#endif35#endif
src/link.cpp+191-117
...@@ -25,6 +25,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou...@@ -25,6 +25,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou
25 CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,25 CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
26 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path());26 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path());
27 child_gen->disable_gen_h = true;27 child_gen->disable_gen_h = true;
28 child_gen->disable_stack_probing = true;
28 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;29 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
29 child_gen->verbose_ast = parent_gen->verbose_ast;30 child_gen->verbose_ast = parent_gen->verbose_ast;
30 child_gen->verbose_link = parent_gen->verbose_link;31 child_gen->verbose_link = parent_gen->verbose_link;
...@@ -772,17 +773,15 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {...@@ -772,17 +773,15 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
772 }773 }
773}774}
774775
775static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) {776static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, OutType child_out_type) {
776 // The Mach-O LLD code is not well maintained, and trips an assertion777 // The Mach-O LLD code is not well maintained, and trips an assertion
777 // when we link compiler_rt and builtin as libraries rather than objects.778 // when we link compiler_rt and builtin as libraries rather than objects.
778 // Here we workaround this by having compiler_rt and builtin be objects.779 // Here we workaround this by having compiler_rt and builtin be objects.
779 // TODO write our own linker. https://github.com/ziglang/zig/issues/1535780 // TODO write our own linker. https://github.com/ziglang/zig/issues/1535
780 OutType child_out_type = OutTypeLib;
781 if (parent_gen->zig_target->os == OsMacOSX) {781 if (parent_gen->zig_target->os == OsMacOSX) {
782 child_out_type = OutTypeObj;782 child_out_type = OutTypeObj;
783 }783 }
784784
785
786 CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type,785 CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type,
787 parent_gen->libc);786 parent_gen->libc);
788 codegen_set_out_name(child_gen, buf_create_from_str(aname));787 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) {...@@ -804,14 +803,14 @@ static Buf *build_a(CodeGen *parent_gen, const char *aname) {
804 Buf *full_path = buf_alloc();803 Buf *full_path = buf_alloc();
805 os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);804 os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);
806805
807 return build_a_raw(parent_gen, aname, full_path);806 return build_a_raw(parent_gen, aname, full_path, OutTypeLib);
808}807}
809808
810static Buf *build_compiler_rt(CodeGen *parent_gen) {809static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type) {
811 Buf *full_path = buf_alloc();810 Buf *full_path = buf_alloc();
812 os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("compiler_rt.zig"), full_path);811 os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("compiler_rt.zig"), full_path);
813812
814 return build_a_raw(parent_gen, "compiler_rt", full_path);813 return build_a_raw(parent_gen, "compiler_rt", full_path, child_out_type);
815}814}
816815
817static const char *get_darwin_arch_string(const ZigTarget *t) {816static const char *get_darwin_arch_string(const ZigTarget *t) {
...@@ -1006,7 +1005,7 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -1006,7 +1005,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
1006 lj->args.append(buf_ptr(builtin_a_path));1005 lj->args.append(buf_ptr(builtin_a_path));
1007 }1006 }
10081007
1009 Buf *compiler_rt_o_path = build_compiler_rt(g);1008 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
1010 lj->args.append(buf_ptr(compiler_rt_o_path));1009 lj->args.append(buf_ptr(compiler_rt_o_path));
1011 }1010 }
10121011
...@@ -1091,16 +1090,35 @@ static void construct_linker_job_wasm(LinkJob *lj) {...@@ -1091,16 +1090,35 @@ static void construct_linker_job_wasm(LinkJob *lj) {
1091 CodeGen *g = lj->codegen;1090 CodeGen *g = lj->codegen;
10921091
1093 lj->args.append("-error-limit=0");1092 lj->args.append("-error-limit=0");
1094 lj->args.append("--no-entry"); // So lld doesn't look for _start.1093
1094 if (g->zig_target->os != OsWASI) {
1095 lj->args.append("--no-entry"); // So lld doesn't look for _start.
1096 }
1095 lj->args.append("--allow-undefined");1097 lj->args.append("--allow-undefined");
1096 lj->args.append("--export-all");
1097 lj->args.append("-o");1098 lj->args.append("-o");
1098 lj->args.append(buf_ptr(&g->output_file_path));1099 lj->args.append(buf_ptr(&g->output_file_path));
10991100
1101 auto export_it = g->exported_symbol_names.entry_iterator();
1102 decltype(g->exported_symbol_names)::Entry *curr_entry = nullptr;
1103 while ((curr_entry = export_it.next()) != nullptr) {
1104 Buf *arg = buf_sprintf("--export=%s", buf_ptr(curr_entry->key));
1105 lj->args.append(buf_ptr(arg));
1106 }
1107
1100 // .o files1108 // .o files
1101 for (size_t i = 0; i < g->link_objects.length; i += 1) {1109 for (size_t i = 0; i < g->link_objects.length; i += 1) {
1102 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));1110 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
1103 }1111 }
1112
1113 if (g->out_type == OutTypeExe) {
1114 if (g->libc_link_lib == nullptr) {
1115 Buf *builtin_a_path = build_a(g, "builtin");
1116 lj->args.append(buf_ptr(builtin_a_path));
1117 }
1118
1119 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
1120 lj->args.append(buf_ptr(compiler_rt_o_path));
1121 }
1104}1122}
11051123
1106static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {1124static 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...@@ -1124,53 +1142,121 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
1124}1142}
11251143
1126static void add_uefi_link_args(LinkJob *lj) {1144static void add_uefi_link_args(LinkJob *lj) {
1127 lj->args.append("/BASE:0");1145 lj->args.append("-BASE:0");
1128 lj->args.append("/ENTRY:EfiMain");1146 lj->args.append("-ENTRY:EfiMain");
1129 lj->args.append("/OPT:REF");1147 lj->args.append("-OPT:REF");
1130 lj->args.append("/SAFESEH:NO");1148 lj->args.append("-SAFESEH:NO");
1131 lj->args.append("/MERGE:.rdata=.data");1149 lj->args.append("-MERGE:.rdata=.data");
1132 lj->args.append("/ALIGN:32");1150 lj->args.append("-ALIGN:32");
1133 lj->args.append("/NODEFAULTLIB");1151 lj->args.append("-NODEFAULTLIB");
1134 lj->args.append("/SECTION:.xdata,D");1152 lj->args.append("-SECTION:.xdata,D");
1135}1153}
11361154
1137static void add_nt_link_args(LinkJob *lj, bool is_library) {1155static void add_msvc_link_args(LinkJob *lj, bool is_library) {
1138 CodeGen *g = lj->codegen;1156 CodeGen *g = lj->codegen;
11391157
1140 if (lj->link_in_crt) {1158 // TODO: https://github.com/ziglang/zig/issues/2064
1141 // TODO: https://github.com/ziglang/zig/issues/20641159 bool is_dynamic = true; // g->is_dynamic;
1142 bool is_dynamic = true; // g->is_dynamic;1160 const char *lib_str = is_dynamic ? "" : "lib";
1143 const char *lib_str = is_dynamic ? "" : "lib";1161 const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
1144 const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";1162
11451163 if (!is_dynamic) {
1146 if (!is_dynamic) {1164 Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str);
1147 Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str);1165 lj->args.append(buf_ptr(cmt_lib_name));
1148 lj->args.append(buf_ptr(cmt_lib_name));1166 } else {
1149 } else {1167 Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str);
1150 Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str);1168 lj->args.append(buf_ptr(msvcrt_lib_name));
1151 lj->args.append(buf_ptr(msvcrt_lib_name));1169 }
1152 }1170
1171 Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str);
1172 lj->args.append(buf_ptr(vcruntime_lib_name));
11531173
1154 Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str);1174 Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str);
1155 lj->args.append(buf_ptr(vcruntime_lib_name));1175 lj->args.append(buf_ptr(crt_lib_name));
11561176
1157 Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str);1177 //Visual C++ 2015 Conformance Changes
1158 lj->args.append(buf_ptr(crt_lib_name));1178 //https://msdn.microsoft.com/en-us/library/bb531344.aspx
1179 lj->args.append("legacy_stdio_definitions.lib");
11591180
1160 //Visual C++ 2015 Conformance Changes1181 // msvcrt depends on kernel32 and ntdll
1161 //https://msdn.microsoft.com/en-us/library/bb531344.aspx1182 lj->args.append("kernel32.lib");
1162 lj->args.append("legacy_stdio_definitions.lib");1183 lj->args.append("ntdll.lib");
1184}
1185
1186static const char *get_libc_file(ZigLibCInstallation *lib, const char *file) {
1187 Buf *out_buf = buf_alloc();
1188 os_path_join(&lib->crt_dir, buf_create_from_str(file), out_buf);
1189 return buf_ptr(out_buf);
1190}
1191
1192static const char *get_libc_static_file(ZigLibCInstallation *lib, const char *file) {
1193 Buf *out_buf = buf_alloc();
1194 os_path_join(&lib->static_crt_dir, buf_create_from_str(file), out_buf);
1195 return buf_ptr(out_buf);
1196}
1197
1198static void add_mingw_link_args(LinkJob *lj, bool is_library) {
1199 CodeGen *g = lj->codegen;
11631200
1164 // msvcrt depends on kernel32 and ntdll1201 bool is_dll = g->out_type == OutTypeLib && g->is_dynamic;
1165 lj->args.append("kernel32.lib");1202
1166 lj->args.append("ntdll.lib");1203 if (g->zig_target->arch == ZigLLVM_x86) {
1204 lj->args.append("-ALTERNATENAME:__image_base__=___ImageBase");
1205 } else {
1206 lj->args.append("-ALTERNATENAME:__image_base__=__ImageBase");
1207 }
1208
1209 if (is_dll) {
1210 lj->args.append(get_libc_file(g->libc, "dllcrt2.o"));
1211 } else {
1212 lj->args.append(get_libc_file(g->libc, "crt2.o"));
1213 }
1214
1215 lj->args.append(get_libc_static_file(g->libc, "crtbegin.o"));
1216
1217 lj->args.append(get_libc_file(g->libc, "libmingw32.a"));
1218
1219 if (is_dll) {
1220 lj->args.append(get_libc_static_file(g->libc, "libgcc_s.a"));
1221 lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
1222 } else {
1223 lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
1224 lj->args.append(get_libc_static_file(g->libc, "libgcc_eh.a"));
1225 }
1226
1227 lj->args.append(get_libc_static_file(g->libc, "libssp.a"));
1228 lj->args.append(get_libc_file(g->libc, "libmoldname.a"));
1229 lj->args.append(get_libc_file(g->libc, "libmingwex.a"));
1230 lj->args.append(get_libc_file(g->libc, "libmsvcrt.a"));
1231
1232 if (g->subsystem == TargetSubsystemWindows) {
1233 lj->args.append(get_libc_file(g->libc, "libgdi32.a"));
1234 lj->args.append(get_libc_file(g->libc, "libcomdlg32.a"));
1235 }
1236
1237 lj->args.append(get_libc_file(g->libc, "libadvapi32.a"));
1238 lj->args.append(get_libc_file(g->libc, "libadvapi32.a"));
1239 lj->args.append(get_libc_file(g->libc, "libshell32.a"));
1240 lj->args.append(get_libc_file(g->libc, "libuser32.a"));
1241 lj->args.append(get_libc_file(g->libc, "libkernel32.a"));
1242
1243 lj->args.append(get_libc_static_file(g->libc, "crtend.o"));
1244}
1245
1246static void add_win_link_args(LinkJob *lj, bool is_library) {
1247 if (lj->link_in_crt) {
1248 if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
1249 add_mingw_link_args(lj, is_library);
1250 } else {
1251 add_msvc_link_args(lj, is_library);
1252 }
1167 } else {1253 } else {
1168 lj->args.append("/NODEFAULTLIB");1254 lj->args.append("-NODEFAULTLIB");
1169 if (!is_library) {1255 if (!is_library) {
1170 if (g->have_winmain) {1256 if (lj->codegen->have_winmain) {
1171 lj->args.append("/ENTRY:WinMain");1257 lj->args.append("-ENTRY:WinMain");
1172 } else {1258 } else {
1173 lj->args.append("/ENTRY:WinMainCRTStartup");1259 lj->args.append("-ENTRY:WinMainCRTStartup");
1174 }1260 }
1175 }1261 }
1176 }1262 }
...@@ -1180,87 +1266,93 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -1180,87 +1266,93 @@ static void construct_linker_job_coff(LinkJob *lj) {
1180 Error err;1266 Error err;
1181 CodeGen *g = lj->codegen;1267 CodeGen *g = lj->codegen;
11821268
1183 lj->args.append("/ERRORLIMIT:0");1269 lj->args.append("-ERRORLIMIT:0");
11841270
1185 lj->args.append("/NOLOGO");1271 lj->args.append("-NOLOGO");
11861272
1187 if (!g->strip_debug_symbols) {1273 if (!g->strip_debug_symbols) {
1188 lj->args.append("/DEBUG");1274 lj->args.append("-DEBUG");
1189 }1275 }
11901276
1191 if (g->out_type == OutTypeExe) {1277 if (g->out_type == OutTypeExe) {
1192 // TODO compile time stack upper bound detection1278 // TODO compile time stack upper bound detection
1193 lj->args.append("/STACK:16777216");1279 lj->args.append("-STACK:16777216");
1194 }1280 }
11951281
1196 coff_append_machine_arg(g, &lj->args);1282 coff_append_machine_arg(g, &lj->args);
11971283
1198 bool is_library = g->out_type == OutTypeLib;1284 bool is_library = g->out_type == OutTypeLib;
1285 if (is_library && g->is_dynamic) {
1286 lj->args.append("-DLL");
1287 }
1288
1289 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
1290
1291 if (g->libc_link_lib != nullptr) {
1292 assert(g->libc != nullptr);
1293
1294 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
1295
1296 if (target_abi_is_gnu(g->zig_target->abi)) {
1297 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->sys_include_dir))));
1298 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->include_dir))));
1299 } else {
1300 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
1301 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
1302 }
1303 }
1304
1305 for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
1306 const char *lib_dir = g->lib_dirs.at(i);
1307 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
1308 }
1309
1310 for (size_t i = 0; i < g->link_objects.length; i += 1) {
1311 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
1312 }
1313
1199 switch (g->subsystem) {1314 switch (g->subsystem) {
1200 case TargetSubsystemAuto:1315 case TargetSubsystemAuto:
1201 if (g->zig_target->os == OsUefi) {1316 if (g->zig_target->os == OsUefi) {
1202 add_uefi_link_args(lj);1317 add_uefi_link_args(lj);
1203 } else {1318 } else {
1204 add_nt_link_args(lj, is_library);1319 add_win_link_args(lj, is_library);
1205 }1320 }
1206 break;1321 break;
1207 case TargetSubsystemConsole:1322 case TargetSubsystemConsole:
1208 lj->args.append("/SUBSYSTEM:console");1323 lj->args.append("-SUBSYSTEM:console");
1209 add_nt_link_args(lj, is_library);1324 add_win_link_args(lj, is_library);
1210 break;1325 break;
1211 case TargetSubsystemEfiApplication:1326 case TargetSubsystemEfiApplication:
1212 lj->args.append("/SUBSYSTEM:efi_application");1327 lj->args.append("-SUBSYSTEM:efi_application");
1213 add_uefi_link_args(lj);1328 add_uefi_link_args(lj);
1214 break;1329 break;
1215 case TargetSubsystemEfiBootServiceDriver:1330 case TargetSubsystemEfiBootServiceDriver:
1216 lj->args.append("/SUBSYSTEM:efi_boot_service_driver");1331 lj->args.append("-SUBSYSTEM:efi_boot_service_driver");
1217 add_uefi_link_args(lj);1332 add_uefi_link_args(lj);
1218 break;1333 break;
1219 case TargetSubsystemEfiRom:1334 case TargetSubsystemEfiRom:
1220 lj->args.append("/SUBSYSTEM:efi_rom");1335 lj->args.append("-SUBSYSTEM:efi_rom");
1221 add_uefi_link_args(lj);1336 add_uefi_link_args(lj);
1222 break;1337 break;
1223 case TargetSubsystemEfiRuntimeDriver:1338 case TargetSubsystemEfiRuntimeDriver:
1224 lj->args.append("/SUBSYSTEM:efi_runtime_driver");1339 lj->args.append("-SUBSYSTEM:efi_runtime_driver");
1225 add_uefi_link_args(lj);1340 add_uefi_link_args(lj);
1226 break;1341 break;
1227 case TargetSubsystemNative:1342 case TargetSubsystemNative:
1228 lj->args.append("/SUBSYSTEM:native");1343 lj->args.append("-SUBSYSTEM:native");
1229 add_nt_link_args(lj, is_library);1344 add_win_link_args(lj, is_library);
1230 break;1345 break;
1231 case TargetSubsystemPosix:1346 case TargetSubsystemPosix:
1232 lj->args.append("/SUBSYSTEM:posix");1347 lj->args.append("-SUBSYSTEM:posix");
1233 add_nt_link_args(lj, is_library);1348 add_win_link_args(lj, is_library);
1234 break;1349 break;
1235 case TargetSubsystemWindows:1350 case TargetSubsystemWindows:
1236 lj->args.append("/SUBSYSTEM:windows");1351 lj->args.append("-SUBSYSTEM:windows");
1237 add_nt_link_args(lj, is_library);1352 add_win_link_args(lj, is_library);
1238 break;1353 break;
1239 }1354 }
12401355
1241 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
1242
1243 if (g->libc_link_lib != nullptr) {
1244 assert(g->libc != nullptr);
1245
1246 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
1247 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
1248 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
1249 }
1250
1251 if (is_library && g->is_dynamic) {
1252 lj->args.append("-DLL");
1253 }
1254
1255 for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
1256 const char *lib_dir = g->lib_dirs.at(i);
1257 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
1258 }
1259
1260 for (size_t i = 0; i < g->link_objects.length; i += 1) {
1261 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
1262 }
1263
1264 if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) {1356 if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) {
1265 if (g->libc_link_lib == nullptr && !g->is_dummy_so) {1357 if (g->libc_link_lib == nullptr && !g->is_dummy_so) {
1266 Buf *builtin_a_path = build_a(g, "builtin");1358 Buf *builtin_a_path = build_a(g, "builtin");
...@@ -1268,7 +1360,7 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -1268,7 +1360,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
1268 }1360 }
12691361
1270 // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage1362 // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage
1271 Buf *compiler_rt_o_path = build_compiler_rt(g);1363 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
1272 lj->args.append(buf_ptr(compiler_rt_o_path));1364 lj->args.append(buf_ptr(compiler_rt_o_path));
1273 }1365 }
12741366
...@@ -1280,11 +1372,10 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -1280,11 +1372,10 @@ static void construct_linker_job_coff(LinkJob *lj) {
1280 continue;1372 continue;
1281 }1373 }
1282 if (link_lib->provided_explicitly) {1374 if (link_lib->provided_explicitly) {
1283 if (lj->codegen->zig_target->abi == ZigLLVM_GNU) {1375 if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
1284 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));1376 Buf *lib_name = buf_sprintf("lib%s.a", buf_ptr(link_lib->name));
1285 lj->args.append(buf_ptr(arg));1377 lj->args.append(buf_ptr(lib_name));
1286 }1378 } else {
1287 else {
1288 lj->args.append(buf_ptr(link_lib->name));1379 lj->args.append(buf_ptr(link_lib->name));
1289 }1380 }
1290 } else {1381 } else {
...@@ -1416,18 +1507,6 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {...@@ -1416,18 +1507,6 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
1416 }1507 }
1417}1508}
14181509
1419static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) {
1420 if (platform->major < major) {
1421 return true;
1422 } else if (platform->major > major) {
1423 return false;
1424 }
1425 if (platform->minor < minor) {
1426 return true;
1427 }
1428 return false;
1429}
1430
1431static void construct_linker_job_macho(LinkJob *lj) {1510static void construct_linker_job_macho(LinkJob *lj) {
1432 CodeGen *g = lj->codegen;1511 CodeGen *g = lj->codegen;
14331512
...@@ -1524,7 +1603,7 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -1524,7 +1603,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
15241603
1525 // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce1604 // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
1526 if (g->out_type == OutTypeExe || is_dyn_lib) {1605 if (g->out_type == OutTypeExe || is_dyn_lib) {
1527 Buf *compiler_rt_o_path = build_compiler_rt(g);1606 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
1528 lj->args.append(buf_ptr(compiler_rt_o_path));1607 lj->args.append(buf_ptr(compiler_rt_o_path));
1529 }1608 }
15301609
...@@ -1552,16 +1631,6 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -1552,16 +1631,6 @@ static void construct_linker_job_macho(LinkJob *lj) {
1552 lj->args.append("dynamic_lookup");1631 lj->args.append("dynamic_lookup");
1553 }1632 }
15541633
1555 if (platform.kind == MacOS) {
1556 if (darwin_version_lt(&platform, 10, 5)) {
1557 lj->args.append("-lgcc_s.10.4");
1558 } else if (darwin_version_lt(&platform, 10, 6)) {
1559 lj->args.append("-lgcc_s.10.5");
1560 }
1561 } else {
1562 zig_panic("TODO");
1563 }
1564
1565 for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {1634 for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {
1566 lj->args.append("-framework");1635 lj->args.append("-framework");
1567 lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));1636 lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));
...@@ -1585,6 +1654,11 @@ static void construct_linker_job(LinkJob *lj) {...@@ -1585,6 +1654,11 @@ static void construct_linker_job(LinkJob *lj) {
1585 }1654 }
1586}1655}
15871656
1657void zig_link_add_compiler_rt(CodeGen *g) {
1658 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj);
1659 g->link_objects.append(compiler_rt_o_path);
1660}
1661
1588void codegen_link(CodeGen *g) {1662void codegen_link(CodeGen *g) {
1589 codegen_add_time_event(g, "Build Dependencies");1663 codegen_add_time_event(g, "Build Dependencies");
15901664
...@@ -1611,14 +1685,14 @@ void codegen_link(CodeGen *g) {...@@ -1611,14 +1685,14 @@ void codegen_link(CodeGen *g) {
1611 if (g->out_type == OutTypeLib && !g->is_dynamic) {1685 if (g->out_type == OutTypeLib && !g->is_dynamic) {
1612 ZigList<const char *> file_names = {};1686 ZigList<const char *> file_names = {};
1613 for (size_t i = 0; i < g->link_objects.length; i += 1) {1687 for (size_t i = 0; i < g->link_objects.length; i += 1) {
1614 file_names.append((const char *)buf_ptr(g->link_objects.at(i)));1688 file_names.append(buf_ptr(g->link_objects.at(i)));
1615 }1689 }
1616 ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os);1690 ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os);
1617 codegen_add_time_event(g, "LLVM Link");1691 codegen_add_time_event(g, "LLVM Link");
1618 if (g->verbose_link) {1692 if (g->verbose_link) {
1619 fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path));1693 fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path));
1620 for (size_t i = 0; i < g->link_objects.length; i += 1) {1694 for (size_t i = 0; i < file_names.length; i += 1) {
1621 fprintf(stderr, " %s", (const char *)buf_ptr(g->link_objects.at(i)));1695 fprintf(stderr, " %s", file_names.at(i));
1622 }1696 }
1623 fprintf(stderr, "\n");1697 fprintf(stderr, "\n");
1624 }1698 }
src/list.hpp-2
...@@ -10,8 +10,6 @@...@@ -10,8 +10,6 @@
1010
11#include "util.hpp"11#include "util.hpp"
1212
13#include <assert.h>
14
15template<typename T>13template<typename T>
16struct ZigList {14struct ZigList {
17 void deinit() {15 void deinit() {
src/main.cpp+87-82
...@@ -14,6 +14,7 @@...@@ -14,6 +14,7 @@
14#include "os.hpp"14#include "os.hpp"
15#include "target.hpp"15#include "target.hpp"
16#include "libc_installation.hpp"16#include "libc_installation.hpp"
17#include "userland.h"
1718
18#include <stdio.h>19#include <stdio.h>
1920
...@@ -40,6 +41,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -40,6 +41,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
40 " libc [paths_file] Display native libc paths file or validate one\n"41 " libc [paths_file] Display native libc paths file or validate one\n"
41 " run [source] [-- [args]] create executable and run immediately\n"42 " run [source] [-- [args]] create executable and run immediately\n"
42 " translate-c [source] convert c code to zig code\n"43 " translate-c [source] convert c code to zig code\n"
44 " translate-c-2 [source] experimental self-hosted translate-c\n"
43 " targets list available compilation targets\n"45 " targets list available compilation targets\n"
44 " test [source] create and run a test build\n"46 " test [source] create and run a test build\n"
45 " version print version number and exit\n"47 " version print version number and exit\n"
...@@ -52,11 +54,12 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -52,11 +54,12 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
52 " --cache [auto|off|on] build in cache, print output path to stdout\n"54 " --cache [auto|off|on] build in cache, print output path to stdout\n"
53 " --color [auto|off|on] enable or disable colored error messages\n"55 " --color [auto|off|on] enable or disable colored error messages\n"
54 " --disable-gen-h do not generate a C header file (.h)\n"56 " --disable-gen-h do not generate a C header file (.h)\n"
55 " --disable-pic disable Position Independent Code\n"
56 " --enable-pic enable Position Independent Code\n"
57 " --disable-valgrind omit valgrind client requests in debug builds\n"57 " --disable-valgrind omit valgrind client requests in debug builds\n"
58 " --enable-valgrind include valgrind client requests release builds\n"58 " --enable-valgrind include valgrind client requests release builds\n"
59 " --disable-stack-probing workaround for macosx\n"
59 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"60 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
61 " -fPIC enable Position Independent Code\n"
62 " -fno-PIC disable Position Independent Code\n"
60 " -ftime-report print timing diagnostics\n"63 " -ftime-report print timing diagnostics\n"
61 " --libc [file] Provide a file which specifies libc paths\n"64 " --libc [file] Provide a file which specifies libc paths\n"
62 " --name [name] override output name\n"65 " --name [name] override output name\n"
...@@ -84,6 +87,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -84,6 +87,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
84 " --override-std-dir [arg] use an alternate Zig standard library\n"87 " --override-std-dir [arg] use an alternate Zig standard library\n"
85 "\n"88 "\n"
86 "Link Options:\n"89 "Link Options:\n"
90 " --bundle-compiler-rt [path] for static libraries, include compiler-rt symbols\n"
87 " --dynamic-linker [path] set the path to ld.so\n"91 " --dynamic-linker [path] set the path to ld.so\n"
88 " --each-lib-rpath add rpath for each used dynamic library\n"92 " --each-lib-rpath add rpath for each used dynamic library\n"
89 " --library [lib] link against lib\n"93 " --library [lib] link against lib\n"
...@@ -131,19 +135,6 @@ static int print_libc_usage(const char *arg0, FILE *file, int return_code) {...@@ -131,19 +135,6 @@ static int print_libc_usage(const char *arg0, FILE *file, int return_code) {
131 return return_code;135 return return_code;
132}136}
133137
134static const char *ZIG_ZEN = "\n"
135" * Communicate intent precisely.\n"
136" * Edge cases matter.\n"
137" * Favor reading code over writing code.\n"
138" * Only one obvious way to do things.\n"
139" * Runtime crashes are better than bugs.\n"
140" * Compile errors are better than runtime crashes.\n"
141" * Incremental improvements.\n"
142" * Avoid local maximums.\n"
143" * Reduce the amount one must remember.\n"
144" * Minimize energy spent on coding style.\n"
145" * Together we serve end users.\n";
146
147static bool arch_available_in_llvm(ZigLLVM_ArchType arch) {138static bool arch_available_in_llvm(ZigLLVM_ArchType arch) {
148 LLVMTargetRef target_ref;139 LLVMTargetRef target_ref;
149 char *err_msg = nullptr;140 char *err_msg = nullptr;
...@@ -211,6 +202,7 @@ enum Cmd {...@@ -211,6 +202,7 @@ enum Cmd {
211 CmdTargets,202 CmdTargets,
212 CmdTest,203 CmdTest,
213 CmdTranslateC,204 CmdTranslateC,
205 CmdTranslateCUserland,
214 CmdVersion,206 CmdVersion,
215 CmdZen,207 CmdZen,
216 CmdLibC,208 CmdLibC,
...@@ -324,7 +316,7 @@ int main(int argc, char **argv) {...@@ -324,7 +316,7 @@ int main(int argc, char **argv) {
324 return print_error_usage(arg0);316 return print_error_usage(arg0);
325 }317 }
326 Buf *cmd_template_path = buf_alloc();318 Buf *cmd_template_path = buf_alloc();
327 os_path_join(get_zig_special_dir(), buf_create_from_str(init_cmd), cmd_template_path);319 os_path_join(get_zig_special_dir(get_zig_lib_dir()), buf_create_from_str(init_cmd), cmd_template_path);
328 Buf *build_zig_path = buf_alloc();320 Buf *build_zig_path = buf_alloc();
329 os_path_join(cmd_template_path, buf_create_from_str("build.zig"), build_zig_path);321 os_path_join(cmd_template_path, buf_create_from_str("build.zig"), build_zig_path);
330 Buf *src_dir_path = buf_alloc();322 Buf *src_dir_path = buf_alloc();
...@@ -341,7 +333,7 @@ int main(int argc, char **argv) {...@@ -341,7 +333,7 @@ int main(int argc, char **argv) {
341 os_path_split(cwd, nullptr, cwd_basename);333 os_path_split(cwd, nullptr, cwd_basename);
342334
343 Buf *build_zig_contents = buf_alloc();335 Buf *build_zig_contents = buf_alloc();
344 if ((err = os_fetch_file_path(build_zig_path, build_zig_contents, false))) {336 if ((err = os_fetch_file_path(build_zig_path, build_zig_contents))) {
345 fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(build_zig_path), err_str(err));337 fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(build_zig_path), err_str(err));
346 return EXIT_FAILURE;338 return EXIT_FAILURE;
347 }339 }
...@@ -356,7 +348,7 @@ int main(int argc, char **argv) {...@@ -356,7 +348,7 @@ int main(int argc, char **argv) {
356 }348 }
357349
358 Buf *main_zig_contents = buf_alloc();350 Buf *main_zig_contents = buf_alloc();
359 if ((err = os_fetch_file_path(main_zig_path, main_zig_contents, false))) {351 if ((err = os_fetch_file_path(main_zig_path, main_zig_contents))) {
360 fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(main_zig_path), err_str(err));352 fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(main_zig_path), err_str(err));
361 return EXIT_FAILURE;353 return EXIT_FAILURE;
362 }354 }
...@@ -450,9 +442,12 @@ int main(int argc, char **argv) {...@@ -450,9 +442,12 @@ int main(int argc, char **argv) {
450 int runtime_args_start = -1;442 int runtime_args_start = -1;
451 bool system_linker_hack = false;443 bool system_linker_hack = false;
452 TargetSubsystem subsystem = TargetSubsystemAuto;444 TargetSubsystem subsystem = TargetSubsystemAuto;
453 bool is_single_threaded = false;445 bool want_single_threaded = false;
454 bool disable_gen_h = false;446 bool disable_gen_h = false;
447 bool bundle_compiler_rt = false;
448 bool disable_stack_probing = false;
455 Buf *override_std_dir = nullptr;449 Buf *override_std_dir = nullptr;
450 Buf *override_lib_dir = nullptr;
456 Buf *main_pkg_path = nullptr;451 Buf *main_pkg_path = nullptr;
457 ValgrindSupport valgrind_support = ValgrindSupportAuto;452 ValgrindSupport valgrind_support = ValgrindSupportAuto;
458 WantPIC want_pic = WantPICAuto;453 WantPIC want_pic = WantPICAuto;
...@@ -486,13 +481,27 @@ int main(int argc, char **argv) {...@@ -486,13 +481,27 @@ int main(int argc, char **argv) {
486 } else if (i + 1 < argc && strcmp(argv[i], "--cache-dir") == 0) {481 } else if (i + 1 < argc && strcmp(argv[i], "--cache-dir") == 0) {
487 cache_dir = argv[i + 1];482 cache_dir = argv[i + 1];
488 i += 1;483 i += 1;
484 } else if (i + 1 < argc && strcmp(argv[i], "--override-std-dir") == 0) {
485 override_std_dir = buf_create_from_str(argv[i + 1]);
486 i += 1;
487
488 args.append("--override-std-dir");
489 args.append(buf_ptr(override_std_dir));
490 } else if (i + 1 < argc && strcmp(argv[i], "--override-lib-dir") == 0) {
491 override_lib_dir = buf_create_from_str(argv[i + 1]);
492 i += 1;
493
494 args.append("--override-lib-dir");
495 args.append(buf_ptr(override_lib_dir));
489 } else {496 } else {
490 args.append(argv[i]);497 args.append(argv[i]);
491 }498 }
492 }499 }
493500
501 Buf *zig_lib_dir = (override_lib_dir == nullptr) ? get_zig_lib_dir() : override_lib_dir;
502
494 Buf *build_runner_path = buf_alloc();503 Buf *build_runner_path = buf_alloc();
495 os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);504 os_path_join(get_zig_special_dir(zig_lib_dir), buf_create_from_str("build_runner.zig"), build_runner_path);
496505
497 ZigTarget target;506 ZigTarget target;
498 get_native_target(&target);507 get_native_target(&target);
...@@ -512,7 +521,7 @@ int main(int argc, char **argv) {...@@ -512,7 +521,7 @@ int main(int argc, char **argv) {
512 }521 }
513522
514 CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe,523 CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe,
515 BuildModeDebug, get_zig_lib_dir(), override_std_dir, nullptr, &full_cache_dir);524 BuildModeDebug, override_lib_dir, override_std_dir, nullptr, &full_cache_dir);
516 g->valgrind_support = valgrind_support;525 g->valgrind_support = valgrind_support;
517 g->enable_time_report = timing_info;526 g->enable_time_report = timing_info;
518 codegen_set_out_name(g, buf_create_from_str("build"));527 codegen_set_out_name(g, buf_create_from_str("build"));
...@@ -532,23 +541,25 @@ int main(int argc, char **argv) {...@@ -532,23 +541,25 @@ int main(int argc, char **argv) {
532 "Usage: %s build [options]\n"541 "Usage: %s build [options]\n"
533 "\n"542 "\n"
534 "General Options:\n"543 "General Options:\n"
535 " --help Print this help and exit\n"544 " --help Print this help and exit\n"
536 " --verbose Print commands before executing them\n"545 " --verbose Print commands before executing them\n"
537 " --prefix [path] Override default install prefix\n"546 " --prefix [path] Override default install prefix\n"
538 " --search-prefix [path] Add a path to look for binaries, libraries, headers\n"547 " --search-prefix [path] Add a path to look for binaries, libraries, headers\n"
539 "\n"548 "\n"
540 "Project-specific options become available when the build file is found.\n"549 "Project-specific options become available when the build file is found.\n"
541 "\n"550 "\n"
542 "Advanced Options:\n"551 "Advanced Options:\n"
543 " --build-file [file] Override path to build.zig\n"552 " --build-file [file] Override path to build.zig\n"
544 " --cache-dir [path] Override path to cache directory\n"553 " --cache-dir [path] Override path to cache directory\n"
545 " --verbose-tokenize Enable compiler debug output for tokenization\n"554 " --override-std-dir [arg] Override path to Zig standard library\n"
546 " --verbose-ast Enable compiler debug output for parsing into an AST\n"555 " --override-lib-dir [arg] Override path to Zig lib library\n"
547 " --verbose-link Enable compiler debug output for linking\n"556 " --verbose-tokenize Enable compiler debug output for tokenization\n"
548 " --verbose-ir Enable compiler debug output for Zig IR\n"557 " --verbose-ast Enable compiler debug output for parsing into an AST\n"
549 " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"558 " --verbose-link Enable compiler debug output for linking\n"
550 " --verbose-cimport Enable compiler debug output for C imports\n"559 " --verbose-ir Enable compiler debug output for Zig IR\n"
551 " --verbose-cc Enable compiler debug output for C compilation\n"560 " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
561 " --verbose-cimport Enable compiler debug output for C imports\n"
562 " --verbose-cc Enable compiler debug output for C compilation\n"
552 "\n"563 "\n"
553 , zig_exe_path);564 , zig_exe_path);
554 return EXIT_SUCCESS;565 return EXIT_SUCCESS;
...@@ -581,36 +592,7 @@ int main(int argc, char **argv) {...@@ -581,36 +592,7 @@ int main(int argc, char **argv) {
581 }592 }
582 return (term.how == TerminationIdClean) ? term.code : -1;593 return (term.how == TerminationIdClean) ? term.code : -1;
583 } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {594 } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
584 init_all_targets();595 return stage2_fmt(argc, argv);
585 ZigTarget target;
586 get_native_target(&target);
587 Buf *fmt_runner_path = buf_alloc();
588 os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path);
589 Buf *cache_dir_buf = buf_create_from_str(cache_dir ? cache_dir : default_zig_cache_name);
590 CodeGen *g = codegen_create(main_pkg_path, fmt_runner_path, &target, OutTypeExe,
591 BuildModeDebug, get_zig_lib_dir(), nullptr, nullptr, cache_dir_buf);
592 g->valgrind_support = valgrind_support;
593 g->is_single_threaded = true;
594 codegen_set_out_name(g, buf_create_from_str("fmt"));
595 g->enable_cache = true;
596
597 codegen_build_and_link(g);
598
599 // TODO standardize os.cpp so that the args are supposed to have the exe
600 ZigList<const char*> args_with_exe = {0};
601 ZigList<const char*> args_without_exe = {0};
602 const char *exec_path = buf_ptr(&g->output_file_path);
603 args_with_exe.append(exec_path);
604 for (int i = 2; i < argc; i += 1) {
605 args_with_exe.append(argv[i]);
606 args_without_exe.append(argv[i]);
607 }
608 args_with_exe.append(nullptr);
609 os_execv(exec_path, args_with_exe.items);
610
611 Termination term;
612 os_spawn_process(exec_path, args_without_exe, &term);
613 return term.code;
614 }596 }
615597
616 for (int i = 1; i < argc; i += 1) {598 for (int i = 1; i < argc; i += 1) {
...@@ -664,16 +646,20 @@ int main(int argc, char **argv) {...@@ -664,16 +646,20 @@ int main(int argc, char **argv) {
664 valgrind_support = ValgrindSupportEnabled;646 valgrind_support = ValgrindSupportEnabled;
665 } else if (strcmp(arg, "--disable-valgrind") == 0) {647 } else if (strcmp(arg, "--disable-valgrind") == 0) {
666 valgrind_support = ValgrindSupportDisabled;648 valgrind_support = ValgrindSupportDisabled;
667 } else if (strcmp(arg, "--enable-pic") == 0) {649 } else if (strcmp(arg, "-fPIC") == 0) {
668 want_pic = WantPICEnabled;650 want_pic = WantPICEnabled;
669 } else if (strcmp(arg, "--disable-pic") == 0) {651 } else if (strcmp(arg, "-fno-PIC") == 0) {
670 want_pic = WantPICDisabled;652 want_pic = WantPICDisabled;
671 } else if (strcmp(arg, "--system-linker-hack") == 0) {653 } else if (strcmp(arg, "--system-linker-hack") == 0) {
672 system_linker_hack = true;654 system_linker_hack = true;
673 } else if (strcmp(arg, "--single-threaded") == 0) {655 } else if (strcmp(arg, "--single-threaded") == 0) {
674 is_single_threaded = true;656 want_single_threaded = true;
675 } else if (strcmp(arg, "--disable-gen-h") == 0) {657 } else if (strcmp(arg, "--disable-gen-h") == 0) {
676 disable_gen_h = true;658 disable_gen_h = true;
659 } else if (strcmp(arg, "--bundle-compiler-rt") == 0) {
660 bundle_compiler_rt = true;
661 } else if (strcmp(arg, "--disable-stack-probing") == 0) {
662 disable_stack_probing = true;
677 } else if (strcmp(arg, "--test-cmd-bin") == 0) {663 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
678 test_exec_args.append(nullptr);664 test_exec_args.append(nullptr);
679 } else if (arg[1] == 'L' && arg[2] != 0) {665 } else if (arg[1] == 'L' && arg[2] != 0) {
...@@ -757,6 +743,8 @@ int main(int argc, char **argv) {...@@ -757,6 +743,8 @@ int main(int argc, char **argv) {
757 llvm_argv.append(argv[i]);743 llvm_argv.append(argv[i]);
758 } else if (strcmp(arg, "--override-std-dir") == 0) {744 } else if (strcmp(arg, "--override-std-dir") == 0) {
759 override_std_dir = buf_create_from_str(argv[i]);745 override_std_dir = buf_create_from_str(argv[i]);
746 } else if (strcmp(arg, "--override-lib-dir") == 0) {
747 override_lib_dir = buf_create_from_str(argv[i]);
760 } else if (strcmp(arg, "--main-pkg-path") == 0) {748 } else if (strcmp(arg, "--main-pkg-path") == 0) {
761 main_pkg_path = buf_create_from_str(argv[i]);749 main_pkg_path = buf_create_from_str(argv[i]);
762 } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {750 } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {
...@@ -775,7 +763,11 @@ int main(int argc, char **argv) {...@@ -775,7 +763,11 @@ int main(int argc, char **argv) {
775 if (argv[i][0] == '-') {763 if (argv[i][0] == '-') {
776 c_file->args.append(argv[i]);764 c_file->args.append(argv[i]);
777 i += 1;765 i += 1;
778 continue;766 if (i < argc) {
767 continue;
768 }
769
770 break;
779 } else {771 } else {
780 c_file->source_path = argv[i];772 c_file->source_path = argv[i];
781 c_source_files.append(c_file);773 c_source_files.append(c_file);
...@@ -867,6 +859,8 @@ int main(int argc, char **argv) {...@@ -867,6 +859,8 @@ int main(int argc, char **argv) {
867 cmd = CmdLibC;859 cmd = CmdLibC;
868 } else if (strcmp(arg, "translate-c") == 0) {860 } else if (strcmp(arg, "translate-c") == 0) {
869 cmd = CmdTranslateC;861 cmd = CmdTranslateC;
862 } else if (strcmp(arg, "translate-c-2") == 0) {
863 cmd = CmdTranslateCUserland;
870 } else if (strcmp(arg, "test") == 0) {864 } else if (strcmp(arg, "test") == 0) {
871 cmd = CmdTest;865 cmd = CmdTest;
872 out_type = OutTypeExe;866 out_type = OutTypeExe;
...@@ -883,6 +877,7 @@ int main(int argc, char **argv) {...@@ -883,6 +877,7 @@ int main(int argc, char **argv) {
883 case CmdBuild:877 case CmdBuild:
884 case CmdRun:878 case CmdRun:
885 case CmdTranslateC:879 case CmdTranslateC:
880 case CmdTranslateCUserland:
886 case CmdTest:881 case CmdTest:
887 case CmdLibC:882 case CmdLibC:
888 if (!in_file) {883 if (!in_file) {
...@@ -959,10 +954,10 @@ int main(int argc, char **argv) {...@@ -959,10 +954,10 @@ int main(int argc, char **argv) {
959 }954 }
960 case CmdBuiltin: {955 case CmdBuiltin: {
961 CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,956 CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,
962 out_type, build_mode, get_zig_lib_dir(), override_std_dir, nullptr, nullptr);957 out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr);
963 g->valgrind_support = valgrind_support;958 g->valgrind_support = valgrind_support;
964 g->want_pic = want_pic;959 g->want_pic = want_pic;
965 g->is_single_threaded = is_single_threaded;960 g->want_single_threaded = want_single_threaded;
966 Buf *builtin_source = codegen_generate_builtin_source(g);961 Buf *builtin_source = codegen_generate_builtin_source(g);
967 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {962 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
968 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));963 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
...@@ -973,6 +968,7 @@ int main(int argc, char **argv) {...@@ -973,6 +968,7 @@ int main(int argc, char **argv) {
973 case CmdRun:968 case CmdRun:
974 case CmdBuild:969 case CmdBuild:
975 case CmdTranslateC:970 case CmdTranslateC:
971 case CmdTranslateCUserland:
976 case CmdTest:972 case CmdTest:
977 {973 {
978 if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0 &&974 if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0 &&
...@@ -985,14 +981,16 @@ int main(int argc, char **argv) {...@@ -985,14 +981,16 @@ int main(int argc, char **argv) {
985 " * --assembly argument\n"981 " * --assembly argument\n"
986 " * --c-source argument\n");982 " * --c-source argument\n");
987 return print_error_usage(arg0);983 return print_error_usage(arg0);
988 } else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) {984 } else if ((cmd == CmdTranslateC || cmd == CmdTranslateCUserland ||
985 cmd == CmdTest || cmd == CmdRun) && !in_file)
986 {
989 fprintf(stderr, "Expected source file argument.\n");987 fprintf(stderr, "Expected source file argument.\n");
990 return print_error_usage(arg0);988 return print_error_usage(arg0);
991 }989 }
992990
993 assert(cmd != CmdBuild || out_type != OutTypeUnknown);991 assert(cmd != CmdBuild || out_type != OutTypeUnknown);
994992
995 bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC);993 bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC || cmd == CmdTranslateCUserland);
996994
997 if (cmd == CmdRun) {995 if (cmd == CmdRun) {
998 out_name = "run";996 out_name = "run";
...@@ -1026,7 +1024,8 @@ int main(int argc, char **argv) {...@@ -1026,7 +1024,8 @@ int main(int argc, char **argv) {
1026 return print_error_usage(arg0);1024 return print_error_usage(arg0);
1027 }1025 }
10281026
1029 Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;1027 Buf *zig_root_source_file = (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) ?
1028 nullptr : in_file_buf;
10301029
1031 if (cmd == CmdRun && buf_out_name == nullptr) {1030 if (cmd == CmdRun && buf_out_name == nullptr) {
1032 buf_out_name = buf_create_from_str("run");1031 buf_out_name = buf_create_from_str("run");
...@@ -1050,7 +1049,7 @@ int main(int argc, char **argv) {...@@ -1050,7 +1049,7 @@ int main(int argc, char **argv) {
1050 cache_dir_buf = buf_create_from_str(cache_dir);1049 cache_dir_buf = buf_create_from_str(cache_dir);
1051 }1050 }
1052 CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,1051 CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,
1053 get_zig_lib_dir(), override_std_dir, libc, cache_dir_buf);1052 override_lib_dir, override_std_dir, libc, cache_dir_buf);
1054 if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);1053 if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
1055 g->valgrind_support = valgrind_support;1054 g->valgrind_support = valgrind_support;
1056 g->want_pic = want_pic;1055 g->want_pic = want_pic;
...@@ -1060,7 +1059,7 @@ int main(int argc, char **argv) {...@@ -1060,7 +1059,7 @@ int main(int argc, char **argv) {
1060 codegen_set_out_name(g, buf_out_name);1059 codegen_set_out_name(g, buf_out_name);
1061 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);1060 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
1062 codegen_set_is_test(g, cmd == CmdTest);1061 codegen_set_is_test(g, cmd == CmdTest);
1063 g->is_single_threaded = is_single_threaded;1062 g->want_single_threaded = want_single_threaded;
1064 codegen_set_linker_script(g, linker_script);1063 codegen_set_linker_script(g, linker_script);
1065 if (each_lib_rpath)1064 if (each_lib_rpath)
1066 codegen_set_each_lib_rpath(g, each_lib_rpath);1065 codegen_set_each_lib_rpath(g, each_lib_rpath);
...@@ -1079,6 +1078,8 @@ int main(int argc, char **argv) {...@@ -1079,6 +1078,8 @@ int main(int argc, char **argv) {
1079 g->verbose_cc = verbose_cc;1078 g->verbose_cc = verbose_cc;
1080 g->output_dir = output_dir;1079 g->output_dir = output_dir;
1081 g->disable_gen_h = disable_gen_h;1080 g->disable_gen_h = disable_gen_h;
1081 g->bundle_compiler_rt = bundle_compiler_rt;
1082 g->disable_stack_probing = disable_stack_probing;
1082 codegen_set_errmsg_color(g, color);1083 codegen_set_errmsg_color(g, color);
1083 g->system_linker_hack = system_linker_hack;1084 g->system_linker_hack = system_linker_hack;
10841085
...@@ -1144,14 +1145,15 @@ int main(int argc, char **argv) {...@@ -1144,14 +1145,15 @@ int main(int argc, char **argv) {
1144 codegen_print_timing_report(g, stdout);1145 codegen_print_timing_report(g, stdout);
11451146
1146 if (cmd == CmdRun) {1147 if (cmd == CmdRun) {
1148 const char *exec_path = buf_ptr(&g->output_file_path);
1147 ZigList<const char*> args = {0};1149 ZigList<const char*> args = {0};
1150
1151 args.append(exec_path);
1148 if (runtime_args_start != -1) {1152 if (runtime_args_start != -1) {
1149 for (int i = runtime_args_start; i < argc; ++i) {1153 for (int i = runtime_args_start; i < argc; ++i) {
1150 args.append(argv[i]);1154 args.append(argv[i]);
1151 }1155 }
1152 }1156 }
1153
1154 const char *exec_path = buf_ptr(&g->output_file_path);
1155 args.append(nullptr);1157 args.append(nullptr);
11561158
1157 os_execv(exec_path, args.items);1159 os_execv(exec_path, args.items);
...@@ -1169,9 +1171,8 @@ int main(int argc, char **argv) {...@@ -1169,9 +1171,8 @@ int main(int argc, char **argv) {
1169 } else {1171 } else {
1170 zig_unreachable();1172 zig_unreachable();
1171 }1173 }
1172 } else if (cmd == CmdTranslateC) {1174 } else if (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) {
1173 AstNode *root_node = codegen_translate_c(g, in_file_buf);1175 codegen_translate_c(g, in_file_buf, stdout, cmd == CmdTranslateCUserland);
1174 ast_render(g, stdout, root_node, 4);
1175 if (timing_info)1176 if (timing_info)
1176 codegen_print_timing_report(g, stderr);1177 codegen_print_timing_report(g, stderr);
1177 return EXIT_SUCCESS;1178 return EXIT_SUCCESS;
...@@ -1228,9 +1229,13 @@ int main(int argc, char **argv) {...@@ -1228,9 +1229,13 @@ int main(int argc, char **argv) {
1228 case CmdVersion:1229 case CmdVersion:
1229 printf("%s\n", ZIG_VERSION_STRING);1230 printf("%s\n", ZIG_VERSION_STRING);
1230 return EXIT_SUCCESS;1231 return EXIT_SUCCESS;
1231 case CmdZen:1232 case CmdZen: {
1232 printf("%s\n", ZIG_ZEN);1233 const char *ptr;
1234 size_t len;
1235 stage2_zen(&ptr, &len);
1236 fwrite(ptr, len, 1, stdout);
1233 return EXIT_SUCCESS;1237 return EXIT_SUCCESS;
1238 }
1234 case CmdTargets:1239 case CmdTargets:
1235 return print_target_list(stdout);1240 return print_target_list(stdout);
1236 case CmdNone:1241 case CmdNone:
src/os.cpp+18-35
...@@ -751,39 +751,15 @@ Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {...@@ -751,39 +751,15 @@ Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {
751#endif751#endif
752}752}
753753
754Error os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {754Error os_fetch_file(FILE *f, Buf *out_buf) {
755 static const ssize_t buf_size = 0x2000;755 static const ssize_t buf_size = 0x2000;
756 buf_resize(out_buf, buf_size);756 buf_resize(out_buf, buf_size);
757 ssize_t actual_buf_len = 0;757 ssize_t actual_buf_len = 0;
758758
759 bool first_read = true;
760
761 for (;;) {759 for (;;) {
762 size_t amt_read = fread(buf_ptr(out_buf) + actual_buf_len, 1, buf_size, f);760 size_t amt_read = fread(buf_ptr(out_buf) + actual_buf_len, 1, buf_size, f);
763 actual_buf_len += amt_read;761 actual_buf_len += amt_read;
764762
765 if (skip_shebang && first_read && buf_starts_with_str(out_buf, "#!")) {
766 size_t i = 0;
767 while (true) {
768 if (i > buf_len(out_buf)) {
769 zig_panic("shebang line exceeded %zd characters", buf_size);
770 }
771
772 size_t current_pos = i;
773 i += 1;
774
775 if (out_buf->list.at(current_pos) == '\n') {
776 break;
777 }
778 }
779
780 ZigList<char> *list = &out_buf->list;
781 memmove(list->items, list->items + i, list->length - i);
782 list->length -= i;
783
784 actual_buf_len -= i;
785 }
786
787 if (amt_read != buf_size) {763 if (amt_read != buf_size) {
788 if (feof(f)) {764 if (feof(f)) {
789 buf_resize(out_buf, actual_buf_len);765 buf_resize(out_buf, actual_buf_len);
...@@ -794,7 +770,6 @@ Error os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {...@@ -794,7 +770,6 @@ Error os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
794 }770 }
795771
796 buf_resize(out_buf, actual_buf_len + buf_size);772 buf_resize(out_buf, actual_buf_len + buf_size);
797 first_read = false;
798 }773 }
799 zig_unreachable();774 zig_unreachable();
800}775}
...@@ -864,8 +839,8 @@ static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,...@@ -864,8 +839,8 @@ static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,
864839
865 FILE *stdout_f = fdopen(stdout_pipe[0], "rb");840 FILE *stdout_f = fdopen(stdout_pipe[0], "rb");
866 FILE *stderr_f = fdopen(stderr_pipe[0], "rb");841 FILE *stderr_f = fdopen(stderr_pipe[0], "rb");
867 Error err1 = os_fetch_file(stdout_f, out_stdout, false);842 Error err1 = os_fetch_file(stdout_f, out_stdout);
868 Error err2 = os_fetch_file(stderr_f, out_stderr, false);843 Error err2 = os_fetch_file(stderr_f, out_stderr);
869844
870 fclose(stdout_f);845 fclose(stdout_f);
871 fclose(stderr_f);846 fclose(stderr_f);
...@@ -1097,7 +1072,7 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {...@@ -1097,7 +1072,7 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {
1097 }1072 }
1098}1073}
10991074
1100Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {1075Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {
1101 FILE *f = fopen(buf_ptr(full_path), "rb");1076 FILE *f = fopen(buf_ptr(full_path), "rb");
1102 if (!f) {1077 if (!f) {
1103 switch (errno) {1078 switch (errno) {
...@@ -1116,7 +1091,7 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {...@@ -1116,7 +1091,7 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
1116 return ErrorFileSystem;1091 return ErrorFileSystem;
1117 }1092 }
1118 }1093 }
1119 Error result = os_fetch_file(f, out_contents, skip_shebang);1094 Error result = os_fetch_file(f, out_contents);
1120 fclose(f);1095 fclose(f);
1121 return result;1096 return result;
1122}1097}
...@@ -1772,8 +1747,14 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {...@@ -1772,8 +1747,14 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {
1772 // TODO use /etc/passwd1747 // TODO use /etc/passwd
1773 return ErrorFileNotFound;1748 return ErrorFileNotFound;
1774 }1749 }
1775 buf_resize(out_path, 0);1750 if (home_dir[0] == 0) {
1776 buf_appendf(out_path, "%s/.local/share/%s", home_dir, appname);1751 return ErrorFileNotFound;
1752 }
1753 buf_init_from_str(out_path, home_dir);
1754 if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') {
1755 buf_append_char(out_path, '/');
1756 }
1757 buf_appendf(out_path, ".local/share/%s", appname);
1777 return ErrorNone;1758 return ErrorNone;
1778#endif1759#endif
1779}1760}
...@@ -2081,11 +2062,13 @@ Error os_file_overwrite(OsFile file, Buf *contents) {...@@ -2081,11 +2062,13 @@ Error os_file_overwrite(OsFile file, Buf *contents) {
2081#endif2062#endif
2082}2063}
20832064
2084void os_file_close(OsFile file) {2065void os_file_close(OsFile *file) {
2085#if defined(ZIG_OS_WINDOWS)2066#if defined(ZIG_OS_WINDOWS)
2086 CloseHandle(file);2067 CloseHandle(*file);
2068 *file = NULL;
2087#else2069#else
2088 close(file);2070 close(*file);
2071 *file = -1;
2089#endif2072#endif
2090}2073}
20912074
src/os.hpp+3-3
...@@ -121,13 +121,13 @@ Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);...@@ -121,13 +121,13 @@ Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
121Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);121Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
122Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);122Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
123Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);123Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
124void os_file_close(OsFile file);124void os_file_close(OsFile *file);
125125
126Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);126Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
127Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);127Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
128128
129Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);129Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
130Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);130Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);
131131
132Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);132Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
133133
src/parser.cpp+57-57
...@@ -577,7 +577,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) {...@@ -577,7 +577,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) {
577577
578// TopLevelDecl578// TopLevelDecl
579// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)579// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
580// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl580// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
581// / KEYWORD_use Expr SEMICOLON581// / KEYWORD_use Expr SEMICOLON
582static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {582static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
583 Token *first = eat_token_if(pc, TokenIdKeywordExport);583 Token *first = eat_token_if(pc, TokenIdKeywordExport);
...@@ -591,17 +591,22 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {...@@ -591,17 +591,22 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
591 lib_name = eat_token_if(pc, TokenIdStringLiteral);591 lib_name = eat_token_if(pc, TokenIdStringLiteral);
592592
593 if (first->id != TokenIdKeywordInline) {593 if (first->id != TokenIdKeywordInline) {
594 Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
594 AstNode *var_decl = ast_parse_var_decl(pc);595 AstNode *var_decl = ast_parse_var_decl(pc);
595 if (var_decl != nullptr) {596 if (var_decl != nullptr) {
596 assert(var_decl->type == NodeTypeVariableDeclaration);597 assert(var_decl->type == NodeTypeVariableDeclaration);
597 var_decl->line = first->start_line;598 var_decl->line = first->start_line;
598 var_decl->column = first->start_column;599 var_decl->column = first->start_column;
600 var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
599 var_decl->data.variable_declaration.visib_mod = visib_mod;601 var_decl->data.variable_declaration.visib_mod = visib_mod;
600 var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern;602 var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern;
601 var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport;603 var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport;
602 var_decl->data.variable_declaration.lib_name = token_buf(lib_name);604 var_decl->data.variable_declaration.lib_name = token_buf(lib_name);
603 return var_decl;605 return var_decl;
604 }606 }
607
608 if (thread_local_kw != nullptr)
609 put_back_token(pc);
605 }610 }
606611
607 AstNode *fn_proto = ast_parse_fn_proto(pc);612 AstNode *fn_proto = ast_parse_fn_proto(pc);
...@@ -632,13 +637,18 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {...@@ -632,13 +637,18 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
632 ast_invalid_token_error(pc, peek_token(pc));637 ast_invalid_token_error(pc, peek_token(pc));
633 }638 }
634639
640 Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
635 AstNode *var_decl = ast_parse_var_decl(pc);641 AstNode *var_decl = ast_parse_var_decl(pc);
636 if (var_decl != nullptr) {642 if (var_decl != nullptr) {
637 assert(var_decl->type == NodeTypeVariableDeclaration);643 assert(var_decl->type == NodeTypeVariableDeclaration);
638 var_decl->data.variable_declaration.visib_mod = visib_mod;644 var_decl->data.variable_declaration.visib_mod = visib_mod;
645 var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
639 return var_decl;646 return var_decl;
640 }647 }
641648
649 if (thread_local_kw != nullptr)
650 put_back_token(pc);
651
642 AstNode *fn_proto = ast_parse_fn_proto(pc);652 AstNode *fn_proto = ast_parse_fn_proto(pc);
643 if (fn_proto != nullptr) {653 if (fn_proto != nullptr) {
644 AstNode *body = ast_parse_block(pc);654 AstNode *body = ast_parse_block(pc);
...@@ -741,17 +751,12 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {...@@ -741,17 +751,12 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
741751
742// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON752// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
743static AstNode *ast_parse_var_decl(ParseContext *pc) {753static AstNode *ast_parse_var_decl(ParseContext *pc) {
744 Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
745 Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst);754 Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst);
746 if (mut_kw == nullptr)755 if (mut_kw == nullptr)
747 mut_kw = eat_token_if(pc, TokenIdKeywordVar);756 mut_kw = eat_token_if(pc, TokenIdKeywordVar);
748 if (mut_kw == nullptr) {757 if (mut_kw == nullptr)
749 if (thread_local_kw == nullptr) {758 return nullptr;
750 return nullptr;759
751 } else {
752 ast_invalid_token_error(pc, peek_token(pc));
753 }
754 }
755 Token *identifier = expect_token(pc, TokenIdSymbol);760 Token *identifier = expect_token(pc, TokenIdSymbol);
756 AstNode *type_expr = nullptr;761 AstNode *type_expr = nullptr;
757 if (eat_token_if(pc, TokenIdColon) != nullptr)762 if (eat_token_if(pc, TokenIdColon) != nullptr)
...@@ -766,7 +771,6 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {...@@ -766,7 +771,6 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
766 expect_token(pc, TokenIdSemicolon);771 expect_token(pc, TokenIdSemicolon);
767772
768 AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw);773 AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw);
769 res->data.variable_declaration.threadlocal_tok = thread_local_kw;
770 res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst;774 res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst;
771 res->data.variable_declaration.symbol = token_buf(identifier);775 res->data.variable_declaration.symbol = token_buf(identifier);
772 res->data.variable_declaration.type = type_expr;776 res->data.variable_declaration.type = type_expr;
...@@ -952,17 +956,10 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) {...@@ -952,17 +956,10 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) {
952956
953// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)957// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
954static AstNode *ast_parse_loop_statement(ParseContext *pc) {958static AstNode *ast_parse_loop_statement(ParseContext *pc) {
955 Token *label = ast_parse_block_label(pc);
956 Token *first = label;
957
958 Token *inline_token = eat_token_if(pc, TokenIdKeywordInline);959 Token *inline_token = eat_token_if(pc, TokenIdKeywordInline);
959 if (first == nullptr)
960 first = inline_token;
961
962 AstNode *for_statement = ast_parse_for_statement(pc);960 AstNode *for_statement = ast_parse_for_statement(pc);
963 if (for_statement != nullptr) {961 if (for_statement != nullptr) {
964 assert(for_statement->type == NodeTypeForExpr);962 assert(for_statement->type == NodeTypeForExpr);
965 for_statement->data.for_expr.name = token_buf(label);
966 for_statement->data.for_expr.is_inline = inline_token != nullptr;963 for_statement->data.for_expr.is_inline = inline_token != nullptr;
967 return for_statement;964 return for_statement;
968 }965 }
...@@ -970,12 +967,11 @@ static AstNode *ast_parse_loop_statement(ParseContext *pc) {...@@ -970,12 +967,11 @@ static AstNode *ast_parse_loop_statement(ParseContext *pc) {
970 AstNode *while_statement = ast_parse_while_statement(pc);967 AstNode *while_statement = ast_parse_while_statement(pc);
971 if (while_statement != nullptr) {968 if (while_statement != nullptr) {
972 assert(while_statement->type == NodeTypeWhileExpr);969 assert(while_statement->type == NodeTypeWhileExpr);
973 while_statement->data.while_expr.name = token_buf(label);
974 while_statement->data.while_expr.is_inline = inline_token != nullptr;970 while_statement->data.while_expr.is_inline = inline_token != nullptr;
975 return while_statement;971 return while_statement;
976 }972 }
977973
978 if (first != nullptr)974 if (inline_token != nullptr)
979 ast_invalid_token_error(pc, peek_token(pc));975 ast_invalid_token_error(pc, peek_token(pc));
980 return nullptr;976 return nullptr;
981}977}
...@@ -1117,7 +1113,7 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc) {...@@ -1117,7 +1113,7 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc) {
11171113
1118// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?1114// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?
1119static AstNode *ast_parse_compare_expr(ParseContext *pc) {1115static AstNode *ast_parse_compare_expr(ParseContext *pc) {
1120 return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_compare_op, ast_parse_bitwise_expr);1116 return ast_parse_bin_op_expr(pc, BinOpChainOnce, ast_parse_compare_op, ast_parse_bitwise_expr);
1121}1117}
11221118
1123// BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*1119// BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*
...@@ -1162,10 +1158,6 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) {...@@ -1162,10 +1158,6 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) {
1162// / Block1158// / Block
1163// / CurlySuffixExpr1159// / CurlySuffixExpr
1164static AstNode *ast_parse_primary_expr(ParseContext *pc) {1160static AstNode *ast_parse_primary_expr(ParseContext *pc) {
1165 AstNode *enum_lit = ast_parse_enum_lit(pc);
1166 if (enum_lit != nullptr)
1167 return enum_lit;
1168
1169 AstNode *asm_expr = ast_parse_asm_expr(pc);1161 AstNode *asm_expr = ast_parse_asm_expr(pc);
1170 if (asm_expr != nullptr)1162 if (asm_expr != nullptr)
1171 return asm_expr;1163 return asm_expr;
...@@ -1246,11 +1238,8 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) {...@@ -1246,11 +1238,8 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) {
1246 }1238 }
12471239
1248 AstNode *block = ast_parse_block(pc);1240 AstNode *block = ast_parse_block(pc);
1249 if (block != nullptr) {1241 if (block != nullptr)
1250 assert(block->type == NodeTypeBlock);
1251 block->data.block.name = token_buf(label);
1252 return block;1242 return block;
1253 }
12541243
1255 AstNode *curly_suffix = ast_parse_curly_suffix_expr(pc);1244 AstNode *curly_suffix = ast_parse_curly_suffix_expr(pc);
1256 if (curly_suffix != nullptr)1245 if (curly_suffix != nullptr)
...@@ -1503,6 +1492,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {...@@ -1503,6 +1492,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1503// <- BUILTINIDENTIFIER FnCallArguments1492// <- BUILTINIDENTIFIER FnCallArguments
1504// / CHAR_LITERAL1493// / CHAR_LITERAL
1505// / ContainerDecl1494// / ContainerDecl
1495// / DOT IDENTIFIER
1506// / ErrorSetDecl1496// / ErrorSetDecl
1507// / FLOAT1497// / FLOAT
1508// / FnProto1498// / FnProto
...@@ -1563,6 +1553,10 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {...@@ -1563,6 +1553,10 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
1563 if (container_decl != nullptr)1553 if (container_decl != nullptr)
1564 return container_decl;1554 return container_decl;
15651555
1556 AstNode *enum_lit = ast_parse_enum_lit(pc);
1557 if (enum_lit != nullptr)
1558 return enum_lit;
1559
1566 AstNode *error_set_decl = ast_parse_error_set_decl(pc);1560 AstNode *error_set_decl = ast_parse_error_set_decl(pc);
1567 if (error_set_decl != nullptr)1561 if (error_set_decl != nullptr)
1568 return error_set_decl;1562 return error_set_decl;
...@@ -1672,32 +1666,26 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {...@@ -1672,32 +1666,26 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
16721666
1673// ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto1667// ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto
1674static AstNode *ast_parse_container_decl(ParseContext *pc) {1668static AstNode *ast_parse_container_decl(ParseContext *pc) {
1675 Token *extern_token = eat_token_if(pc, TokenIdKeywordExtern);1669 Token *layout_token = eat_token_if(pc, TokenIdKeywordExtern);
1676 if (extern_token != nullptr) {1670 if (layout_token == nullptr)
1677 AstNode *res = ast_parse_container_decl_auto(pc);1671 layout_token = eat_token_if(pc, TokenIdKeywordPacked);
1678 if (res == nullptr) {
1679 put_back_token(pc);
1680 return nullptr;
1681 }
16821672
1683 assert(res->type == NodeTypeContainerDecl);1673 AstNode *res = ast_parse_container_decl_auto(pc);
1684 res->line = extern_token->start_line;1674 if (res == nullptr) {
1685 res->column = extern_token->start_column;1675 if (layout_token != nullptr)
1686 res->data.container_decl.layout = ContainerLayoutExtern;1676 put_back_token(pc);
1687 return res;1677 return nullptr;
1688 }1678 }
16891679
1690 Token *packed_token = eat_token_if(pc, TokenIdKeywordPacked);1680 assert(res->type == NodeTypeContainerDecl);
1691 if (packed_token != nullptr) {1681 if (layout_token != nullptr) {
1692 AstNode *res = ast_expect(pc, ast_parse_container_decl_auto);1682 res->line = layout_token->start_line;
1693 assert(res->type == NodeTypeContainerDecl);1683 res->column = layout_token->start_column;
1694 res->line = packed_token->start_line;1684 res->data.container_decl.layout = layout_token->id == TokenIdKeywordExtern
1695 res->column = packed_token->start_column;1685 ? ContainerLayoutExtern
1696 res->data.container_decl.layout = ContainerLayoutPacked;1686 : ContainerLayoutPacked;
1697 return res;
1698 }1687 }
16991688 return res;
1700 return ast_parse_container_decl_auto(pc);
1701}1689}
17021690
1703// ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE1691// ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE
...@@ -1971,7 +1959,14 @@ static AstNode *ast_parse_field_init(ParseContext *pc) {...@@ -1971,7 +1959,14 @@ static AstNode *ast_parse_field_init(ParseContext *pc) {
1971 return nullptr;1959 return nullptr;
19721960
1973 Token *name = expect_token(pc, TokenIdSymbol);1961 Token *name = expect_token(pc, TokenIdSymbol);
1974 expect_token(pc, TokenIdEq);1962 if (eat_token_if(pc, TokenIdEq) == nullptr) {
1963 // Because ".Name" can also be intepreted as an enum literal, we should put back
1964 // those two tokens again so that the parser can try to parse them as the enum
1965 // literal later.
1966 put_back_token(pc);
1967 put_back_token(pc);
1968 return nullptr;
1969 }
1975 AstNode *expr = ast_expect(pc, ast_parse_expr);1970 AstNode *expr = ast_expect(pc, ast_parse_expr);
19761971
1977 AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first);1972 AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first);
...@@ -2750,12 +2745,19 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) {...@@ -2750,12 +2745,19 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) {
2750}2745}
27512746
2752// ContainerDeclType2747// ContainerDeclType
2753// <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)?2748// <- KEYWORD_struct
2749// / KEYWORD_enum (LPAREN Expr RPAREN)?
2754// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?2750// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
2755static AstNode *ast_parse_container_decl_type(ParseContext *pc) {2751static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
2756 Token *first = eat_token_if(pc, TokenIdKeywordStruct);2752 Token *first = eat_token_if(pc, TokenIdKeywordStruct);
2757 if (first == nullptr)2753 if (first != nullptr) {
2758 first = eat_token_if(pc, TokenIdKeywordEnum);2754 AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
2755 res->data.container_decl.init_arg_expr = nullptr;
2756 res->data.container_decl.kind = ContainerKindStruct;
2757 return res;
2758 }
2759
2760 first = eat_token_if(pc, TokenIdKeywordEnum);
2759 if (first != nullptr) {2761 if (first != nullptr) {
2760 AstNode *init_arg_expr = nullptr;2762 AstNode *init_arg_expr = nullptr;
2761 if (eat_token_if(pc, TokenIdLParen) != nullptr) {2763 if (eat_token_if(pc, TokenIdLParen) != nullptr) {
...@@ -2764,9 +2766,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) {...@@ -2764,9 +2766,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
2764 }2766 }
2765 AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);2767 AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
2766 res->data.container_decl.init_arg_expr = init_arg_expr;2768 res->data.container_decl.init_arg_expr = init_arg_expr;
2767 res->data.container_decl.kind = first->id == TokenIdKeywordStruct2769 res->data.container_decl.kind = ContainerKindEnum;
2768 ? ContainerKindStruct
2769 : ContainerKindEnum;
2770 return res;2770 return res;
2771 }2771 }
27722772
src/target.cpp+26-1
...@@ -894,10 +894,25 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -894,10 +894,25 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
894 case CIntTypeCount:894 case CIntTypeCount:
895 zig_unreachable();895 zig_unreachable();
896 }896 }
897 case OsIOS:
898 switch (id) {
899 case CIntTypeShort:
900 case CIntTypeUShort:
901 return 16;
902 case CIntTypeInt:
903 case CIntTypeUInt:
904 return 32;
905 case CIntTypeLong:
906 case CIntTypeULong:
907 case CIntTypeLongLong:
908 case CIntTypeULongLong:
909 return 64;
910 case CIntTypeCount:
911 zig_unreachable();
912 }
897 case OsAnanas:913 case OsAnanas:
898 case OsCloudABI:914 case OsCloudABI:
899 case OsDragonFly:915 case OsDragonFly:
900 case OsIOS:
901 case OsKFreeBSD:916 case OsKFreeBSD:
902 case OsLv2:917 case OsLv2:
903 case OsSolaris:918 case OsSolaris:
...@@ -950,6 +965,8 @@ const char *target_exe_file_ext(const ZigTarget *target) {...@@ -950,6 +965,8 @@ const char *target_exe_file_ext(const ZigTarget *target) {
950 return ".exe";965 return ".exe";
951 } else if (target->os == OsUefi) {966 } else if (target->os == OsUefi) {
952 return ".efi";967 return ".efi";
968 } else if (target_is_wasm(target)) {
969 return ".wasm";
953 } else {970 } else {
954 return "";971 return "";
955 }972 }
...@@ -1350,6 +1367,14 @@ bool target_is_musl(const ZigTarget *target) {...@@ -1350,6 +1367,14 @@ bool target_is_musl(const ZigTarget *target) {
1350 return target->os == OsLinux && target_abi_is_musl(target->abi);1367 return target->os == OsLinux && target_abi_is_musl(target->abi);
1351}1368}
13521369
1370bool target_is_wasm(const ZigTarget *target) {
1371 return target->arch == ZigLLVM_wasm32 || target->arch == ZigLLVM_wasm64;
1372}
1373
1374bool target_is_single_threaded(const ZigTarget *target) {
1375 return target_is_wasm(target);
1376}
1377
1353ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {1378ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
1354 switch (os) {1379 switch (os) {
1355 case OsFreestanding:1380 case OsFreestanding:
src/target.hpp+2
...@@ -170,6 +170,8 @@ bool target_abi_is_gnu(ZigLLVM_EnvironmentType abi);...@@ -170,6 +170,8 @@ bool target_abi_is_gnu(ZigLLVM_EnvironmentType abi);
170bool target_abi_is_musl(ZigLLVM_EnvironmentType abi);170bool target_abi_is_musl(ZigLLVM_EnvironmentType abi);
171bool target_is_glibc(const ZigTarget *target);171bool target_is_glibc(const ZigTarget *target);
172bool target_is_musl(const ZigTarget *target);172bool target_is_musl(const ZigTarget *target);
173bool target_is_wasm(const ZigTarget *target);
174bool target_is_single_threaded(const ZigTarget *target);
173175
174uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);176uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
175177
src/translate_c.cpp+1628-1591
...@@ -76,10 +76,9 @@ struct TransScopeWhile {...@@ -76,10 +76,9 @@ struct TransScopeWhile {
76};76};
7777
78struct Context {78struct Context {
79 ZigList<ErrorMsg *> *errors;79 AstNode *root;
80 VisibMod visib_mod;80 VisibMod visib_mod;
81 bool want_export;81 bool want_export;
82 AstNode *root;
83 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;82 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
84 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;83 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
85 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;84 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
...@@ -112,19 +111,39 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren...@@ -112,19 +111,39 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren
112111
113static TransScopeBlock *trans_scope_block_find(TransScope *scope);112static TransScopeBlock *trans_scope_block_find(TransScope *scope);
114113
115static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl);114static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl);
116static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl);115static AstNode *resolve_enum_decl(Context *c, const ZigClangEnumDecl *enum_decl);
117static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl);116static AstNode *resolve_typedef_decl(Context *c, const ZigClangTypedefNameDecl *typedef_decl);
118117
119static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,118static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *stmt,
120 ResultUsed result_used, TransLRValue lrval,119 ResultUsed result_used, TransLRValue lrval,
121 AstNode **out_node, TransScope **out_child_scope,120 AstNode **out_node, TransScope **out_child_scope,
122 TransScope **out_node_scope);121 TransScope **out_node_scope);
123static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node);122static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt *stmt, AstNode **out_node);
124static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);123static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr, TransLRValue lrval);
125static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc);124static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc);
126static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);125static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceLocation source_loc);
127static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc);126static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope,
127 const ZigClangExpr *expr, TransLRValue lrval);
128static AstNode *trans_ap_value(Context *c, const ZigClangAPValue *ap_value, ZigClangQualType qt,
129 ZigClangSourceLocation source_loc);
130static bool c_is_unsigned_integer(Context *c, ZigClangQualType qt);
131
132static const ZigClangAPSInt *bitcast(const llvm::APSInt *src) {
133 return reinterpret_cast<const ZigClangAPSInt *>(src);
134}
135
136static const ZigClangAPValue *bitcast(const clang::APValue *src) {
137 return reinterpret_cast<const ZigClangAPValue *>(src);
138}
139
140static const ZigClangStmt *bitcast(const clang::Stmt *src) {
141 return reinterpret_cast<const ZigClangStmt *>(src);
142}
143
144static const ZigClangExpr *bitcast(const clang::Expr *src) {
145 return reinterpret_cast<const ZigClangExpr *>(src);
146}
128147
129static ZigClangSourceLocation bitcast(clang::SourceLocation src) {148static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
130 ZigClangSourceLocation dest;149 ZigClangSourceLocation dest;
...@@ -136,14 +155,14 @@ static ZigClangQualType bitcast(clang::QualType src) {...@@ -136,14 +155,14 @@ static ZigClangQualType bitcast(clang::QualType src) {
136 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));155 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));
137 return dest;156 return dest;
138}157}
139static clang::QualType bitcast(ZigClangQualType src) {158//static clang::QualType bitcast(ZigClangQualType src) {
140 clang::QualType dest;159// clang::QualType dest;
141 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));160// memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));
142 return dest;161// return dest;
143}162//}
144163
145ATTRIBUTE_PRINTF(3, 4)164ATTRIBUTE_PRINTF(3, 4)
146static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) {165static void emit_warning(Context *c, ZigClangSourceLocation sl, const char *format, ...) {
147 if (!c->warnings_on) {166 if (!c->warnings_on) {
148 return;167 return;
149 }168 }
...@@ -153,7 +172,6 @@ static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, cons...@@ -153,7 +172,6 @@ static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, cons
153 Buf *msg = buf_vprintf(format, ap);172 Buf *msg = buf_vprintf(format, ap);
154 va_end(ap);173 va_end(ap);
155174
156 ZigClangSourceLocation sl = bitcast(clang_sl);
157 const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,175 const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,
158 ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));176 ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));
159 Buf *path;177 Buf *path;
...@@ -489,107 +507,99 @@ static Buf *string_ref_to_buf(llvm::StringRef string_ref) {...@@ -489,107 +507,99 @@ static Buf *string_ref_to_buf(llvm::StringRef string_ref) {
489 return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());507 return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
490}508}
491509
492static const char *decl_name(const clang::Decl *decl) {510static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_int) {
493 const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl);
494 return (const char *)named_decl->getName().bytes_begin();
495}
496
497static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
498 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);511 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
499 node->data.int_literal.bigint = allocate<BigInt>(1);512 node->data.int_literal.bigint = allocate<BigInt>(1);
500 bool is_negative = aps_int.isSigned() && aps_int.isNegative();513 bool is_negative = ZigClangAPSInt_isSigned(aps_int) && ZigClangAPSInt_isNegative(aps_int);
501 if (!is_negative) {514 if (!is_negative) {
502 bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);515 bigint_init_data(node->data.int_literal.bigint,
516 ZigClangAPSInt_getRawData(aps_int),
517 ZigClangAPSInt_getNumWords(aps_int),
518 false);
503 return node;519 return node;
504 }520 }
505 llvm::APSInt negated = -aps_int;521 const ZigClangAPSInt *negated = ZigClangAPSInt_negate(aps_int);
506 bigint_init_data(node->data.int_literal.bigint, negated.getRawData(), negated.getNumWords(), true);522 bigint_init_data(node->data.int_literal.bigint, ZigClangAPSInt_getRawData(negated),
523 ZigClangAPSInt_getNumWords(negated), true);
524 ZigClangAPSInt_free(negated);
507 return node;525 return node;
526}
508527
528static AstNode *trans_create_node_apfloat(Context *c, const llvm::APFloat &ap_float) {
529 uint8_t buf[128];
530 size_t written = ap_float.convertToHexString((char *)buf, 0, false,
531 llvm::APFloat::rmNearestTiesToEven);
532 AstNode *node = trans_create_node(c, NodeTypeFloatLiteral);
533 node->data.float_literal.bigfloat = allocate<BigFloat>(1);
534 if (bigfloat_init_buf(node->data.float_literal.bigfloat, buf, written)) {
535 node->data.float_literal.overflow = true;
536 }
537 return node;
509}538}
510539
511static const clang::Type *qual_type_canon(clang::QualType qt) {540static const ZigClangType *qual_type_canon(ZigClangQualType qt) {
512 return qt.getCanonicalType().getTypePtr();541 ZigClangQualType canon = ZigClangQualType_getCanonicalType(qt);
542 return ZigClangQualType_getTypePtr(canon);
513}543}
514544
515static clang::QualType get_expr_qual_type(Context *c, const clang::Expr *expr) {545static ZigClangQualType get_expr_qual_type(Context *c, const ZigClangExpr *expr) {
516 // String literals in C are `char *` but they should really be `const char *`.546 // String literals in C are `char *` but they should really be `const char *`.
517 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {547 if (ZigClangExpr_getStmtClass(expr) == ZigClangStmt_ImplicitCastExprClass) {
518 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);548 const clang::ImplicitCastExpr *cast_expr = reinterpret_cast<const clang::ImplicitCastExpr *>(expr);
519 if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) {549 if ((ZigClangCK)cast_expr->getCastKind() == ZigClangCK_ArrayToPointerDecay) {
520 const clang::Expr *sub_expr = cast_expr->getSubExpr();550 const ZigClangExpr *sub_expr = bitcast(cast_expr->getSubExpr());
521 if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) {551 if (ZigClangExpr_getStmtClass(sub_expr) == ZigClangStmt_StringLiteralClass) {
522 clang::QualType array_qt = sub_expr->getType();552 ZigClangQualType array_qt = ZigClangExpr_getType(sub_expr);
523 const clang::ArrayType *array_type = static_cast<const clang::ArrayType *>(array_qt.getTypePtr());553 const clang::ArrayType *array_type = reinterpret_cast<const clang::ArrayType *>(
524 clang::QualType pointee_qt = array_type->getElementType();554 ZigClangQualType_getTypePtr(array_qt));
525 pointee_qt.addConst();555 ZigClangQualType pointee_qt = bitcast(array_type->getElementType());
526 return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt)));556 ZigClangQualType_addConst(&pointee_qt);
557 return ZigClangASTContext_getPointerType(c->ctx, pointee_qt);
527 }558 }
528 }559 }
529 }560 }
530 return expr->getType();561 return ZigClangExpr_getType(expr);
531}562}
532563
533static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) {564static ZigClangQualType get_expr_qual_type_before_implicit_cast(Context *c, const ZigClangExpr *expr) {
534 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {565 if (ZigClangExpr_getStmtClass(expr) == ZigClangStmt_ImplicitCastExprClass) {
535 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);566 const clang::ImplicitCastExpr *cast_expr = reinterpret_cast<const clang::ImplicitCastExpr *>(expr);
536 return get_expr_qual_type(c, cast_expr->getSubExpr());567 return get_expr_qual_type(c, bitcast(cast_expr->getSubExpr()));
537 }568 }
538 return expr->getType();569 return ZigClangExpr_getType(expr);
539}570}
540571
541static AstNode *get_expr_type(Context *c, const clang::Expr *expr) {572static AstNode *get_expr_type(Context *c, const ZigClangExpr *expr) {
542 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getBeginLoc());573 return trans_qual_type(c, get_expr_qual_type(c, expr), ZigClangExpr_getBeginLoc(expr));
543}
544
545static bool qual_types_equal(clang::QualType t1, clang::QualType t2) {
546 if (t1.isConstQualified() != t2.isConstQualified()) {
547 return false;
548 }
549 if (t1.isVolatileQualified() != t2.isVolatileQualified()) {
550 return false;
551 }
552 if (t1.isRestrictQualified() != t2.isRestrictQualified()) {
553 return false;
554 }
555 return t1.getTypePtr() == t2.getTypePtr();
556}574}
557575
558static bool is_c_void_type(AstNode *node) {576static bool is_c_void_type(AstNode *node) {
559 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));577 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
560}578}
561579
562static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) {580static bool qual_type_is_ptr(ZigClangQualType qt) {
563 clang::QualType t1 = get_expr_qual_type(c, expr1);581 const ZigClangType *ty = qual_type_canon(qt);
564 clang::QualType t2 = get_expr_qual_type(c, expr2);582 return ZigClangType_getTypeClass(ty) == ZigClangType_Pointer;
565
566 return qual_types_equal(t1, t2);
567}583}
568584
569static bool qual_type_is_ptr(clang::QualType qt) {585static const clang::FunctionProtoType *qual_type_get_fn_proto(ZigClangQualType qt, bool *is_ptr) {
570 const clang::Type *ty = qual_type_canon(qt);586 const ZigClangType *ty = qual_type_canon(qt);
571 return ty->getTypeClass() == clang::Type::Pointer;
572}
573
574static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) {
575 const clang::Type *ty = qual_type_canon(qt);
576 *is_ptr = false;587 *is_ptr = false;
577588
578 if (ty->getTypeClass() == clang::Type::Pointer) {589 if (ZigClangType_getTypeClass(ty) == ZigClangType_Pointer) {
579 *is_ptr = true;590 *is_ptr = true;
580 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);591 ZigClangQualType child_qt = ZigClangType_getPointeeType(ty);
581 clang::QualType child_qt = pointer_ty->getPointeeType();592 ty = ZigClangQualType_getTypePtr(child_qt);
582 ty = child_qt.getTypePtr();
583 }593 }
584594
585 if (ty->getTypeClass() == clang::Type::FunctionProto) {595 if (ZigClangType_getTypeClass(ty) == ZigClangType_FunctionProto) {
586 return static_cast<const clang::FunctionProtoType*>(ty);596 return reinterpret_cast<const clang::FunctionProtoType*>(ty);
587 }597 }
588598
589 return nullptr;599 return nullptr;
590}600}
591601
592static bool qual_type_is_fn_ptr(clang::QualType qt) {602static bool qual_type_is_fn_ptr(ZigClangQualType qt) {
593 bool is_ptr;603 bool is_ptr;
594 if (qual_type_get_fn_proto(qt, &is_ptr)) {604 if (qual_type_get_fn_proto(qt, &is_ptr)) {
595 return is_ptr;605 return is_ptr;
...@@ -598,31 +608,31 @@ static bool qual_type_is_fn_ptr(clang::QualType qt) {...@@ -598,31 +608,31 @@ static bool qual_type_is_fn_ptr(clang::QualType qt) {
598 return false;608 return false;
599}609}
600610
601static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) {611static uint32_t qual_type_int_bit_width(Context *c, const ZigClangQualType qt, ZigClangSourceLocation source_loc) {
602 const clang::Type *ty = qt.getTypePtr();612 const ZigClangType *ty = ZigClangQualType_getTypePtr(qt);
603 switch (ty->getTypeClass()) {613 switch (ZigClangType_getTypeClass(ty)) {
604 case clang::Type::Builtin:614 case ZigClangType_Builtin:
605 {615 {
606 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);616 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty);
607 switch (builtin_ty->getKind()) {617 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
608 case clang::BuiltinType::Char_U:618 case ZigClangBuiltinTypeChar_U:
609 case clang::BuiltinType::UChar:619 case ZigClangBuiltinTypeUChar:
610 case clang::BuiltinType::Char_S:620 case ZigClangBuiltinTypeChar_S:
611 case clang::BuiltinType::SChar:621 case ZigClangBuiltinTypeSChar:
612 return 8;622 return 8;
613 case clang::BuiltinType::UInt128:623 case ZigClangBuiltinTypeUInt128:
614 case clang::BuiltinType::Int128:624 case ZigClangBuiltinTypeInt128:
615 return 128;625 return 128;
616 default:626 default:
617 return 0;627 return 0;
618 }628 }
619 zig_unreachable();629 zig_unreachable();
620 }630 }
621 case clang::Type::Typedef:631 case ZigClangType_Typedef:
622 {632 {
623 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);633 const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
624 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();634 const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
625 const char *type_name = decl_name(typedef_decl);635 const char *type_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl);
626 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {636 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
627 return 8;637 return 8;
628 } else if (strcmp(type_name, "uint16_t") == 0 || strcmp(type_name, "int16_t") == 0) {638 } 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...@@ -642,8 +652,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, c
642}652}
643653
644654
645static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,655static AstNode *qual_type_to_log2_int_ref(Context *c, const ZigClangQualType qt,
646 const clang::SourceLocation &source_loc)656 ZigClangSourceLocation source_loc)
647{657{
648 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);658 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
649 if (int_bit_width != 0) {659 if (int_bit_width != 0) {
...@@ -675,37 +685,76 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,...@@ -675,37 +685,76 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,
675 return log2int_fn_call;685 return log2int_fn_call;
676}686}
677687
678static bool qual_type_child_is_fn_proto(const clang::QualType &qt) {688static bool qual_type_child_is_fn_proto(ZigClangQualType qt) {
679 if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) {689 const ZigClangType *ty = ZigClangQualType_getTypePtr(qt);
680 const clang::ParenType *paren_type = static_cast<const clang::ParenType *>(qt.getTypePtr());690 if (ZigClangType_getTypeClass(ty) == ZigClangType_Paren) {
691 const clang::ParenType *paren_type = reinterpret_cast<const clang::ParenType *>(ty);
681 if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) {692 if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) {
682 return true;693 return true;
683 }694 }
684 } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) {695 } else if (ZigClangType_getTypeClass(ty) == ZigClangType_Attributed) {
685 const clang::AttributedType *attr_type = static_cast<const clang::AttributedType *>(qt.getTypePtr());696 const clang::AttributedType *attr_type = reinterpret_cast<const clang::AttributedType *>(ty);
686 return qual_type_child_is_fn_proto(attr_type->getEquivalentType());697 return qual_type_child_is_fn_proto(bitcast(attr_type->getEquivalentType()));
687 }698 }
688 return false;699 return false;
689}700}
690701
691static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type,702static AstNode* trans_c_ptr_cast(Context *c, ZigClangSourceLocation source_location, ZigClangQualType dest_type,
692 clang::QualType src_type, AstNode *expr)703 ZigClangQualType src_type, AstNode *expr)
704{
705 const ZigClangType *ty = ZigClangQualType_getTypePtr(dest_type);
706 const ZigClangQualType child_type = ZigClangType_getPointeeType(ty);
707
708 AstNode *dest_type_node = trans_type(c, ty, source_location);
709 AstNode *child_type_node = trans_qual_type(c, child_type, source_location);
710
711 // Implicit downcasting from higher to lower alignment values is forbidden,
712 // use @alignCast to side-step this problem
713 AstNode *ptrcast_node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
714 ptrcast_node->data.fn_call_expr.params.append(dest_type_node);
715
716 if (ZigClangType_isVoidType(qual_type_canon(child_type))) {
717 // void has 1-byte alignment
718 ptrcast_node->data.fn_call_expr.params.append(expr);
719 } else {
720 AstNode *alignof_node = trans_create_node_builtin_fn_call_str(c, "alignOf");
721 alignof_node->data.fn_call_expr.params.append(child_type_node);
722 AstNode *aligncast_node = trans_create_node_builtin_fn_call_str(c, "alignCast");
723 aligncast_node->data.fn_call_expr.params.append(alignof_node);
724 aligncast_node->data.fn_call_expr.params.append(expr);
725
726 ptrcast_node->data.fn_call_expr.params.append(aligncast_node);
727 }
728
729 return ptrcast_node;
730}
731
732static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location, ZigClangQualType dest_type,
733 ZigClangQualType src_type, AstNode *expr)
693{734{
694 // The only way void pointer casts are valid C code, is if735 // The only way void pointer casts are valid C code, is if
695 // the value of the expression is ignored. We therefore just736 // the value of the expression is ignored. We therefore just
696 // return the expr, and let the system that ignores values737 // return the expr, and let the system that ignores values
697 // translate this correctly.738 // translate this correctly.
698 if (qual_type_canon(dest_type)->isVoidType()) {739 if (ZigClangType_isVoidType(qual_type_canon(dest_type))) {
699 return expr;740 return expr;
700 }741 }
701 if (qual_types_equal(dest_type, src_type)) {742 if (ZigClangQualType_eq(dest_type, src_type)) {
702 return expr;743 return expr;
703 }744 }
704 if (qual_type_is_ptr(dest_type) && qual_type_is_ptr(src_type)) {745 if (qual_type_is_ptr(dest_type) && qual_type_is_ptr(src_type)) {
705 AstNode *ptr_cast_node = trans_create_node_builtin_fn_call_str(c, "ptrCast");746 return trans_c_ptr_cast(c, source_location, dest_type, src_type, expr);
706 ptr_cast_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location));747 }
707 ptr_cast_node->data.fn_call_expr.params.append(expr);748 if (c_is_unsigned_integer(c, dest_type) && qual_type_is_ptr(src_type)) {
708 return ptr_cast_node;749 AstNode *addr_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
750 addr_node->data.fn_call_expr.params.append(expr);
751 return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), addr_node);
752 }
753 if (c_is_unsigned_integer(c, src_type) && qual_type_is_ptr(dest_type)) {
754 AstNode *ptr_node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
755 ptr_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location));
756 ptr_node->data.fn_call_expr.params.append(expr);
757 return ptr_node;
709 }758 }
710 // TODO: maybe widen to increase size759 // TODO: maybe widen to increase size
711 // TODO: maybe bitcast to change sign760 // TODO: maybe bitcast to change sign
...@@ -713,72 +762,72 @@ static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_loc...@@ -713,72 +762,72 @@ static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_loc
713 return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);762 return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);
714}763}
715764
716static bool c_is_signed_integer(Context *c, clang::QualType qt) {765static bool c_is_signed_integer(Context *c, ZigClangQualType qt) {
717 const clang::Type *c_type = qual_type_canon(qt);766 const ZigClangType *c_type = qual_type_canon(qt);
718 if (c_type->getTypeClass() != clang::Type::Builtin)767 if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
719 return false;768 return false;
720 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);769 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
721 switch (builtin_ty->getKind()) {770 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
722 case clang::BuiltinType::SChar:771 case ZigClangBuiltinTypeSChar:
723 case clang::BuiltinType::Short:772 case ZigClangBuiltinTypeShort:
724 case clang::BuiltinType::Int:773 case ZigClangBuiltinTypeInt:
725 case clang::BuiltinType::Long:774 case ZigClangBuiltinTypeLong:
726 case clang::BuiltinType::LongLong:775 case ZigClangBuiltinTypeLongLong:
727 case clang::BuiltinType::Int128:776 case ZigClangBuiltinTypeInt128:
728 case clang::BuiltinType::WChar_S:777 case ZigClangBuiltinTypeWChar_S:
729 return true;778 return true;
730 default:779 default:
731 return false;780 return false;
732 }781 }
733}782}
734783
735static bool c_is_unsigned_integer(Context *c, clang::QualType qt) {784static bool c_is_unsigned_integer(Context *c, ZigClangQualType qt) {
736 const clang::Type *c_type = qual_type_canon(qt);785 const ZigClangType *c_type = qual_type_canon(qt);
737 if (c_type->getTypeClass() != clang::Type::Builtin)786 if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
738 return false;787 return false;
739 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);788 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
740 switch (builtin_ty->getKind()) {789 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
741 case clang::BuiltinType::Char_U:790 case ZigClangBuiltinTypeChar_U:
742 case clang::BuiltinType::UChar:791 case ZigClangBuiltinTypeUChar:
743 case clang::BuiltinType::Char_S:792 case ZigClangBuiltinTypeChar_S:
744 case clang::BuiltinType::UShort:793 case ZigClangBuiltinTypeUShort:
745 case clang::BuiltinType::UInt:794 case ZigClangBuiltinTypeUInt:
746 case clang::BuiltinType::ULong:795 case ZigClangBuiltinTypeULong:
747 case clang::BuiltinType::ULongLong:796 case ZigClangBuiltinTypeULongLong:
748 case clang::BuiltinType::UInt128:797 case ZigClangBuiltinTypeUInt128:
749 case clang::BuiltinType::WChar_U:798 case ZigClangBuiltinTypeWChar_U:
750 return true;799 return true;
751 default:800 default:
752 return false;801 return false;
753 }802 }
754}803}
755804
756static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) {805static bool c_is_builtin_type(Context *c, ZigClangQualType qt, ZigClangBuiltinTypeKind kind) {
757 const clang::Type *c_type = qual_type_canon(qt);806 const ZigClangType *c_type = qual_type_canon(qt);
758 if (c_type->getTypeClass() != clang::Type::Builtin)807 if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
759 return false;808 return false;
760 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);809 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
761 return builtin_ty->getKind() == kind;810 return ZigClangBuiltinType_getKind(builtin_ty) == kind;
762}811}
763812
764static bool c_is_float(Context *c, clang::QualType qt) {813static bool c_is_float(Context *c, ZigClangQualType qt) {
765 const clang::Type *c_type = qt.getTypePtr();814 const ZigClangType *c_type = ZigClangQualType_getTypePtr(qt);
766 if (c_type->getTypeClass() != clang::Type::Builtin)815 if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
767 return false;816 return false;
768 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);817 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
769 switch (builtin_ty->getKind()) {818 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
770 case clang::BuiltinType::Half:819 case ZigClangBuiltinTypeHalf:
771 case clang::BuiltinType::Float:820 case ZigClangBuiltinTypeFloat:
772 case clang::BuiltinType::Double:821 case ZigClangBuiltinTypeDouble:
773 case clang::BuiltinType::Float128:822 case ZigClangBuiltinTypeFloat128:
774 case clang::BuiltinType::LongDouble:823 case ZigClangBuiltinTypeLongDouble:
775 return true;824 return true;
776 default:825 default:
777 return false;826 return false;
778 }827 }
779}828}
780829
781static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {830static bool qual_type_has_wrapping_overflow(Context *c, ZigClangQualType qt) {
782 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {831 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
783 // float and signed integer overflow is undefined behavior.832 // float and signed integer overflow is undefined behavior.
784 return false;833 return false;
...@@ -788,181 +837,182 @@ static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {...@@ -788,181 +837,182 @@ static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {
788 }837 }
789}838}
790839
791static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {840static bool type_is_opaque(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
792 switch (ty->getTypeClass()) {841 switch (ZigClangType_getTypeClass(ty)) {
793 case clang::Type::Builtin: {842 case ZigClangType_Builtin: {
794 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);843 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty);
795 return builtin_ty->getKind() == clang::BuiltinType::Void;844 return ZigClangBuiltinType_getKind(builtin_ty) == ZigClangBuiltinTypeVoid;
796 }845 }
797 case clang::Type::Record: {846 case ZigClangType_Record: {
798 const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);847 const clang::RecordType *record_ty = reinterpret_cast<const clang::RecordType*>(ty);
799 return record_ty->getDecl()->getDefinition() == nullptr;848 return record_ty->getDecl()->getDefinition() == nullptr;
800 }849 }
801 case clang::Type::Elaborated: {850 case ZigClangType_Elaborated: {
802 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);851 const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty);
803 return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);852 ZigClangQualType qt = bitcast(elaborated_ty->getNamedType());
853 return type_is_opaque(c, ZigClangQualType_getTypePtr(qt), source_loc);
804 }854 }
805 case clang::Type::Typedef: {855 case ZigClangType_Typedef: {
806 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);856 const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
807 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();857 const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
808 return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);858 ZigClangQualType underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
859 return type_is_opaque(c, ZigClangQualType_getTypePtr(underlying_type), source_loc);
809 }860 }
810 default:861 default:
811 return false;862 return false;
812 }863 }
813}864}
814865
815static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {866static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
816 switch (ty->getTypeClass()) {867 switch (ZigClangType_getTypeClass(ty)) {
817 case clang::Type::Builtin:868 case ZigClangType_Builtin:
818 {869 {
819 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);870 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType *>(ty);
820 switch (builtin_ty->getKind()) {871 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
821 case clang::BuiltinType::Void:872 case ZigClangBuiltinTypeVoid:
822 return trans_create_node_symbol_str(c, "c_void");873 return trans_create_node_symbol_str(c, "c_void");
823 case clang::BuiltinType::Bool:874 case ZigClangBuiltinTypeBool:
824 return trans_create_node_symbol_str(c, "bool");875 return trans_create_node_symbol_str(c, "bool");
825 case clang::BuiltinType::Char_U:876 case ZigClangBuiltinTypeChar_U:
826 case clang::BuiltinType::UChar:877 case ZigClangBuiltinTypeUChar:
827 case clang::BuiltinType::Char_S:878 case ZigClangBuiltinTypeChar_S:
828 case clang::BuiltinType::Char8:879 case ZigClangBuiltinTypeChar8:
829 return trans_create_node_symbol_str(c, "u8");880 return trans_create_node_symbol_str(c, "u8");
830 case clang::BuiltinType::SChar:881 case ZigClangBuiltinTypeSChar:
831 return trans_create_node_symbol_str(c, "i8");882 return trans_create_node_symbol_str(c, "i8");
832 case clang::BuiltinType::UShort:883 case ZigClangBuiltinTypeUShort:
833 return trans_create_node_symbol_str(c, "c_ushort");884 return trans_create_node_symbol_str(c, "c_ushort");
834 case clang::BuiltinType::UInt:885 case ZigClangBuiltinTypeUInt:
835 return trans_create_node_symbol_str(c, "c_uint");886 return trans_create_node_symbol_str(c, "c_uint");
836 case clang::BuiltinType::ULong:887 case ZigClangBuiltinTypeULong:
837 return trans_create_node_symbol_str(c, "c_ulong");888 return trans_create_node_symbol_str(c, "c_ulong");
838 case clang::BuiltinType::ULongLong:889 case ZigClangBuiltinTypeULongLong:
839 return trans_create_node_symbol_str(c, "c_ulonglong");890 return trans_create_node_symbol_str(c, "c_ulonglong");
840 case clang::BuiltinType::Short:891 case ZigClangBuiltinTypeShort:
841 return trans_create_node_symbol_str(c, "c_short");892 return trans_create_node_symbol_str(c, "c_short");
842 case clang::BuiltinType::Int:893 case ZigClangBuiltinTypeInt:
843 return trans_create_node_symbol_str(c, "c_int");894 return trans_create_node_symbol_str(c, "c_int");
844 case clang::BuiltinType::Long:895 case ZigClangBuiltinTypeLong:
845 return trans_create_node_symbol_str(c, "c_long");896 return trans_create_node_symbol_str(c, "c_long");
846 case clang::BuiltinType::LongLong:897 case ZigClangBuiltinTypeLongLong:
847 return trans_create_node_symbol_str(c, "c_longlong");898 return trans_create_node_symbol_str(c, "c_longlong");
848 case clang::BuiltinType::UInt128:899 case ZigClangBuiltinTypeUInt128:
849 return trans_create_node_symbol_str(c, "u128");900 return trans_create_node_symbol_str(c, "u128");
850 case clang::BuiltinType::Int128:901 case ZigClangBuiltinTypeInt128:
851 return trans_create_node_symbol_str(c, "i128");902 return trans_create_node_symbol_str(c, "i128");
852 case clang::BuiltinType::Float:903 case ZigClangBuiltinTypeFloat:
853 return trans_create_node_symbol_str(c, "f32");904 return trans_create_node_symbol_str(c, "f32");
854 case clang::BuiltinType::Double:905 case ZigClangBuiltinTypeDouble:
855 return trans_create_node_symbol_str(c, "f64");906 return trans_create_node_symbol_str(c, "f64");
856 case clang::BuiltinType::Float128:907 case ZigClangBuiltinTypeFloat128:
857 return trans_create_node_symbol_str(c, "f128");908 return trans_create_node_symbol_str(c, "f128");
858 case clang::BuiltinType::Float16:909 case ZigClangBuiltinTypeFloat16:
859 return trans_create_node_symbol_str(c, "f16");910 return trans_create_node_symbol_str(c, "f16");
860 case clang::BuiltinType::LongDouble:911 case ZigClangBuiltinTypeLongDouble:
861 return trans_create_node_symbol_str(c, "c_longdouble");912 return trans_create_node_symbol_str(c, "c_longdouble");
862 case clang::BuiltinType::WChar_U:913 case ZigClangBuiltinTypeWChar_U:
863 case clang::BuiltinType::Char16:914 case ZigClangBuiltinTypeChar16:
864 case clang::BuiltinType::Char32:915 case ZigClangBuiltinTypeChar32:
865 case clang::BuiltinType::WChar_S:916 case ZigClangBuiltinTypeWChar_S:
866 case clang::BuiltinType::Half:917 case ZigClangBuiltinTypeHalf:
867 case clang::BuiltinType::NullPtr:918 case ZigClangBuiltinTypeNullPtr:
868 case clang::BuiltinType::ObjCId:919 case ZigClangBuiltinTypeObjCId:
869 case clang::BuiltinType::ObjCClass:920 case ZigClangBuiltinTypeObjCClass:
870 case clang::BuiltinType::ObjCSel:921 case ZigClangBuiltinTypeObjCSel:
871 case clang::BuiltinType::OMPArraySection:922 case ZigClangBuiltinTypeOMPArraySection:
872 case clang::BuiltinType::Dependent:923 case ZigClangBuiltinTypeDependent:
873 case clang::BuiltinType::Overload:924 case ZigClangBuiltinTypeOverload:
874 case clang::BuiltinType::BoundMember:925 case ZigClangBuiltinTypeBoundMember:
875 case clang::BuiltinType::PseudoObject:926 case ZigClangBuiltinTypePseudoObject:
876 case clang::BuiltinType::UnknownAny:927 case ZigClangBuiltinTypeUnknownAny:
877 case clang::BuiltinType::BuiltinFn:928 case ZigClangBuiltinTypeBuiltinFn:
878 case clang::BuiltinType::ARCUnbridgedCast:929 case ZigClangBuiltinTypeARCUnbridgedCast:
879 case clang::BuiltinType::ShortAccum:930 case ZigClangBuiltinTypeShortAccum:
880 case clang::BuiltinType::Accum:931 case ZigClangBuiltinTypeAccum:
881 case clang::BuiltinType::LongAccum:932 case ZigClangBuiltinTypeLongAccum:
882 case clang::BuiltinType::UShortAccum:933 case ZigClangBuiltinTypeUShortAccum:
883 case clang::BuiltinType::UAccum:934 case ZigClangBuiltinTypeUAccum:
884 case clang::BuiltinType::ULongAccum:935 case ZigClangBuiltinTypeULongAccum:
885936
886 case clang::BuiltinType::OCLImage1dRO:937 case ZigClangBuiltinTypeOCLImage1dRO:
887 case clang::BuiltinType::OCLImage1dArrayRO:938 case ZigClangBuiltinTypeOCLImage1dArrayRO:
888 case clang::BuiltinType::OCLImage1dBufferRO:939 case ZigClangBuiltinTypeOCLImage1dBufferRO:
889 case clang::BuiltinType::OCLImage2dRO:940 case ZigClangBuiltinTypeOCLImage2dRO:
890 case clang::BuiltinType::OCLImage2dArrayRO:941 case ZigClangBuiltinTypeOCLImage2dArrayRO:
891 case clang::BuiltinType::OCLImage2dDepthRO:942 case ZigClangBuiltinTypeOCLImage2dDepthRO:
892 case clang::BuiltinType::OCLImage2dArrayDepthRO:943 case ZigClangBuiltinTypeOCLImage2dArrayDepthRO:
893 case clang::BuiltinType::OCLImage2dMSAARO:944 case ZigClangBuiltinTypeOCLImage2dMSAARO:
894 case clang::BuiltinType::OCLImage2dArrayMSAARO:945 case ZigClangBuiltinTypeOCLImage2dArrayMSAARO:
895 case clang::BuiltinType::OCLImage2dMSAADepthRO:946 case ZigClangBuiltinTypeOCLImage2dMSAADepthRO:
896 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:947 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO:
897 case clang::BuiltinType::OCLImage3dRO:948 case ZigClangBuiltinTypeOCLImage3dRO:
898 case clang::BuiltinType::OCLImage1dWO:949 case ZigClangBuiltinTypeOCLImage1dWO:
899 case clang::BuiltinType::OCLImage1dArrayWO:950 case ZigClangBuiltinTypeOCLImage1dArrayWO:
900 case clang::BuiltinType::OCLImage1dBufferWO:951 case ZigClangBuiltinTypeOCLImage1dBufferWO:
901 case clang::BuiltinType::OCLImage2dWO:952 case ZigClangBuiltinTypeOCLImage2dWO:
902 case clang::BuiltinType::OCLImage2dArrayWO:953 case ZigClangBuiltinTypeOCLImage2dArrayWO:
903 case clang::BuiltinType::OCLImage2dDepthWO:954 case ZigClangBuiltinTypeOCLImage2dDepthWO:
904 case clang::BuiltinType::OCLImage2dArrayDepthWO:955 case ZigClangBuiltinTypeOCLImage2dArrayDepthWO:
905 case clang::BuiltinType::OCLImage2dMSAAWO:956 case ZigClangBuiltinTypeOCLImage2dMSAAWO:
906 case clang::BuiltinType::OCLImage2dArrayMSAAWO:957 case ZigClangBuiltinTypeOCLImage2dArrayMSAAWO:
907 case clang::BuiltinType::OCLImage2dMSAADepthWO:958 case ZigClangBuiltinTypeOCLImage2dMSAADepthWO:
908 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:959 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO:
909 case clang::BuiltinType::OCLImage3dWO:960 case ZigClangBuiltinTypeOCLImage3dWO:
910 case clang::BuiltinType::OCLImage1dRW:961 case ZigClangBuiltinTypeOCLImage1dRW:
911 case clang::BuiltinType::OCLImage1dArrayRW:962 case ZigClangBuiltinTypeOCLImage1dArrayRW:
912 case clang::BuiltinType::OCLImage1dBufferRW:963 case ZigClangBuiltinTypeOCLImage1dBufferRW:
913 case clang::BuiltinType::OCLImage2dRW:964 case ZigClangBuiltinTypeOCLImage2dRW:
914 case clang::BuiltinType::OCLImage2dArrayRW:965 case ZigClangBuiltinTypeOCLImage2dArrayRW:
915 case clang::BuiltinType::OCLImage2dDepthRW:966 case ZigClangBuiltinTypeOCLImage2dDepthRW:
916 case clang::BuiltinType::OCLImage2dArrayDepthRW:967 case ZigClangBuiltinTypeOCLImage2dArrayDepthRW:
917 case clang::BuiltinType::OCLImage2dMSAARW:968 case ZigClangBuiltinTypeOCLImage2dMSAARW:
918 case clang::BuiltinType::OCLImage2dArrayMSAARW:969 case ZigClangBuiltinTypeOCLImage2dArrayMSAARW:
919 case clang::BuiltinType::OCLImage2dMSAADepthRW:970 case ZigClangBuiltinTypeOCLImage2dMSAADepthRW:
920 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:971 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW:
921 case clang::BuiltinType::OCLImage3dRW:972 case ZigClangBuiltinTypeOCLImage3dRW:
922 case clang::BuiltinType::OCLSampler:973 case ZigClangBuiltinTypeOCLSampler:
923 case clang::BuiltinType::OCLEvent:974 case ZigClangBuiltinTypeOCLEvent:
924 case clang::BuiltinType::OCLClkEvent:975 case ZigClangBuiltinTypeOCLClkEvent:
925 case clang::BuiltinType::OCLQueue:976 case ZigClangBuiltinTypeOCLQueue:
926 case clang::BuiltinType::OCLReserveID:977 case ZigClangBuiltinTypeOCLReserveID:
927 case clang::BuiltinType::ShortFract:978 case ZigClangBuiltinTypeShortFract:
928 case clang::BuiltinType::Fract:979 case ZigClangBuiltinTypeFract:
929 case clang::BuiltinType::LongFract:980 case ZigClangBuiltinTypeLongFract:
930 case clang::BuiltinType::UShortFract:981 case ZigClangBuiltinTypeUShortFract:
931 case clang::BuiltinType::UFract:982 case ZigClangBuiltinTypeUFract:
932 case clang::BuiltinType::ULongFract:983 case ZigClangBuiltinTypeULongFract:
933 case clang::BuiltinType::SatShortAccum:984 case ZigClangBuiltinTypeSatShortAccum:
934 case clang::BuiltinType::SatAccum:985 case ZigClangBuiltinTypeSatAccum:
935 case clang::BuiltinType::SatLongAccum:986 case ZigClangBuiltinTypeSatLongAccum:
936 case clang::BuiltinType::SatUShortAccum:987 case ZigClangBuiltinTypeSatUShortAccum:
937 case clang::BuiltinType::SatUAccum:988 case ZigClangBuiltinTypeSatUAccum:
938 case clang::BuiltinType::SatULongAccum:989 case ZigClangBuiltinTypeSatULongAccum:
939 case clang::BuiltinType::SatShortFract:990 case ZigClangBuiltinTypeSatShortFract:
940 case clang::BuiltinType::SatFract:991 case ZigClangBuiltinTypeSatFract:
941 case clang::BuiltinType::SatLongFract:992 case ZigClangBuiltinTypeSatLongFract:
942 case clang::BuiltinType::SatUShortFract:993 case ZigClangBuiltinTypeSatUShortFract:
943 case clang::BuiltinType::SatUFract:994 case ZigClangBuiltinTypeSatUFract:
944 case clang::BuiltinType::SatULongFract:995 case ZigClangBuiltinTypeSatULongFract:
945 case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:996 case ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload:
946 case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:997 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload:
947 case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:998 case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload:
948 case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:999 case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload:
949 case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:1000 case ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult:
950 case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:1001 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult:
951 case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:1002 case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult:
952 case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:1003 case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult:
953 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:1004 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout:
954 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:1005 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout:
955 case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:1006 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin:
956 case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:1007 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin:
957 emit_warning(c, source_loc, "unsupported builtin type");1008 emit_warning(c, source_loc, "unsupported builtin type");
958 return nullptr;1009 return nullptr;
959 }1010 }
960 break;1011 break;
961 }1012 }
962 case clang::Type::Pointer:1013 case ZigClangType_Pointer:
963 {1014 {
964 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);1015 ZigClangQualType child_qt = ZigClangType_getPointeeType(ty);
965 clang::QualType child_qt = pointer_ty->getPointeeType();
966 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);1016 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
967 if (child_node == nullptr) {1017 if (child_node == nullptr) {
968 emit_warning(c, source_loc, "pointer to unsupported type");1018 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...@@ -973,29 +1023,33 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
973 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);1023 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
974 }1024 }
9751025
976 if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {1026 if (type_is_opaque(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
977 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),1027 AstNode *pointer_node = trans_create_node_ptr_type(c,
978 child_qt.isVolatileQualified(), child_node, PtrLenSingle);1028 ZigClangQualType_isConstQualified(child_qt),
1029 ZigClangQualType_isVolatileQualified(child_qt),
1030 child_node, PtrLenSingle);
979 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);1031 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
980 } else {1032 } else {
981 return trans_create_node_ptr_type(c, child_qt.isConstQualified(),1033 return trans_create_node_ptr_type(c,
982 child_qt.isVolatileQualified(), child_node, PtrLenC);1034 ZigClangQualType_isConstQualified(child_qt),
1035 ZigClangQualType_isVolatileQualified(child_qt),
1036 child_node, PtrLenC);
983 }1037 }
984 }1038 }
985 case clang::Type::Typedef:1039 case ZigClangType_Typedef:
986 {1040 {
987 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);1041 const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
988 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();1042 const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
989 return resolve_typedef_decl(c, typedef_decl);1043 return resolve_typedef_decl(c, typedef_decl);
990 }1044 }
991 case clang::Type::Elaborated:1045 case ZigClangType_Elaborated:
992 {1046 {
993 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);1047 const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty);
994 switch (elaborated_ty->getKeyword()) {1048 switch (elaborated_ty->getKeyword()) {
995 case clang::ETK_Struct:1049 case clang::ETK_Struct:
996 case clang::ETK_Enum:1050 case clang::ETK_Enum:
997 case clang::ETK_Union:1051 case clang::ETK_Union:
998 return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);1052 return trans_qual_type(c, bitcast(elaborated_ty->getNamedType()), source_loc);
999 case clang::ETK_Interface:1053 case clang::ETK_Interface:
1000 case clang::ETK_Class:1054 case clang::ETK_Class:
1001 case clang::ETK_Typename:1055 case clang::ETK_Typename:
...@@ -1004,81 +1058,81 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc...@@ -1004,81 +1058,81 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
1004 return nullptr;1058 return nullptr;
1005 }1059 }
1006 }1060 }
1007 case clang::Type::FunctionProto:1061 case ZigClangType_FunctionProto:
1008 case clang::Type::FunctionNoProto:1062 case ZigClangType_FunctionNoProto:
1009 {1063 {
1010 const clang::FunctionType *fn_ty = static_cast<const clang::FunctionType*>(ty);1064 const ZigClangFunctionType *fn_ty = reinterpret_cast<const ZigClangFunctionType*>(ty);
10111065
1012 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);1066 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
1013 switch (fn_ty->getCallConv()) {1067 switch (ZigClangFunctionType_getCallConv(fn_ty)) {
1014 case clang::CC_C: // __attribute__((cdecl))1068 case ZigClangCallingConv_C: // __attribute__((cdecl))
1015 proto_node->data.fn_proto.cc = CallingConventionC;1069 proto_node->data.fn_proto.cc = CallingConventionC;
1016 proto_node->data.fn_proto.is_extern = true;1070 proto_node->data.fn_proto.is_extern = true;
1017 break;1071 break;
1018 case clang::CC_X86StdCall: // __attribute__((stdcall))1072 case ZigClangCallingConv_X86StdCall: // __attribute__((stdcall))
1019 proto_node->data.fn_proto.cc = CallingConventionStdcall;1073 proto_node->data.fn_proto.cc = CallingConventionStdcall;
1020 break;1074 break;
1021 case clang::CC_X86FastCall: // __attribute__((fastcall))1075 case ZigClangCallingConv_X86FastCall: // __attribute__((fastcall))
1022 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");1076 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
1023 return nullptr;1077 return nullptr;
1024 case clang::CC_X86ThisCall: // __attribute__((thiscall))1078 case ZigClangCallingConv_X86ThisCall: // __attribute__((thiscall))
1025 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");1079 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
1026 return nullptr;1080 return nullptr;
1027 case clang::CC_X86VectorCall: // __attribute__((vectorcall))1081 case ZigClangCallingConv_X86VectorCall: // __attribute__((vectorcall))
1028 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");1082 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
1029 return nullptr;1083 return nullptr;
1030 case clang::CC_X86Pascal: // __attribute__((pascal))1084 case ZigClangCallingConv_X86Pascal: // __attribute__((pascal))
1031 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");1085 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
1032 return nullptr;1086 return nullptr;
1033 case clang::CC_Win64: // __attribute__((ms_abi))1087 case ZigClangCallingConv_Win64: // __attribute__((ms_abi))
1034 emit_warning(c, source_loc, "unsupported calling convention: win64");1088 emit_warning(c, source_loc, "unsupported calling convention: win64");
1035 return nullptr;1089 return nullptr;
1036 case clang::CC_X86_64SysV: // __attribute__((sysv_abi))1090 case ZigClangCallingConv_X86_64SysV: // __attribute__((sysv_abi))
1037 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");1091 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
1038 return nullptr;1092 return nullptr;
1039 case clang::CC_X86RegCall:1093 case ZigClangCallingConv_X86RegCall:
1040 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");1094 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
1041 return nullptr;1095 return nullptr;
1042 case clang::CC_AAPCS: // __attribute__((pcs("aapcs")))1096 case ZigClangCallingConv_AAPCS: // __attribute__((pcs("aapcs")))
1043 emit_warning(c, source_loc, "unsupported calling convention: aapcs");1097 emit_warning(c, source_loc, "unsupported calling convention: aapcs");
1044 return nullptr;1098 return nullptr;
1045 case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))1099 case ZigClangCallingConv_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
1046 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");1100 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
1047 return nullptr;1101 return nullptr;
1048 case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))1102 case ZigClangCallingConv_IntelOclBicc: // __attribute__((intel_ocl_bicc))
1049 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");1103 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
1050 return nullptr;1104 return nullptr;
1051 case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target1105 case ZigClangCallingConv_SpirFunction: // default for OpenCL functions on SPIR target
1052 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");1106 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
1053 return nullptr;1107 return nullptr;
1054 case clang::CC_OpenCLKernel:1108 case ZigClangCallingConv_OpenCLKernel:
1055 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");1109 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
1056 return nullptr;1110 return nullptr;
1057 case clang::CC_Swift:1111 case ZigClangCallingConv_Swift:
1058 emit_warning(c, source_loc, "unsupported calling convention: Swift");1112 emit_warning(c, source_loc, "unsupported calling convention: Swift");
1059 return nullptr;1113 return nullptr;
1060 case clang::CC_PreserveMost:1114 case ZigClangCallingConv_PreserveMost:
1061 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");1115 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
1062 return nullptr;1116 return nullptr;
1063 case clang::CC_PreserveAll:1117 case ZigClangCallingConv_PreserveAll:
1064 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");1118 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
1065 return nullptr;1119 return nullptr;
1066 case clang::CC_AArch64VectorCall:1120 case ZigClangCallingConv_AArch64VectorCall:
1067 emit_warning(c, source_loc, "unsupported calling convention: AArch64VectorCall");1121 emit_warning(c, source_loc, "unsupported calling convention: AArch64VectorCall");
1068 return nullptr;1122 return nullptr;
1069 }1123 }
10701124
1071 if (fn_ty->getNoReturnAttr()) {1125 if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) {
1072 proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");1126 proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
1073 } else {1127 } else {
1074 proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_ty->getReturnType(),1128 proto_node->data.fn_proto.return_type = trans_qual_type(c,
1075 source_loc);1129 ZigClangFunctionType_getReturnType(fn_ty), source_loc);
1076 if (proto_node->data.fn_proto.return_type == nullptr) {1130 if (proto_node->data.fn_proto.return_type == nullptr) {
1077 emit_warning(c, source_loc, "unsupported function proto return type");1131 emit_warning(c, source_loc, "unsupported function proto return type");
1078 return nullptr;1132 return nullptr;
1079 }1133 }
1080 // convert c_void to actual void (only for return type)1134 // convert c_void to actual void (only for return type)
1081 // we do want to look at the AstNode instead of clang::QualType, because1135 // we do want to look at the AstNode instead of ZigClangQualType, because
1082 // if they do something like:1136 // if they do something like:
1083 // typedef Foo void;1137 // typedef Foo void;
1084 // void foo(void) -> Foo;1138 // void foo(void) -> Foo;
...@@ -1094,17 +1148,17 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc...@@ -1094,17 +1148,17 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
1094 proto_node->data.fn_proto.name = buf_create_from_str(fn_name);1148 proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
1095 }1149 }
10961150
1097 if (ty->getTypeClass() == clang::Type::FunctionNoProto) {1151 if (ZigClangType_getTypeClass(ty) == ZigClangType_FunctionNoProto) {
1098 return proto_node;1152 return proto_node;
1099 }1153 }
11001154
1101 const clang::FunctionProtoType *fn_proto_ty = static_cast<const clang::FunctionProtoType*>(ty);1155 const ZigClangFunctionProtoType *fn_proto_ty = reinterpret_cast<const ZigClangFunctionProtoType*>(ty);
11021156
1103 proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();1157 proto_node->data.fn_proto.is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty);
1104 size_t param_count = fn_proto_ty->getNumParams();1158 size_t param_count = ZigClangFunctionProtoType_getNumParams(fn_proto_ty);
11051159
1106 for (size_t i = 0; i < param_count; i += 1) {1160 for (size_t i = 0; i < param_count; i += 1) {
1107 clang::QualType qt = fn_proto_ty->getParamType(i);1161 ZigClangQualType qt = ZigClangFunctionProtoType_getParamType(fn_proto_ty, i);
1108 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);1162 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
11091163
1110 if (param_type_node == nullptr) {1164 if (param_type_node == nullptr) {
...@@ -1118,7 +1172,7 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc...@@ -1118,7 +1172,7 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
1118 if (param_name != nullptr) {1172 if (param_name != nullptr) {
1119 param_node->data.param_decl.name = buf_create_from_str(param_name);1173 param_node->data.param_decl.name = buf_create_from_str(param_name);
1120 }1174 }
1121 param_node->data.param_decl.is_noalias = qt.isRestrictQualified();1175 param_node->data.param_decl.is_noalias = ZigClangQualType_isRestrictQualified(qt);
1122 param_node->data.param_decl.type = param_type_node;1176 param_node->data.param_decl.type = param_type_node;
1123 proto_node->data.fn_proto.params.append(param_node);1177 proto_node->data.fn_proto.params.append(param_node);
1124 }1178 }
...@@ -1127,20 +1181,20 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc...@@ -1127,20 +1181,20 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
11271181
1128 return proto_node;1182 return proto_node;
1129 }1183 }
1130 case clang::Type::Record:1184 case ZigClangType_Record:
1131 {1185 {
1132 const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);1186 const ZigClangRecordType *record_ty = reinterpret_cast<const ZigClangRecordType*>(ty);
1133 return resolve_record_decl(c, record_ty->getDecl());1187 return resolve_record_decl(c, ZigClangRecordType_getDecl(record_ty));
1134 }1188 }
1135 case clang::Type::Enum:1189 case ZigClangType_Enum:
1136 {1190 {
1137 const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);1191 const ZigClangEnumType *enum_ty = reinterpret_cast<const ZigClangEnumType*>(ty);
1138 return resolve_enum_decl(c, enum_ty->getDecl());1192 return resolve_enum_decl(c, ZigClangEnumType_getDecl(enum_ty));
1139 }1193 }
1140 case clang::Type::ConstantArray:1194 case ZigClangType_ConstantArray:
1141 {1195 {
1142 const clang::ConstantArrayType *const_arr_ty = static_cast<const clang::ConstantArrayType *>(ty);1196 const clang::ConstantArrayType *const_arr_ty = reinterpret_cast<const clang::ConstantArrayType *>(ty);
1143 AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);1197 AstNode *child_type_node = trans_qual_type(c, bitcast(const_arr_ty->getElementType()), source_loc);
1144 if (child_type_node == nullptr) {1198 if (child_type_node == nullptr) {
1145 emit_warning(c, source_loc, "unresolved array element type");1199 emit_warning(c, source_loc, "unresolved array element type");
1146 return nullptr;1200 return nullptr;
...@@ -1149,83 +1203,87 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc...@@ -1149,83 +1203,87 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc
1149 AstNode *size_node = trans_create_node_unsigned(c, size);1203 AstNode *size_node = trans_create_node_unsigned(c, size);
1150 return trans_create_node_array_type(c, size_node, child_type_node);1204 return trans_create_node_array_type(c, size_node, child_type_node);
1151 }1205 }
1152 case clang::Type::Paren:1206 case ZigClangType_Paren:
1153 {1207 {
1154 const clang::ParenType *paren_ty = static_cast<const clang::ParenType *>(ty);1208 const clang::ParenType *paren_ty = reinterpret_cast<const clang::ParenType *>(ty);
1155 return trans_qual_type(c, paren_ty->getInnerType(), source_loc);1209 return trans_qual_type(c, bitcast(paren_ty->getInnerType()), source_loc);
1156 }1210 }
1157 case clang::Type::Decayed:1211 case ZigClangType_Decayed:
1158 {1212 {
1159 const clang::DecayedType *decayed_ty = static_cast<const clang::DecayedType *>(ty);1213 const clang::DecayedType *decayed_ty = reinterpret_cast<const clang::DecayedType *>(ty);
1160 return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);1214 return trans_qual_type(c, bitcast(decayed_ty->getDecayedType()), source_loc);
1161 }1215 }
1162 case clang::Type::Attributed:1216 case ZigClangType_Attributed:
1163 {1217 {
1164 const clang::AttributedType *attributed_ty = static_cast<const clang::AttributedType *>(ty);1218 const clang::AttributedType *attributed_ty = reinterpret_cast<const clang::AttributedType *>(ty);
1165 return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);1219 return trans_qual_type(c, bitcast(attributed_ty->getEquivalentType()), source_loc);
1166 }1220 }
1167 case clang::Type::IncompleteArray:1221 case ZigClangType_IncompleteArray:
1168 {1222 {
1169 const clang::IncompleteArrayType *incomplete_array_ty = static_cast<const clang::IncompleteArrayType *>(ty);1223 const clang::IncompleteArrayType *incomplete_array_ty = reinterpret_cast<const clang::IncompleteArrayType *>(ty);
1170 clang::QualType child_qt = incomplete_array_ty->getElementType();1224 ZigClangQualType child_qt = bitcast(incomplete_array_ty->getElementType());
1171 AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);1225 AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);
1172 if (child_type_node == nullptr) {1226 if (child_type_node == nullptr) {
1173 emit_warning(c, source_loc, "unresolved array element type");1227 emit_warning(c, source_loc, "unresolved array element type");
1174 return nullptr;1228 return nullptr;
1175 }1229 }
1176 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),1230 AstNode *pointer_node = trans_create_node_ptr_type(c,
1177 child_qt.isVolatileQualified(), child_type_node, PtrLenC);1231 ZigClangQualType_isConstQualified(child_qt),
1232 ZigClangQualType_isVolatileQualified(child_qt),
1233 child_type_node, PtrLenC);
1178 return pointer_node;1234 return pointer_node;
1179 }1235 }
1180 case clang::Type::BlockPointer:1236 case ZigClangType_BlockPointer:
1181 case clang::Type::LValueReference:1237 case ZigClangType_LValueReference:
1182 case clang::Type::RValueReference:1238 case ZigClangType_RValueReference:
1183 case clang::Type::MemberPointer:1239 case ZigClangType_MemberPointer:
1184 case clang::Type::VariableArray:1240 case ZigClangType_VariableArray:
1185 case clang::Type::DependentSizedArray:1241 case ZigClangType_DependentSizedArray:
1186 case clang::Type::DependentSizedExtVector:1242 case ZigClangType_DependentSizedExtVector:
1187 case clang::Type::Vector:1243 case ZigClangType_Vector:
1188 case clang::Type::ExtVector:1244 case ZigClangType_ExtVector:
1189 case clang::Type::UnresolvedUsing:1245 case ZigClangType_UnresolvedUsing:
1190 case clang::Type::Adjusted:1246 case ZigClangType_Adjusted:
1191 case clang::Type::TypeOfExpr:1247 case ZigClangType_TypeOfExpr:
1192 case clang::Type::TypeOf:1248 case ZigClangType_TypeOf:
1193 case clang::Type::Decltype:1249 case ZigClangType_Decltype:
1194 case clang::Type::UnaryTransform:1250 case ZigClangType_UnaryTransform:
1195 case clang::Type::TemplateTypeParm:1251 case ZigClangType_TemplateTypeParm:
1196 case clang::Type::SubstTemplateTypeParm:1252 case ZigClangType_SubstTemplateTypeParm:
1197 case clang::Type::SubstTemplateTypeParmPack:1253 case ZigClangType_SubstTemplateTypeParmPack:
1198 case clang::Type::TemplateSpecialization:1254 case ZigClangType_TemplateSpecialization:
1199 case clang::Type::Auto:1255 case ZigClangType_Auto:
1200 case clang::Type::InjectedClassName:1256 case ZigClangType_InjectedClassName:
1201 case clang::Type::DependentName:1257 case ZigClangType_DependentName:
1202 case clang::Type::DependentTemplateSpecialization:1258 case ZigClangType_DependentTemplateSpecialization:
1203 case clang::Type::PackExpansion:1259 case ZigClangType_PackExpansion:
1204 case clang::Type::ObjCObject:1260 case ZigClangType_ObjCObject:
1205 case clang::Type::ObjCInterface:1261 case ZigClangType_ObjCInterface:
1206 case clang::Type::Complex:1262 case ZigClangType_Complex:
1207 case clang::Type::ObjCObjectPointer:1263 case ZigClangType_ObjCObjectPointer:
1208 case clang::Type::Atomic:1264 case ZigClangType_Atomic:
1209 case clang::Type::Pipe:1265 case ZigClangType_Pipe:
1210 case clang::Type::ObjCTypeParam:1266 case ZigClangType_ObjCTypeParam:
1211 case clang::Type::DeducedTemplateSpecialization:1267 case ZigClangType_DeducedTemplateSpecialization:
1212 case clang::Type::DependentAddressSpace:1268 case ZigClangType_DependentAddressSpace:
1213 case clang::Type::DependentVector:1269 case ZigClangType_DependentVector:
1214 emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());1270 emit_warning(c, source_loc, "unsupported type: '%s'", ZigClangType_getTypeClassName(ty));
1215 return nullptr;1271 return nullptr;
1216 }1272 }
1217 zig_unreachable();1273 zig_unreachable();
1218}1274}
12191275
1220static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) {1276static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceLocation source_loc) {
1221 return trans_type(c, qt.getTypePtr(), source_loc);1277 return trans_type(c, ZigClangQualType_getTypePtr(qt), source_loc);
1222}1278}
12231279
1224static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,1280static int trans_compound_stmt_inline(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt,
1225 AstNode *block_node, TransScope **out_node_scope)1281 AstNode *block_node, TransScope **out_node_scope)
1226{1282{
1227 assert(block_node->type == NodeTypeBlock);1283 assert(block_node->type == NodeTypeBlock);
1228 for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {1284 for (ZigClangCompoundStmt_const_body_iterator it = ZigClangCompoundStmt_body_begin(stmt),
1285 end_it = ZigClangCompoundStmt_body_end(stmt); it != end_it; ++it)
1286 {
1229 AstNode *child_node;1287 AstNode *child_node;
1230 scope = trans_stmt(c, scope, *it, &child_node);1288 scope = trans_stmt(c, scope, *it, &child_node);
1231 if (scope == nullptr)1289 if (scope == nullptr)
...@@ -1239,7 +1297,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang...@@ -1239,7 +1297,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang
1239 return ErrorNone;1297 return ErrorNone;
1240}1298}
12411299
1242static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,1300static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt,
1243 TransScope **out_node_scope)1301 TransScope **out_node_scope)
1244{1302{
1245 TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);1303 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::...@@ -1251,7 +1309,7 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::
1251static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope,1309static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope,
1252 const clang::StmtExpr *stmt, TransScope **out_node_scope)1310 const clang::StmtExpr *stmt, TransScope **out_node_scope)
1253{1311{
1254 AstNode *block = trans_compound_stmt(c, scope, stmt->getSubStmt(), out_node_scope);1312 AstNode *block = trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt->getSubStmt(), out_node_scope);
1255 if (block == nullptr)1313 if (block == nullptr)
1256 return block;1314 return block;
1257 assert(block->type == NodeTypeBlock);1315 assert(block->type == NodeTypeBlock);
...@@ -1274,7 +1332,7 @@ static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *...@@ -1274,7 +1332,7 @@ static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *
1274}1332}
12751333
1276static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {1334static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {
1277 const clang::Expr *value_expr = stmt->getRetValue();1335 const ZigClangExpr *value_expr = bitcast(stmt->getRetValue());
1278 if (value_expr == nullptr) {1336 if (value_expr == nullptr) {
1279 return trans_create_node(c, NodeTypeReturnExpr);1337 return trans_create_node(c, NodeTypeReturnExpr);
1280 } else {1338 } else {
...@@ -1289,22 +1347,62 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::Re...@@ -1289,22 +1347,62 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::Re
1289static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const clang::IntegerLiteral *stmt) {1347static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const clang::IntegerLiteral *stmt) {
1290 clang::Expr::EvalResult result;1348 clang::Expr::EvalResult result;
1291 if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {1349 if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
1292 emit_warning(c, stmt->getBeginLoc(), "invalid integer literal");1350 emit_warning(c, bitcast(stmt->getBeginLoc()), "invalid integer literal");
1351 return nullptr;
1352 }
1353 AstNode *node = trans_create_node_apint(c, bitcast(&result.Val.getInt()));
1354 return maybe_suppress_result(c, result_used, node);
1355}
1356
1357static AstNode *trans_floating_literal(Context *c, ResultUsed result_used, const clang::FloatingLiteral *stmt) {
1358 llvm::APFloat result{0.0f};
1359 if (!stmt->EvaluateAsFloat(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
1360 emit_warning(c, bitcast(stmt->getBeginLoc()), "invalid floating literal");
1293 return nullptr;1361 return nullptr;
1294 }1362 }
1295 AstNode *node = trans_create_node_apint(c, result.Val.getInt());1363 AstNode *node = trans_create_node_apfloat(c, result);
1296 return maybe_suppress_result(c, result_used, node);1364 return maybe_suppress_result(c, result_used, node);
1297}1365}
12981366
1367static AstNode *trans_character_literal(Context *c, ResultUsed result_used, const clang::CharacterLiteral *stmt) {
1368 switch (stmt->getKind()) {
1369 case clang::CharacterLiteral::CharacterKind::Ascii:
1370 {
1371 unsigned val = stmt->getValue();
1372 // C has a somewhat obscure feature called multi-character character
1373 // constant
1374 if (val > 255)
1375 return trans_create_node_unsigned(c, val);
1376 }
1377 // fallthrough
1378 case clang::CharacterLiteral::CharacterKind::UTF8:
1379 {
1380 AstNode *node = trans_create_node(c, NodeTypeCharLiteral);
1381 node->data.char_literal.value = stmt->getValue();
1382 return maybe_suppress_result(c, result_used, node);
1383 }
1384 case clang::CharacterLiteral::CharacterKind::UTF16:
1385 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF16 character literals");
1386 return nullptr;
1387 case clang::CharacterLiteral::CharacterKind::UTF32:
1388 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF32 character literals");
1389 return nullptr;
1390 case clang::CharacterLiteral::CharacterKind::Wide:
1391 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support wide character literals");
1392 return nullptr;
1393 }
1394 zig_unreachable();
1395}
1396
1299static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) {1397static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) {
1300 clang::Expr::EvalResult result;1398 clang::Expr::EvalResult result;
1301 if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen,1399 if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen,
1302 *reinterpret_cast<clang::ASTContext *>(c->ctx)))1400 *reinterpret_cast<clang::ASTContext *>(c->ctx)))
1303 {1401 {
1304 emit_warning(c, expr->getBeginLoc(), "invalid constant expression");1402 emit_warning(c, bitcast(expr->getBeginLoc()), "invalid constant expression");
1305 return nullptr;1403 return nullptr;
1306 }1404 }
1307 AstNode *node = trans_ap_value(c, &result.Val, expr->getType(), expr->getBeginLoc());1405 AstNode *node = trans_ap_value(c, bitcast(&result.Val), bitcast(expr->getType()), bitcast(expr->getBeginLoc()));
1308 return maybe_suppress_result(c, result_used, node);1406 return maybe_suppress_result(c, result_used, node);
1309}1407}
13101408
...@@ -1313,9 +1411,9 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T...@@ -1313,9 +1411,9 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
1313{1411{
1314 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);1412 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
13151413
1316 clang::Expr *cond_expr = stmt->getCond();1414 const ZigClangExpr *cond_expr = bitcast(stmt->getCond());
1317 clang::Expr *true_expr = stmt->getTrueExpr();1415 const ZigClangExpr *true_expr = bitcast(stmt->getTrueExpr());
1318 clang::Expr *false_expr = stmt->getFalseExpr();1416 const ZigClangExpr *false_expr = bitcast(stmt->getFalseExpr());
13191417
1320 node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);1418 node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);
1321 if (node->data.if_bool_expr.condition == nullptr)1419 if (node->data.if_bool_expr.condition == nullptr)
...@@ -1332,7 +1430,9 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T...@@ -1332,7 +1430,9 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
1332 return maybe_suppress_result(c, result_used, node);1430 return maybe_suppress_result(c, result_used, node);
1333}1431}
13341432
1335static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {1433static AstNode *trans_create_bin_op(Context *c, TransScope *scope, const ZigClangExpr *lhs,
1434 BinOpType bin_op, const ZigClangExpr *rhs)
1435{
1336 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);1436 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1337 node->data.bin_op_expr.bin_op = bin_op;1437 node->data.bin_op_expr.bin_op = bin_op;
13381438
...@@ -1347,7 +1447,9 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *...@@ -1347,7 +1447,9 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *
1347 return node;1447 return node;
1348}1448}
13491449
1350static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {1450static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, const ZigClangExpr *lhs,
1451 BinOpType bin_op, const ZigClangExpr *rhs)
1452{
1351 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);1453 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
1352 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);1454 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1353 node->data.bin_op_expr.bin_op = bin_op;1455 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...@@ -1363,7 +1465,9 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::E
1363 return node;1465 return node;
1364}1466}
13651467
1366static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, clang::Expr *lhs, clang::Expr *rhs) {1468static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope,
1469 const ZigClangExpr *lhs, const ZigClangExpr *rhs)
1470{
1367 if (result_used == ResultUsedNo) {1471 if (result_used == ResultUsedNo) {
1368 // common case1472 // common case
1369 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);1473 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
...@@ -1414,10 +1518,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco...@@ -1414,10 +1518,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
1414 }1518 }
1415}1519}
14161520
1417static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type,1521static AstNode *trans_create_shift_op(Context *c, TransScope *scope, ZigClangQualType result_type,
1418 clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr)1522 const ZigClangExpr *lhs_expr, BinOpType bin_op, const ZigClangExpr *rhs_expr)
1419{1523{
1420 const clang::SourceLocation &rhs_location = rhs_expr->getBeginLoc();1524 ZigClangSourceLocation rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);
1421 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);1525 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
1422 // lhs >> u5(rh)1526 // lhs >> u5(rh)
14231527
...@@ -1434,130 +1538,130 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::Qual...@@ -1434,130 +1538,130 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::Qual
1434static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) {1538static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) {
1435 switch (stmt->getOpcode()) {1539 switch (stmt->getOpcode()) {
1436 case clang::BO_PtrMemD:1540 case clang::BO_PtrMemD:
1437 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemD");1541 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C binary operators: BO_PtrMemD");
1438 return nullptr;1542 return nullptr;
1439 case clang::BO_PtrMemI:1543 case clang::BO_PtrMemI:
1440 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemI");1544 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C binary operators: BO_PtrMemI");
1441 return nullptr;1545 return nullptr;
1442 case clang::BO_Cmp:1546 case clang::BO_Cmp:
1443 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_Cmp");1547 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C binary operators: BO_Cmp");
1444 return nullptr;1548 return nullptr;
1445 case clang::BO_Mul: {1549 case clang::BO_Mul: {
1446 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(),1550 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()),
1447 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,1551 qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())) ? BinOpTypeMultWrap : BinOpTypeMult,
1448 stmt->getRHS());1552 bitcast(stmt->getRHS()));
1449 return maybe_suppress_result(c, result_used, node);1553 return maybe_suppress_result(c, result_used, node);
1450 }1554 }
1451 case clang::BO_Div:1555 case clang::BO_Div:
1452 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {1556 if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType()))) {
1453 // unsigned/float division uses the operator1557 // unsigned/float division uses the operator
1454 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());1558 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeDiv, bitcast(stmt->getRHS()));
1455 return maybe_suppress_result(c, result_used, node);1559 return maybe_suppress_result(c, result_used, node);
1456 } else {1560 } else {
1457 // signed integer division uses @divTrunc1561 // signed integer division uses @divTrunc
1458 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc");1562 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc");
1459 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue);1563 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getLHS()), TransLValue);
1460 if (lhs == nullptr) return nullptr;1564 if (lhs == nullptr) return nullptr;
1461 fn_call->data.fn_call_expr.params.append(lhs);1565 fn_call->data.fn_call_expr.params.append(lhs);
1462 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue);1566 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getRHS()), TransLValue);
1463 if (rhs == nullptr) return nullptr;1567 if (rhs == nullptr) return nullptr;
1464 fn_call->data.fn_call_expr.params.append(rhs);1568 fn_call->data.fn_call_expr.params.append(rhs);
1465 return maybe_suppress_result(c, result_used, fn_call);1569 return maybe_suppress_result(c, result_used, fn_call);
1466 }1570 }
1467 case clang::BO_Rem:1571 case clang::BO_Rem:
1468 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {1572 if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType()))) {
1469 // unsigned/float division uses the operator1573 // unsigned/float division uses the operator
1470 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());1574 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeMod, bitcast(stmt->getRHS()));
1471 return maybe_suppress_result(c, result_used, node);1575 return maybe_suppress_result(c, result_used, node);
1472 } else {1576 } else {
1473 // signed integer division uses @rem1577 // signed integer division uses @rem
1474 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem");1578 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem");
1475 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue);1579 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getLHS()), TransLValue);
1476 if (lhs == nullptr) return nullptr;1580 if (lhs == nullptr) return nullptr;
1477 fn_call->data.fn_call_expr.params.append(lhs);1581 fn_call->data.fn_call_expr.params.append(lhs);
1478 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue);1582 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getRHS()), TransLValue);
1479 if (rhs == nullptr) return nullptr;1583 if (rhs == nullptr) return nullptr;
1480 fn_call->data.fn_call_expr.params.append(rhs);1584 fn_call->data.fn_call_expr.params.append(rhs);
1481 return maybe_suppress_result(c, result_used, fn_call);1585 return maybe_suppress_result(c, result_used, fn_call);
1482 }1586 }
1483 case clang::BO_Add: {1587 case clang::BO_Add: {
1484 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(),1588 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()),
1485 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,1589 qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())) ? BinOpTypeAddWrap : BinOpTypeAdd,
1486 stmt->getRHS());1590 bitcast(stmt->getRHS()));
1487 return maybe_suppress_result(c, result_used, node);1591 return maybe_suppress_result(c, result_used, node);
1488 }1592 }
1489 case clang::BO_Sub: {1593 case clang::BO_Sub: {
1490 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(),1594 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()),
1491 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,1595 qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())) ? BinOpTypeSubWrap : BinOpTypeSub,
1492 stmt->getRHS());1596 bitcast(stmt->getRHS()));
1493 return maybe_suppress_result(c, result_used, node);1597 return maybe_suppress_result(c, result_used, node);
1494 }1598 }
1495 case clang::BO_Shl: {1599 case clang::BO_Shl: {
1496 AstNode *node = trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());1600 AstNode *node = trans_create_shift_op(c, scope, bitcast(stmt->getType()), bitcast(stmt->getLHS()), BinOpTypeBitShiftLeft, bitcast(stmt->getRHS()));
1497 return maybe_suppress_result(c, result_used, node);1601 return maybe_suppress_result(c, result_used, node);
1498 }1602 }
1499 case clang::BO_Shr: {1603 case clang::BO_Shr: {
1500 AstNode *node = trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());1604 AstNode *node = trans_create_shift_op(c, scope, bitcast(stmt->getType()), bitcast(stmt->getLHS()), BinOpTypeBitShiftRight, bitcast(stmt->getRHS()));
1501 return maybe_suppress_result(c, result_used, node);1605 return maybe_suppress_result(c, result_used, node);
1502 }1606 }
1503 case clang::BO_LT: {1607 case clang::BO_LT: {
1504 AstNode *node =trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());1608 AstNode *node =trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpLessThan, bitcast(stmt->getRHS()));
1505 return maybe_suppress_result(c, result_used, node);1609 return maybe_suppress_result(c, result_used, node);
1506 }1610 }
1507 case clang::BO_GT: {1611 case clang::BO_GT: {
1508 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());1612 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpGreaterThan, bitcast(stmt->getRHS()));
1509 return maybe_suppress_result(c, result_used, node);1613 return maybe_suppress_result(c, result_used, node);
1510 }1614 }
1511 case clang::BO_LE: {1615 case clang::BO_LE: {
1512 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());1616 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpLessOrEq, bitcast(stmt->getRHS()));
1513 return maybe_suppress_result(c, result_used, node);1617 return maybe_suppress_result(c, result_used, node);
1514 }1618 }
1515 case clang::BO_GE: {1619 case clang::BO_GE: {
1516 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());1620 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpGreaterOrEq, bitcast(stmt->getRHS()));
1517 return maybe_suppress_result(c, result_used, node);1621 return maybe_suppress_result(c, result_used, node);
1518 }1622 }
1519 case clang::BO_EQ: {1623 case clang::BO_EQ: {
1520 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());1624 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpEq, bitcast(stmt->getRHS()));
1521 return maybe_suppress_result(c, result_used, node);1625 return maybe_suppress_result(c, result_used, node);
1522 }1626 }
1523 case clang::BO_NE: {1627 case clang::BO_NE: {
1524 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());1628 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeCmpNotEq, bitcast(stmt->getRHS()));
1525 return maybe_suppress_result(c, result_used, node);1629 return maybe_suppress_result(c, result_used, node);
1526 }1630 }
1527 case clang::BO_And: {1631 case clang::BO_And: {
1528 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());1632 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBinAnd, bitcast(stmt->getRHS()));
1529 return maybe_suppress_result(c, result_used, node);1633 return maybe_suppress_result(c, result_used, node);
1530 }1634 }
1531 case clang::BO_Xor: {1635 case clang::BO_Xor: {
1532 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());1636 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBinXor, bitcast(stmt->getRHS()));
1533 return maybe_suppress_result(c, result_used, node);1637 return maybe_suppress_result(c, result_used, node);
1534 }1638 }
1535 case clang::BO_Or: {1639 case clang::BO_Or: {
1536 AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());1640 AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBinOr, bitcast(stmt->getRHS()));
1537 return maybe_suppress_result(c, result_used, node);1641 return maybe_suppress_result(c, result_used, node);
1538 }1642 }
1539 case clang::BO_LAnd: {1643 case clang::BO_LAnd: {
1540 AstNode *node = trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());1644 AstNode *node = trans_create_bool_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBoolAnd, bitcast(stmt->getRHS()));
1541 return maybe_suppress_result(c, result_used, node);1645 return maybe_suppress_result(c, result_used, node);
1542 }1646 }
1543 case clang::BO_LOr: {1647 case clang::BO_LOr: {
1544 AstNode *node = trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());1648 AstNode *node = trans_create_bool_bin_op(c, scope, bitcast(stmt->getLHS()), BinOpTypeBoolOr, bitcast(stmt->getRHS()));
1545 return maybe_suppress_result(c, result_used, node);1649 return maybe_suppress_result(c, result_used, node);
1546 }1650 }
1547 case clang::BO_Assign:1651 case clang::BO_Assign:
1548 return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());1652 return trans_create_assign(c, result_used, scope, bitcast(stmt->getLHS()), bitcast(stmt->getRHS()));
1549 case clang::BO_Comma:1653 case clang::BO_Comma:
1550 {1654 {
1551 TransScopeBlock *scope_block = trans_scope_block_create(c, scope);1655 TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
1552 Buf *label_name = buf_create_from_str("x");1656 Buf *label_name = buf_create_from_str("x");
1553 scope_block->node->data.block.name = label_name;1657 scope_block->node->data.block.name = label_name;
15541658
1555 AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, stmt->getLHS(), TransRValue);1659 AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, bitcast(stmt->getLHS()), TransRValue);
1556 if (lhs == nullptr)1660 if (lhs == nullptr)
1557 return nullptr;1661 return nullptr;
1558 scope_block->node->data.block.statements.append(lhs);1662 scope_block->node->data.block.statements.append(lhs);
15591663
1560 AstNode *rhs = trans_expr(c, ResultUsedYes, &scope_block->base, stmt->getRHS(), TransRValue);1664 AstNode *rhs = trans_expr(c, ResultUsedYes, &scope_block->base, bitcast(stmt->getRHS()), TransRValue);
1561 if (rhs == nullptr)1665 if (rhs == nullptr)
1562 return nullptr;1666 return nullptr;
15631667
...@@ -1584,17 +1688,17 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS...@@ -1584,17 +1688,17 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1584static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope,1688static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope,
1585 const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)1689 const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
1586{1690{
1587 const clang::SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc();1691 ZigClangSourceLocation rhs_location = bitcast(stmt->getRHS()->getBeginLoc());
1588 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);1692 AstNode *rhs_type = qual_type_to_log2_int_ref(c, bitcast(stmt->getComputationLHSType()), rhs_location);
15891693
1590 bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();1694 bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();
1591 if (!use_intermediate_casts && result_used == ResultUsedNo) {1695 if (!use_intermediate_casts && result_used == ResultUsedNo) {
1592 // simple common case, where the C and Zig are identical:1696 // simple common case, where the C and Zig are identical:
1593 // lhs >>= rhs1697 // lhs >>= rhs
1594 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue);1698 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getLHS()), TransLValue);
1595 if (lhs == nullptr) return nullptr;1699 if (lhs == nullptr) return nullptr;
15961700
1597 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransRValue);1701 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getRHS()), TransRValue);
1598 if (rhs == nullptr) return nullptr;1702 if (rhs == nullptr) return nullptr;
1599 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);1703 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
16001704
...@@ -1614,7 +1718,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result...@@ -1614,7 +1718,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
1614 child_scope->node->data.block.name = label_name;1718 child_scope->node->data.block.name = label_name;
16151719
1616 // const _ref = &lhs;1720 // const _ref = &lhs;
1617 AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue);1721 AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, bitcast(stmt->getLHS()), TransLValue);
1618 if (lhs == nullptr) return nullptr;1722 if (lhs == nullptr) return nullptr;
1619 AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);1723 AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);
1620 // TODO: avoid name collisions with generated variable names1724 // TODO: avoid name collisions with generated variable names
...@@ -1624,20 +1728,20 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result...@@ -1624,20 +1728,20 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
16241728
1625 // *_ref = result_type(operation_type(*_ref) >> u5(rhs));1729 // *_ref = result_type(operation_type(*_ref) >> u5(rhs));
16261730
1627 AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getRHS(), TransRValue);1731 AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, bitcast(stmt->getRHS()), TransRValue);
1628 if (rhs == nullptr) return nullptr;1732 if (rhs == nullptr) return nullptr;
1629 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);1733 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
16301734
1631 // operation_type(*_ref)1735 // operation_type(*_ref)
1632 AstNode *operation_type_cast = trans_c_cast(c, rhs_location,1736 AstNode *operation_type_cast = trans_c_cast(c, rhs_location,
1633 stmt->getComputationLHSType(),1737 bitcast(stmt->getComputationLHSType()),
1634 stmt->getLHS()->getType(),1738 bitcast(stmt->getLHS()->getType()),
1635 trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)));1739 trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)));
16361740
1637 // result_type(... >> u5(rhs))1741 // result_type(... >> u5(rhs))
1638 AstNode *result_type_cast = trans_c_cast(c, rhs_location,1742 AstNode *result_type_cast = trans_c_cast(c, rhs_location,
1639 stmt->getComputationResultType(),1743 bitcast(stmt->getComputationResultType()),
1640 stmt->getComputationLHSType(),1744 bitcast(stmt->getComputationLHSType()),
1641 trans_create_node_bin_op(c,1745 trans_create_node_bin_op(c,
1642 operation_type_cast,1746 operation_type_cast,
1643 bin_op,1747 bin_op,
...@@ -1669,9 +1773,9 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,...@@ -1669,9 +1773,9 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
1669 if (result_used == ResultUsedNo) {1773 if (result_used == ResultUsedNo) {
1670 // simple common case, where the C and Zig are identical:1774 // simple common case, where the C and Zig are identical:
1671 // lhs += rhs1775 // lhs += rhs
1672 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, stmt->getLHS(), TransLValue);1776 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getLHS()), TransLValue);
1673 if (lhs == nullptr) return nullptr;1777 if (lhs == nullptr) return nullptr;
1674 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransRValue);1778 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getRHS()), TransRValue);
1675 if (rhs == nullptr) return nullptr;1779 if (rhs == nullptr) return nullptr;
1676 return trans_create_node_bin_op(c, lhs, assign_op, rhs);1780 return trans_create_node_bin_op(c, lhs, assign_op, rhs);
1677 } else {1781 } else {
...@@ -1688,7 +1792,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,...@@ -1688,7 +1792,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
1688 child_scope->node->data.block.name = label_name;1792 child_scope->node->data.block.name = label_name;
16891793
1690 // const _ref = &lhs;1794 // const _ref = &lhs;
1691 AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue);1795 AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, bitcast(stmt->getLHS()), TransLValue);
1692 if (lhs == nullptr) return nullptr;1796 if (lhs == nullptr) return nullptr;
1693 AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);1797 AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);
1694 // TODO: avoid name collisions with generated variable names1798 // TODO: avoid name collisions with generated variable names
...@@ -1698,7 +1802,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,...@@ -1698,7 +1802,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
16981802
1699 // *_ref = *_ref + rhs;1803 // *_ref = *_ref + rhs;
17001804
1701 AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getRHS(), TransRValue);1805 AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, bitcast(stmt->getRHS()), TransRValue);
1702 if (rhs == nullptr) return nullptr;1806 if (rhs == nullptr) return nullptr;
17031807
1704 AstNode *assign_statement = trans_create_node_bin_op(c,1808 AstNode *assign_statement = trans_create_node_bin_op(c,
...@@ -1728,26 +1832,26 @@ static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_use...@@ -1728,26 +1832,26 @@ static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_use
1728{1832{
1729 switch (stmt->getOpcode()) {1833 switch (stmt->getOpcode()) {
1730 case clang::BO_MulAssign:1834 case clang::BO_MulAssign:
1731 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1835 if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
1732 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);1836 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
1733 else1837 else
1734 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);1838 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
1735 case clang::BO_DivAssign:1839 case clang::BO_DivAssign:
1736 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_DivAssign");1840 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C compound assign operators: BO_DivAssign");
1737 return nullptr;1841 return nullptr;
1738 case clang::BO_RemAssign:1842 case clang::BO_RemAssign:
1739 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_RemAssign");1843 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C compound assign operators: BO_RemAssign");
1740 return nullptr;1844 return nullptr;
1741 case clang::BO_Cmp:1845 case clang::BO_Cmp:
1742 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_Cmp");1846 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle more C compound assign operators: BO_Cmp");
1743 return nullptr;1847 return nullptr;
1744 case clang::BO_AddAssign:1848 case clang::BO_AddAssign:
1745 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1849 if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
1746 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);1850 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
1747 else1851 else
1748 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);1852 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
1749 case clang::BO_SubAssign:1853 case clang::BO_SubAssign:
1750 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1854 if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
1751 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);1855 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
1752 else1856 else
1753 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);1857 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...@@ -1790,202 +1894,265 @@ static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_use
1790}1894}
17911895
1792static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ImplicitCastExpr *stmt) {1896static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ImplicitCastExpr *stmt) {
1793 switch (stmt->getCastKind()) {1897 switch ((ZigClangCK)stmt->getCastKind()) {
1794 case clang::CK_LValueToRValue:1898 case ZigClangCK_LValueToRValue:
1795 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1899 return trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
1796 case clang::CK_IntegralCast:1900 case ZigClangCK_IntegralCast:
1797 {1901 {
1798 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1902 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
1799 if (target_node == nullptr)1903 if (target_node == nullptr)
1800 return nullptr;1904 return nullptr;
1801 AstNode *node = trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),1905 AstNode *node = trans_c_cast(c, bitcast(stmt->getExprLoc()), bitcast(stmt->getType()),
1802 stmt->getSubExpr()->getType(), target_node);1906 bitcast(stmt->getSubExpr()->getType()), target_node);
1803 return maybe_suppress_result(c, result_used, node);1907 return maybe_suppress_result(c, result_used, node);
1804 }1908 }
1805 case clang::CK_FunctionToPointerDecay:1909 case ZigClangCK_FunctionToPointerDecay:
1806 case clang::CK_ArrayToPointerDecay:1910 case ZigClangCK_ArrayToPointerDecay:
1807 {1911 {
1808 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1912 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
1809 if (target_node == nullptr)1913 if (target_node == nullptr)
1810 return nullptr;1914 return nullptr;
1811 return maybe_suppress_result(c, result_used, target_node);1915 return maybe_suppress_result(c, result_used, target_node);
1812 }1916 }
1813 case clang::CK_BitCast:1917 case ZigClangCK_BitCast:
1814 {1918 {
1815 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1919 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
1816 if (target_node == nullptr)1920 if (target_node == nullptr)
1817 return nullptr;1921 return nullptr;
18181922
1819 if (expr_types_equal(c, stmt, stmt->getSubExpr())) {1923 const ZigClangQualType dest_type = get_expr_qual_type(c, bitcast(stmt));
1820 return target_node;1924 const ZigClangQualType src_type = get_expr_qual_type(c, bitcast(stmt->getSubExpr()));
1821 }
18221925
1823 AstNode *dest_type_node = get_expr_type(c, stmt);1926 return trans_c_cast(c, bitcast(stmt->getBeginLoc()), dest_type, src_type, target_node);
1824
1825 AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
1826 node->data.fn_call_expr.params.append(dest_type_node);
1827 node->data.fn_call_expr.params.append(target_node);
1828 return maybe_suppress_result(c, result_used, node);
1829 }1927 }
1830 case clang::CK_NullToPointer:1928 case ZigClangCK_NullToPointer:
1831 return trans_create_node_unsigned(c, 0);1929 return trans_create_node(c, NodeTypeNullLiteral);
1832 case clang::CK_NoOp:1930 case ZigClangCK_NoOp:
1833 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1931 return trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
1834 case clang::CK_Dependent:1932 case ZigClangCK_Dependent:
1835 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dependent");1933 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_Dependent");
1836 return nullptr;
1837 case clang::CK_LValueBitCast:
1838 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_LValueBitCast");
1839 return nullptr;
1840 case clang::CK_BaseToDerived:
1841 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerived");
1842 return nullptr;
1843 case clang::CK_DerivedToBase:
1844 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBase");
1845 return nullptr;
1846 case clang::CK_UncheckedDerivedToBase:
1847 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UncheckedDerivedToBase");
1848 return nullptr;1934 return nullptr;
1849 case clang::CK_Dynamic:1935 case ZigClangCK_LValueBitCast:
1850 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dynamic");1936 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_LValueBitCast");
1851 return nullptr;1937 return nullptr;
1852 case clang::CK_ToUnion:1938 case ZigClangCK_BaseToDerived:
1853 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToUnion");1939 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_BaseToDerived");
1854 return nullptr;1940 return nullptr;
1855 case clang::CK_NullToMemberPointer:1941 case ZigClangCK_DerivedToBase:
1856 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NullToMemberPointer");1942 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_DerivedToBase");
1857 return nullptr;1943 return nullptr;
1858 case clang::CK_BaseToDerivedMemberPointer:1944 case ZigClangCK_UncheckedDerivedToBase:
1859 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");1945 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_UncheckedDerivedToBase");
1860 return nullptr;1946 return nullptr;
1861 case clang::CK_DerivedToBaseMemberPointer:1947 case ZigClangCK_Dynamic:
1862 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");1948 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_Dynamic");
1863 return nullptr;1949 return nullptr;
1864 case clang::CK_MemberPointerToBoolean:1950 case ZigClangCK_ToUnion:
1865 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_MemberPointerToBoolean");1951 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_ToUnion");
1866 return nullptr;1952 return nullptr;
1867 case clang::CK_ReinterpretMemberPointer:1953 case ZigClangCK_NullToMemberPointer:
1868 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ReinterpretMemberPointer");1954 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_NullToMemberPointer");
1869 return nullptr;1955 return nullptr;
1870 case clang::CK_UserDefinedConversion:1956 case ZigClangCK_BaseToDerivedMemberPointer:
1871 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UserDefinedConversion");1957 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
1872 return nullptr;1958 return nullptr;
1873 case clang::CK_ConstructorConversion:1959 case ZigClangCK_DerivedToBaseMemberPointer:
1874 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ConstructorConversion");1960 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
1875 return nullptr;1961 return nullptr;
1876 case clang::CK_IntegralToPointer:1962 case ZigClangCK_MemberPointerToBoolean:
1877 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToPointer");1963 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_MemberPointerToBoolean");
1878 return nullptr;1964 return nullptr;
1879 case clang::CK_PointerToIntegral:1965 case ZigClangCK_ReinterpretMemberPointer:
1880 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_PointerToIntegral");1966 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_ReinterpretMemberPointer");
1881 return nullptr;1967 return nullptr;
1882 case clang::CK_PointerToBoolean:1968 case ZigClangCK_UserDefinedConversion:
1883 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_PointerToBoolean");1969 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_UserDefinedConversion");
1884 return nullptr;1970 return nullptr;
1885 case clang::CK_ToVoid:1971 case ZigClangCK_ConstructorConversion:
1886 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ToVoid");1972 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion");
1887 return nullptr;1973 return nullptr;
1888 case clang::CK_VectorSplat:1974 case ZigClangCK_PointerToBoolean:
1889 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_VectorSplat");1975 {
1890 return nullptr;1976 const clang::Expr *expr = stmt->getSubExpr();
1891 case clang::CK_IntegralToBoolean:1977 AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue);
1892 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToBoolean");1978 if (val == nullptr)
1893 return nullptr;1979 return nullptr;
1894 case clang::CK_IntegralToFloating:1980
1895 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToFloating");1981 AstNode *val_ptr = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
1982 val_ptr->data.fn_call_expr.params.append(val);
1983
1984 AstNode *zero = trans_create_node_unsigned(c, 0);
1985
1986 // Translate as @ptrToInt((&val) != 0)
1987 return trans_create_node_bin_op(c, val_ptr, BinOpTypeCmpNotEq, zero);
1988 }
1989 case ZigClangCK_ToVoid:
1990 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ToVoid");
1896 return nullptr;1991 return nullptr;
1897 case clang::CK_FixedPointCast:1992 case ZigClangCK_VectorSplat:
1898 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FixedPointCast");1993 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat");
1899 return nullptr;1994 return nullptr;
1900 case clang::CK_FixedPointToBoolean:1995 case ZigClangCK_IntegralToBoolean:
1901 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FixedPointToBoolean");1996 {
1997 const clang::Expr *expr = stmt->getSubExpr();
1998
1999 bool expr_val;
2000 if (expr->EvaluateAsBooleanCondition(expr_val, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
2001 return trans_create_node_bool(c, expr_val);
2002 }
2003
2004 AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue);
2005 if (val == nullptr)
2006 return nullptr;
2007
2008 AstNode *zero = trans_create_node_unsigned(c, 0);
2009
2010 // Translate as val != 0
2011 return trans_create_node_bin_op(c, val, BinOpTypeCmpNotEq, zero);
2012 }
2013 case ZigClangCK_PointerToIntegral:
2014 {
2015 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
2016 if (target_node == nullptr)
2017 return nullptr;
2018
2019 AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
2020 if (dest_type_node == nullptr)
2021 return nullptr;
2022
2023 AstNode *val_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
2024 val_node->data.fn_call_expr.params.append(target_node);
2025 // @ptrToInt always returns a usize
2026 AstNode *node = trans_create_node_builtin_fn_call_str(c, "intCast");
2027 node->data.fn_call_expr.params.append(dest_type_node);
2028 node->data.fn_call_expr.params.append(val_node);
2029
2030 return maybe_suppress_result(c, result_used, node);
2031 }
2032 case ZigClangCK_IntegralToPointer:
2033 {
2034 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
2035 if (target_node == nullptr)
2036 return nullptr;
2037
2038 AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
2039 if (dest_type_node == nullptr)
2040 return nullptr;
2041
2042 AstNode *node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
2043 node->data.fn_call_expr.params.append(dest_type_node);
2044 node->data.fn_call_expr.params.append(target_node);
2045
2046 return maybe_suppress_result(c, result_used, node);
2047 }
2048 case ZigClangCK_IntegralToFloating:
2049 case ZigClangCK_FloatingToIntegral:
2050 {
2051 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
2052 if (target_node == nullptr)
2053 return nullptr;
2054
2055 AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
2056 if (dest_type_node == nullptr)
2057 return nullptr;
2058
2059 char const *fn = (ZigClangCK)stmt->getCastKind() == ZigClangCK_IntegralToFloating ?
2060 "intToFloat" : "floatToInt";
2061 AstNode *node = trans_create_node_builtin_fn_call_str(c, fn);
2062 node->data.fn_call_expr.params.append(dest_type_node);
2063 node->data.fn_call_expr.params.append(target_node);
2064
2065 return maybe_suppress_result(c, result_used, node);
2066 }
2067 case ZigClangCK_FixedPointCast:
2068 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointCast");
1902 return nullptr;2069 return nullptr;
1903 case clang::CK_FloatingToIntegral:2070 case ZigClangCK_FixedPointToBoolean:
1904 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingToIntegral");2071 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean");
1905 return nullptr;2072 return nullptr;
1906 case clang::CK_FloatingToBoolean:2073 case ZigClangCK_FloatingToBoolean:
1907 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingToBoolean");2074 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean");
1908 return nullptr;2075 return nullptr;
1909 case clang::CK_BooleanToSignedIntegral:2076 case ZigClangCK_BooleanToSignedIntegral:
1910 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BooleanToSignedIntegral");2077 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BooleanToSignedIntegral");
1911 return nullptr;2078 return nullptr;
1912 case clang::CK_FloatingCast:2079 case ZigClangCK_FloatingCast:
1913 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingCast");2080 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingCast");
1914 return nullptr;2081 return nullptr;
1915 case clang::CK_CPointerToObjCPointerCast:2082 case ZigClangCK_CPointerToObjCPointerCast:
1916 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_CPointerToObjCPointerCast");2083 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_CPointerToObjCPointerCast");
1917 return nullptr;2084 return nullptr;
1918 case clang::CK_BlockPointerToObjCPointerCast:2085 case ZigClangCK_BlockPointerToObjCPointerCast:
1919 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BlockPointerToObjCPointerCast");2086 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BlockPointerToObjCPointerCast");
1920 return nullptr;2087 return nullptr;
1921 case clang::CK_AnyPointerToBlockPointerCast:2088 case ZigClangCK_AnyPointerToBlockPointerCast:
1922 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AnyPointerToBlockPointerCast");2089 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AnyPointerToBlockPointerCast");
1923 return nullptr;2090 return nullptr;
1924 case clang::CK_ObjCObjectLValueCast:2091 case ZigClangCK_ObjCObjectLValueCast:
1925 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ObjCObjectLValueCast");2092 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ObjCObjectLValueCast");
1926 return nullptr;2093 return nullptr;
1927 case clang::CK_FloatingRealToComplex:2094 case ZigClangCK_FloatingRealToComplex:
1928 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingRealToComplex");2095 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingRealToComplex");
1929 return nullptr;2096 return nullptr;
1930 case clang::CK_FloatingComplexToReal:2097 case ZigClangCK_FloatingComplexToReal:
1931 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToReal");2098 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToReal");
1932 return nullptr;2099 return nullptr;
1933 case clang::CK_FloatingComplexToBoolean:2100 case ZigClangCK_FloatingComplexToBoolean:
1934 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToBoolean");2101 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToBoolean");
1935 return nullptr;2102 return nullptr;
1936 case clang::CK_FloatingComplexCast:2103 case ZigClangCK_FloatingComplexCast:
1937 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexCast");2104 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexCast");
1938 return nullptr;2105 return nullptr;
1939 case clang::CK_FloatingComplexToIntegralComplex:2106 case ZigClangCK_FloatingComplexToIntegralComplex:
1940 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToIntegralComplex");2107 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToIntegralComplex");
1941 return nullptr;2108 return nullptr;
1942 case clang::CK_IntegralRealToComplex:2109 case ZigClangCK_IntegralRealToComplex:
1943 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralRealToComplex");2110 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralRealToComplex");
1944 return nullptr;2111 return nullptr;
1945 case clang::CK_IntegralComplexToReal:2112 case ZigClangCK_IntegralComplexToReal:
1946 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToReal");2113 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToReal");
1947 return nullptr;2114 return nullptr;
1948 case clang::CK_IntegralComplexToBoolean:2115 case ZigClangCK_IntegralComplexToBoolean:
1949 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToBoolean");2116 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToBoolean");
1950 return nullptr;2117 return nullptr;
1951 case clang::CK_IntegralComplexCast:2118 case ZigClangCK_IntegralComplexCast:
1952 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexCast");2119 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexCast");
1953 return nullptr;2120 return nullptr;
1954 case clang::CK_IntegralComplexToFloatingComplex:2121 case ZigClangCK_IntegralComplexToFloatingComplex:
1955 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToFloatingComplex");2122 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToFloatingComplex");
1956 return nullptr;2123 return nullptr;
1957 case clang::CK_ARCProduceObject:2124 case ZigClangCK_ARCProduceObject:
1958 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCProduceObject");2125 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCProduceObject");
1959 return nullptr;2126 return nullptr;
1960 case clang::CK_ARCConsumeObject:2127 case ZigClangCK_ARCConsumeObject:
1961 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCConsumeObject");2128 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCConsumeObject");
1962 return nullptr;2129 return nullptr;
1963 case clang::CK_ARCReclaimReturnedObject:2130 case ZigClangCK_ARCReclaimReturnedObject:
1964 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCReclaimReturnedObject");2131 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCReclaimReturnedObject");
1965 return nullptr;2132 return nullptr;
1966 case clang::CK_ARCExtendBlockObject:2133 case ZigClangCK_ARCExtendBlockObject:
1967 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCExtendBlockObject");2134 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCExtendBlockObject");
1968 return nullptr;2135 return nullptr;
1969 case clang::CK_AtomicToNonAtomic:2136 case ZigClangCK_AtomicToNonAtomic:
1970 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AtomicToNonAtomic");2137 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AtomicToNonAtomic");
1971 return nullptr;2138 return nullptr;
1972 case clang::CK_NonAtomicToAtomic:2139 case ZigClangCK_NonAtomicToAtomic:
1973 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_NonAtomicToAtomic");2140 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_NonAtomicToAtomic");
1974 return nullptr;2141 return nullptr;
1975 case clang::CK_CopyAndAutoreleaseBlockObject:2142 case ZigClangCK_CopyAndAutoreleaseBlockObject:
1976 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_CopyAndAutoreleaseBlockObject");2143 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_CopyAndAutoreleaseBlockObject");
1977 return nullptr;2144 return nullptr;
1978 case clang::CK_BuiltinFnToFnPtr:2145 case ZigClangCK_BuiltinFnToFnPtr:
1979 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BuiltinFnToFnPtr");2146 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BuiltinFnToFnPtr");
1980 return nullptr;2147 return nullptr;
1981 case clang::CK_ZeroToOCLOpaqueType:2148 case ZigClangCK_ZeroToOCLOpaqueType:
1982 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ZeroToOCLOpaqueType");2149 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ZeroToOCLOpaqueType");
1983 return nullptr;2150 return nullptr;
1984 case clang::CK_AddressSpaceConversion:2151 case ZigClangCK_AddressSpaceConversion:
1985 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AddressSpaceConversion");2152 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AddressSpaceConversion");
1986 return nullptr;2153 return nullptr;
1987 case clang::CK_IntToOCLSampler:2154 case ZigClangCK_IntToOCLSampler:
1988 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntToOCLSampler");2155 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntToOCLSampler");
1989 return nullptr;2156 return nullptr;
1990 }2157 }
1991 zig_unreachable();2158 zig_unreachable();
...@@ -1993,7 +2160,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra...@@ -1993,7 +2160,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra
19932160
1994static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) {2161static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) {
1995 const clang::ValueDecl *value_decl = stmt->getDecl();2162 const clang::ValueDecl *value_decl = stmt->getDecl();
1996 Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));2163 Buf *c_symbol_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)value_decl));
1997 Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);2164 Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);
1998 if (lrval == TransLValue) {2165 if (lrval == TransLValue) {
1999 c->ptr_params.put(zig_symbol_name, true);2166 c->ptr_params.put(zig_symbol_name, true);
...@@ -2004,7 +2171,7 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::...@@ -2004,7 +2171,7 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::
2004static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope,2171static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope,
2005 const clang::UnaryOperator *stmt, BinOpType assign_op)2172 const clang::UnaryOperator *stmt, BinOpType assign_op)
2006{2173{
2007 clang::Expr *op_expr = stmt->getSubExpr();2174 const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
20082175
2009 if (result_used == ResultUsedNo) {2176 if (result_used == ResultUsedNo) {
2010 // common case2177 // common case
...@@ -2060,7 +2227,7 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr...@@ -2060,7 +2227,7 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
2060static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope,2227static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope,
2061 const clang::UnaryOperator *stmt, BinOpType assign_op)2228 const clang::UnaryOperator *stmt, BinOpType assign_op)
2062{2229{
2063 clang::Expr *op_expr = stmt->getSubExpr();2230 const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
20642231
2065 if (result_used == ResultUsedNo) {2232 if (result_used == ResultUsedNo) {
2066 // common case2233 // common case
...@@ -2110,50 +2277,50 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra...@@ -2110,50 +2277,50 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
2110static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) {2277static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) {
2111 switch (stmt->getOpcode()) {2278 switch (stmt->getOpcode()) {
2112 case clang::UO_PostInc:2279 case clang::UO_PostInc:
2113 if (qual_type_has_wrapping_overflow(c, stmt->getType()))2280 if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
2114 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);2281 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
2115 else2282 else
2116 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);2283 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
2117 case clang::UO_PostDec:2284 case clang::UO_PostDec:
2118 if (qual_type_has_wrapping_overflow(c, stmt->getType()))2285 if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
2119 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);2286 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
2120 else2287 else
2121 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);2288 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
2122 case clang::UO_PreInc:2289 case clang::UO_PreInc:
2123 if (qual_type_has_wrapping_overflow(c, stmt->getType()))2290 if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
2124 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);2291 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
2125 else2292 else
2126 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);2293 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
2127 case clang::UO_PreDec:2294 case clang::UO_PreDec:
2128 if (qual_type_has_wrapping_overflow(c, stmt->getType()))2295 if (qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())))
2129 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);2296 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
2130 else2297 else
2131 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);2298 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
2132 case clang::UO_AddrOf:2299 case clang::UO_AddrOf:
2133 {2300 {
2134 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);2301 AstNode *value_node = trans_expr(c, result_used, scope, bitcast(stmt->getSubExpr()), TransLValue);
2135 if (value_node == nullptr)2302 if (value_node == nullptr)
2136 return value_node;2303 return value_node;
2137 return trans_create_node_addr_of(c, value_node);2304 return trans_create_node_addr_of(c, value_node);
2138 }2305 }
2139 case clang::UO_Deref:2306 case clang::UO_Deref:
2140 {2307 {
2141 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);2308 AstNode *value_node = trans_expr(c, result_used, scope, bitcast(stmt->getSubExpr()), TransRValue);
2142 if (value_node == nullptr)2309 if (value_node == nullptr)
2143 return nullptr;2310 return nullptr;
2144 bool is_fn_ptr = qual_type_is_fn_ptr(stmt->getSubExpr()->getType());2311 bool is_fn_ptr = qual_type_is_fn_ptr(bitcast(stmt->getSubExpr()->getType()));
2145 if (is_fn_ptr)2312 if (is_fn_ptr)
2146 return value_node;2313 return value_node;
2147 AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);2314 AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);
2148 return trans_create_node_ptr_deref(c, unwrapped);2315 return trans_create_node_ptr_deref(c, unwrapped);
2149 }2316 }
2150 case clang::UO_Plus:2317 case clang::UO_Plus:
2151 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Plus");2318 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Plus");
2152 return nullptr;2319 return nullptr;
2153 case clang::UO_Minus:2320 case clang::UO_Minus:
2154 {2321 {
2155 clang::Expr *op_expr = stmt->getSubExpr();2322 const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
2156 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {2323 if (!qual_type_has_wrapping_overflow(c, ZigClangExpr_getType(op_expr))) {
2157 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);2324 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
2158 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;2325 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
21592326
...@@ -2162,7 +2329,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc...@@ -2162,7 +2329,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
2162 return nullptr;2329 return nullptr;
21632330
2164 return node;2331 return node;
2165 } else if (c_is_unsigned_integer(c, op_expr->getType())) {2332 } else if (c_is_unsigned_integer(c, ZigClangExpr_getType(op_expr))) {
2166 // we gotta emit 0 -% x2333 // we gotta emit 0 -% x
2167 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);2334 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
2168 node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0);2335 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...@@ -2174,13 +2341,13 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
2174 node->data.bin_op_expr.bin_op = BinOpTypeSubWrap;2341 node->data.bin_op_expr.bin_op = BinOpTypeSubWrap;
2175 return node;2342 return node;
2176 } else {2343 } else {
2177 emit_warning(c, stmt->getBeginLoc(), "C negation with non float non integer");2344 emit_warning(c, bitcast(stmt->getBeginLoc()), "C negation with non float non integer");
2178 return nullptr;2345 return nullptr;
2179 }2346 }
2180 }2347 }
2181 case clang::UO_Not:2348 case clang::UO_Not:
2182 {2349 {
2183 clang::Expr *op_expr = stmt->getSubExpr();2350 const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
2184 AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);2351 AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2185 if (sub_node == nullptr)2352 if (sub_node == nullptr)
2186 return nullptr;2353 return nullptr;
...@@ -2189,7 +2356,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc...@@ -2189,7 +2356,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
2189 }2356 }
2190 case clang::UO_LNot:2357 case clang::UO_LNot:
2191 {2358 {
2192 clang::Expr *op_expr = stmt->getSubExpr();2359 const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr());
2193 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);2360 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2194 if (sub_node == nullptr)2361 if (sub_node == nullptr)
2195 return nullptr;2362 return nullptr;
...@@ -2197,15 +2364,15 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc...@@ -2197,15 +2364,15 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
2197 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);2364 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
2198 }2365 }
2199 case clang::UO_Real:2366 case clang::UO_Real:
2200 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Real");2367 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Real");
2201 return nullptr;2368 return nullptr;
2202 case clang::UO_Imag:2369 case clang::UO_Imag:
2203 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Imag");2370 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Imag");
2204 return nullptr;2371 return nullptr;
2205 case clang::UO_Extension:2372 case clang::UO_Extension:
2206 return trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);2373 return trans_expr(c, result_used, scope, bitcast(stmt->getSubExpr()), TransLValue);
2207 case clang::UO_Coawait:2374 case clang::UO_Coawait:
2208 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Coawait");2375 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation UO_Coawait");
2209 return nullptr;2376 return nullptr;
2210 }2377 }
2211 zig_unreachable();2378 zig_unreachable();
...@@ -2225,249 +2392,250 @@ static int trans_local_declaration(Context *c, TransScope *scope, const clang::D...@@ -2225,249 +2392,250 @@ static int trans_local_declaration(Context *c, TransScope *scope, const clang::D
2225 switch (decl->getKind()) {2392 switch (decl->getKind()) {
2226 case clang::Decl::Var: {2393 case clang::Decl::Var: {
2227 clang::VarDecl *var_decl = (clang::VarDecl *)decl;2394 clang::VarDecl *var_decl = (clang::VarDecl *)decl;
2228 clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType();2395 ZigClangQualType qual_type = bitcast(var_decl->getTypeSourceInfo()->getType());
2229 AstNode *init_node = nullptr;2396 AstNode *init_node = nullptr;
2230 if (var_decl->hasInit()) {2397 if (var_decl->hasInit()) {
2231 init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue);2398 init_node = trans_expr(c, ResultUsedYes, scope, bitcast(var_decl->getInit()), TransRValue);
2232 if (init_node == nullptr)2399 if (init_node == nullptr)
2233 return ErrorUnexpected;2400 return ErrorUnexpected;
22342401
2235 } else {2402 } else {
2236 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);2403 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
2237 }2404 }
2238 AstNode *type_node = trans_qual_type(c, qual_type, stmt->getBeginLoc());2405 AstNode *type_node = trans_qual_type(c, qual_type, bitcast(stmt->getBeginLoc()));
2239 if (type_node == nullptr)2406 if (type_node == nullptr)
2240 return ErrorUnexpected;2407 return ErrorUnexpected;
22412408
2242 Buf *c_symbol_name = buf_create_from_str(decl_name(var_decl));2409 Buf *c_symbol_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)var_decl));
22432410
2244 TransScopeVar *var_scope = trans_scope_var_create(c, scope, c_symbol_name);2411 TransScopeVar *var_scope = trans_scope_var_create(c, scope, c_symbol_name);
2245 scope = &var_scope->base;2412 scope = &var_scope->base;
22462413
2247 AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(),2414 AstNode *node = trans_create_node_var_decl_local(c,
2415 ZigClangQualType_isConstQualified(qual_type),
2248 var_scope->zig_name, type_node, init_node);2416 var_scope->zig_name, type_node, init_node);
22492417
2250 scope_block->node->data.block.statements.append(node);2418 scope_block->node->data.block.statements.append(node);
2251 continue;2419 continue;
2252 }2420 }
2253 case clang::Decl::AccessSpec:2421 case clang::Decl::AccessSpec:
2254 emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind AccessSpec");2422 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle decl kind AccessSpec");
2255 return ErrorUnexpected;2423 return ErrorUnexpected;
2256 case clang::Decl::Block:2424 case clang::Decl::Block:
2257 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Block");2425 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Block");
2258 return ErrorUnexpected;2426 return ErrorUnexpected;
2259 case clang::Decl::Captured:2427 case clang::Decl::Captured:
2260 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Captured");2428 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Captured");
2261 return ErrorUnexpected;2429 return ErrorUnexpected;
2262 case clang::Decl::ClassScopeFunctionSpecialization:2430 case clang::Decl::ClassScopeFunctionSpecialization:
2263 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassScopeFunctionSpecialization");2431 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassScopeFunctionSpecialization");
2264 return ErrorUnexpected;2432 return ErrorUnexpected;
2265 case clang::Decl::Empty:2433 case clang::Decl::Empty:
2266 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Empty");2434 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Empty");
2267 return ErrorUnexpected;2435 return ErrorUnexpected;
2268 case clang::Decl::Export:2436 case clang::Decl::Export:
2269 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Export");2437 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Export");
2270 return ErrorUnexpected;2438 return ErrorUnexpected;
2271 case clang::Decl::ExternCContext:2439 case clang::Decl::ExternCContext:
2272 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExternCContext");2440 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ExternCContext");
2273 return ErrorUnexpected;2441 return ErrorUnexpected;
2274 case clang::Decl::FileScopeAsm:2442 case clang::Decl::FileScopeAsm:
2275 emit_warning(c, stmt->getBeginLoc(), "TODO handle C FileScopeAsm");2443 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FileScopeAsm");
2276 return ErrorUnexpected;2444 return ErrorUnexpected;
2277 case clang::Decl::Friend:2445 case clang::Decl::Friend:
2278 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Friend");2446 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Friend");
2279 return ErrorUnexpected;2447 return ErrorUnexpected;
2280 case clang::Decl::FriendTemplate:2448 case clang::Decl::FriendTemplate:
2281 emit_warning(c, stmt->getBeginLoc(), "TODO handle C FriendTemplate");2449 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FriendTemplate");
2282 return ErrorUnexpected;2450 return ErrorUnexpected;
2283 case clang::Decl::Import:2451 case clang::Decl::Import:
2284 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Import");2452 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Import");
2285 return ErrorUnexpected;2453 return ErrorUnexpected;
2286 case clang::Decl::LinkageSpec:2454 case clang::Decl::LinkageSpec:
2287 emit_warning(c, stmt->getBeginLoc(), "TODO handle C LinkageSpec");2455 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C LinkageSpec");
2288 return ErrorUnexpected;2456 return ErrorUnexpected;
2289 case clang::Decl::Label:2457 case clang::Decl::Label:
2290 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Label");2458 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Label");
2291 return ErrorUnexpected;2459 return ErrorUnexpected;
2292 case clang::Decl::Namespace:2460 case clang::Decl::Namespace:
2293 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Namespace");2461 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Namespace");
2294 return ErrorUnexpected;2462 return ErrorUnexpected;
2295 case clang::Decl::NamespaceAlias:2463 case clang::Decl::NamespaceAlias:
2296 emit_warning(c, stmt->getBeginLoc(), "TODO handle C NamespaceAlias");2464 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C NamespaceAlias");
2297 return ErrorUnexpected;2465 return ErrorUnexpected;
2298 case clang::Decl::ObjCCompatibleAlias:2466 case clang::Decl::ObjCCompatibleAlias:
2299 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCCompatibleAlias");2467 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCCompatibleAlias");
2300 return ErrorUnexpected;2468 return ErrorUnexpected;
2301 case clang::Decl::ObjCCategory:2469 case clang::Decl::ObjCCategory:
2302 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCCategory");2470 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCCategory");
2303 return ErrorUnexpected;2471 return ErrorUnexpected;
2304 case clang::Decl::ObjCCategoryImpl:2472 case clang::Decl::ObjCCategoryImpl:
2305 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCCategoryImpl");2473 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCCategoryImpl");
2306 return ErrorUnexpected;2474 return ErrorUnexpected;
2307 case clang::Decl::ObjCImplementation:2475 case clang::Decl::ObjCImplementation:
2308 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCImplementation");2476 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCImplementation");
2309 return ErrorUnexpected;2477 return ErrorUnexpected;
2310 case clang::Decl::ObjCInterface:2478 case clang::Decl::ObjCInterface:
2311 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCInterface");2479 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCInterface");
2312 return ErrorUnexpected;2480 return ErrorUnexpected;
2313 case clang::Decl::ObjCProtocol:2481 case clang::Decl::ObjCProtocol:
2314 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProtocol");2482 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCProtocol");
2315 return ErrorUnexpected;2483 return ErrorUnexpected;
2316 case clang::Decl::ObjCMethod:2484 case clang::Decl::ObjCMethod:
2317 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCMethod");2485 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCMethod");
2318 return ErrorUnexpected;2486 return ErrorUnexpected;
2319 case clang::Decl::ObjCProperty:2487 case clang::Decl::ObjCProperty:
2320 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProperty");2488 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCProperty");
2321 return ErrorUnexpected;2489 return ErrorUnexpected;
2322 case clang::Decl::BuiltinTemplate:2490 case clang::Decl::BuiltinTemplate:
2323 emit_warning(c, stmt->getBeginLoc(), "TODO handle C BuiltinTemplate");2491 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C BuiltinTemplate");
2324 return ErrorUnexpected;2492 return ErrorUnexpected;
2325 case clang::Decl::ClassTemplate:2493 case clang::Decl::ClassTemplate:
2326 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassTemplate");2494 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassTemplate");
2327 return ErrorUnexpected;2495 return ErrorUnexpected;
2328 case clang::Decl::FunctionTemplate:2496 case clang::Decl::FunctionTemplate:
2329 emit_warning(c, stmt->getBeginLoc(), "TODO handle C FunctionTemplate");2497 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C FunctionTemplate");
2330 return ErrorUnexpected;2498 return ErrorUnexpected;
2331 case clang::Decl::TypeAliasTemplate:2499 case clang::Decl::TypeAliasTemplate:
2332 emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeAliasTemplate");2500 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TypeAliasTemplate");
2333 return ErrorUnexpected;2501 return ErrorUnexpected;
2334 case clang::Decl::VarTemplate:2502 case clang::Decl::VarTemplate:
2335 emit_warning(c, stmt->getBeginLoc(), "TODO handle C VarTemplate");2503 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VarTemplate");
2336 return ErrorUnexpected;2504 return ErrorUnexpected;
2337 case clang::Decl::TemplateTemplateParm:2505 case clang::Decl::TemplateTemplateParm:
2338 emit_warning(c, stmt->getBeginLoc(), "TODO handle C TemplateTemplateParm");2506 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TemplateTemplateParm");
2339 return ErrorUnexpected;2507 return ErrorUnexpected;
2340 case clang::Decl::Enum:2508 case clang::Decl::Enum:
2341 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Enum");2509 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Enum");
2342 return ErrorUnexpected;2510 return ErrorUnexpected;
2343 case clang::Decl::Record:2511 case clang::Decl::Record:
2344 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Record");2512 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Record");
2345 return ErrorUnexpected;2513 return ErrorUnexpected;
2346 case clang::Decl::CXXRecord:2514 case clang::Decl::CXXRecord:
2347 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXRecord");2515 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXRecord");
2348 return ErrorUnexpected;2516 return ErrorUnexpected;
2349 case clang::Decl::ClassTemplateSpecialization:2517 case clang::Decl::ClassTemplateSpecialization:
2350 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassTemplateSpecialization");2518 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassTemplateSpecialization");
2351 return ErrorUnexpected;2519 return ErrorUnexpected;
2352 case clang::Decl::ClassTemplatePartialSpecialization:2520 case clang::Decl::ClassTemplatePartialSpecialization:
2353 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ClassTemplatePartialSpecialization");2521 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ClassTemplatePartialSpecialization");
2354 return ErrorUnexpected;2522 return ErrorUnexpected;
2355 case clang::Decl::TemplateTypeParm:2523 case clang::Decl::TemplateTypeParm:
2356 emit_warning(c, stmt->getBeginLoc(), "TODO handle C TemplateTypeParm");2524 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TemplateTypeParm");
2357 return ErrorUnexpected;2525 return ErrorUnexpected;
2358 case clang::Decl::ObjCTypeParam:2526 case clang::Decl::ObjCTypeParam:
2359 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCTypeParam");2527 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCTypeParam");
2360 return ErrorUnexpected;2528 return ErrorUnexpected;
2361 case clang::Decl::TypeAlias:2529 case clang::Decl::TypeAlias:
2362 emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeAlias");2530 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TypeAlias");
2363 return ErrorUnexpected;2531 return ErrorUnexpected;
2364 case clang::Decl::Typedef:2532 case clang::Decl::Typedef:
2365 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Typedef");2533 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Typedef");
2366 return ErrorUnexpected;2534 return ErrorUnexpected;
2367 case clang::Decl::UnresolvedUsingTypename:2535 case clang::Decl::UnresolvedUsingTypename:
2368 emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedUsingTypename");2536 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UnresolvedUsingTypename");
2369 return ErrorUnexpected;2537 return ErrorUnexpected;
2370 case clang::Decl::Using:2538 case clang::Decl::Using:
2371 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Using");2539 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Using");
2372 return ErrorUnexpected;2540 return ErrorUnexpected;
2373 case clang::Decl::UsingDirective:2541 case clang::Decl::UsingDirective:
2374 emit_warning(c, stmt->getBeginLoc(), "TODO handle C UsingDirective");2542 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UsingDirective");
2375 return ErrorUnexpected;2543 return ErrorUnexpected;
2376 case clang::Decl::UsingPack:2544 case clang::Decl::UsingPack:
2377 emit_warning(c, stmt->getBeginLoc(), "TODO handle C UsingPack");2545 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UsingPack");
2378 return ErrorUnexpected;2546 return ErrorUnexpected;
2379 case clang::Decl::UsingShadow:2547 case clang::Decl::UsingShadow:
2380 emit_warning(c, stmt->getBeginLoc(), "TODO handle C UsingShadow");2548 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UsingShadow");
2381 return ErrorUnexpected;2549 return ErrorUnexpected;
2382 case clang::Decl::ConstructorUsingShadow:2550 case clang::Decl::ConstructorUsingShadow:
2383 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ConstructorUsingShadow");2551 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ConstructorUsingShadow");
2384 return ErrorUnexpected;2552 return ErrorUnexpected;
2385 case clang::Decl::Binding:2553 case clang::Decl::Binding:
2386 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Binding");2554 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Binding");
2387 return ErrorUnexpected;2555 return ErrorUnexpected;
2388 case clang::Decl::Field:2556 case clang::Decl::Field:
2389 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Field");2557 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Field");
2390 return ErrorUnexpected;2558 return ErrorUnexpected;
2391 case clang::Decl::ObjCAtDefsField:2559 case clang::Decl::ObjCAtDefsField:
2392 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtDefsField");2560 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCAtDefsField");
2393 return ErrorUnexpected;2561 return ErrorUnexpected;
2394 case clang::Decl::ObjCIvar:2562 case clang::Decl::ObjCIvar:
2395 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIvar");2563 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCIvar");
2396 return ErrorUnexpected;2564 return ErrorUnexpected;
2397 case clang::Decl::Function:2565 case clang::Decl::Function:
2398 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Function");2566 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Function");
2399 return ErrorUnexpected;2567 return ErrorUnexpected;
2400 case clang::Decl::CXXDeductionGuide:2568 case clang::Decl::CXXDeductionGuide:
2401 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDeductionGuide");2569 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDeductionGuide");
2402 return ErrorUnexpected;2570 return ErrorUnexpected;
2403 case clang::Decl::CXXMethod:2571 case clang::Decl::CXXMethod:
2404 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXMethod");2572 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXMethod");
2405 return ErrorUnexpected;2573 return ErrorUnexpected;
2406 case clang::Decl::CXXConstructor:2574 case clang::Decl::CXXConstructor:
2407 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstructor");2575 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXConstructor");
2408 return ErrorUnexpected;2576 return ErrorUnexpected;
2409 case clang::Decl::CXXConversion:2577 case clang::Decl::CXXConversion:
2410 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConversion");2578 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXConversion");
2411 return ErrorUnexpected;2579 return ErrorUnexpected;
2412 case clang::Decl::CXXDestructor:2580 case clang::Decl::CXXDestructor:
2413 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDestructor");2581 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CXXDestructor");
2414 return ErrorUnexpected;2582 return ErrorUnexpected;
2415 case clang::Decl::MSProperty:2583 case clang::Decl::MSProperty:
2416 emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSProperty");2584 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C MSProperty");
2417 return ErrorUnexpected;2585 return ErrorUnexpected;
2418 case clang::Decl::NonTypeTemplateParm:2586 case clang::Decl::NonTypeTemplateParm:
2419 emit_warning(c, stmt->getBeginLoc(), "TODO handle C NonTypeTemplateParm");2587 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C NonTypeTemplateParm");
2420 return ErrorUnexpected;2588 return ErrorUnexpected;
2421 case clang::Decl::Decomposition:2589 case clang::Decl::Decomposition:
2422 emit_warning(c, stmt->getBeginLoc(), "TODO handle C Decomposition");2590 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C Decomposition");
2423 return ErrorUnexpected;2591 return ErrorUnexpected;
2424 case clang::Decl::ImplicitParam:2592 case clang::Decl::ImplicitParam:
2425 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImplicitParam");2593 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ImplicitParam");
2426 return ErrorUnexpected;2594 return ErrorUnexpected;
2427 case clang::Decl::OMPCapturedExpr:2595 case clang::Decl::OMPCapturedExpr:
2428 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCapturedExpr");2596 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPCapturedExpr");
2429 return ErrorUnexpected;2597 return ErrorUnexpected;
2430 case clang::Decl::ParmVar:2598 case clang::Decl::ParmVar:
2431 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ParmVar");2599 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ParmVar");
2432 return ErrorUnexpected;2600 return ErrorUnexpected;
2433 case clang::Decl::VarTemplateSpecialization:2601 case clang::Decl::VarTemplateSpecialization:
2434 emit_warning(c, stmt->getBeginLoc(), "TODO handle C VarTemplateSpecialization");2602 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VarTemplateSpecialization");
2435 return ErrorUnexpected;2603 return ErrorUnexpected;
2436 case clang::Decl::VarTemplatePartialSpecialization:2604 case clang::Decl::VarTemplatePartialSpecialization:
2437 emit_warning(c, stmt->getBeginLoc(), "TODO handle C VarTemplatePartialSpecialization");2605 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C VarTemplatePartialSpecialization");
2438 return ErrorUnexpected;2606 return ErrorUnexpected;
2439 case clang::Decl::EnumConstant:2607 case clang::Decl::EnumConstant:
2440 emit_warning(c, stmt->getBeginLoc(), "TODO handle C EnumConstant");2608 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C EnumConstant");
2441 return ErrorUnexpected;2609 return ErrorUnexpected;
2442 case clang::Decl::IndirectField:2610 case clang::Decl::IndirectField:
2443 emit_warning(c, stmt->getBeginLoc(), "TODO handle C IndirectField");2611 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C IndirectField");
2444 return ErrorUnexpected;2612 return ErrorUnexpected;
2445 case clang::Decl::OMPDeclareReduction:2613 case clang::Decl::OMPDeclareReduction:
2446 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDeclareReduction");2614 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPDeclareReduction");
2447 return ErrorUnexpected;2615 return ErrorUnexpected;
2448 case clang::Decl::UnresolvedUsingValue:2616 case clang::Decl::UnresolvedUsingValue:
2449 emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedUsingValue");2617 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C UnresolvedUsingValue");
2450 return ErrorUnexpected;2618 return ErrorUnexpected;
2451 case clang::Decl::OMPRequires:2619 case clang::Decl::OMPRequires:
2452 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPRequires");2620 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPRequires");
2453 return ErrorUnexpected;2621 return ErrorUnexpected;
2454 case clang::Decl::OMPThreadPrivate:2622 case clang::Decl::OMPThreadPrivate:
2455 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPThreadPrivate");2623 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C OMPThreadPrivate");
2456 return ErrorUnexpected;2624 return ErrorUnexpected;
2457 case clang::Decl::ObjCPropertyImpl:2625 case clang::Decl::ObjCPropertyImpl:
2458 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCPropertyImpl");2626 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C ObjCPropertyImpl");
2459 return ErrorUnexpected;2627 return ErrorUnexpected;
2460 case clang::Decl::PragmaComment:2628 case clang::Decl::PragmaComment:
2461 emit_warning(c, stmt->getBeginLoc(), "TODO handle C PragmaComment");2629 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C PragmaComment");
2462 return ErrorUnexpected;2630 return ErrorUnexpected;
2463 case clang::Decl::PragmaDetectMismatch:2631 case clang::Decl::PragmaDetectMismatch:
2464 emit_warning(c, stmt->getBeginLoc(), "TODO handle C PragmaDetectMismatch");2632 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C PragmaDetectMismatch");
2465 return ErrorUnexpected;2633 return ErrorUnexpected;
2466 case clang::Decl::StaticAssert:2634 case clang::Decl::StaticAssert:
2467 emit_warning(c, stmt->getBeginLoc(), "TODO handle C StaticAssert");2635 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C StaticAssert");
2468 return ErrorUnexpected;2636 return ErrorUnexpected;
2469 case clang::Decl::TranslationUnit:2637 case clang::Decl::TranslationUnit:
2470 emit_warning(c, stmt->getBeginLoc(), "TODO handle C TranslationUnit");2638 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C TranslationUnit");
2471 return ErrorUnexpected;2639 return ErrorUnexpected;
2472 }2640 }
2473 zig_unreachable();2641 zig_unreachable();
...@@ -2493,7 +2661,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)...@@ -2493,7 +2661,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)
2493 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);2661 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
2494}2662}
24952663
2496static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval) {2664static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr, TransLRValue lrval) {
2497 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);2665 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
2498 if (res == nullptr)2666 if (res == nullptr)
2499 return nullptr;2667 return nullptr;
...@@ -2530,146 +2698,145 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2530,146 +2698,145 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2530 }2698 }
25312699
25322700
2533 const clang::Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();2701 const ZigClangType *ty = ZigClangQualType_getTypePtr(get_expr_qual_type_before_implicit_cast(c, expr));
2534 auto classs = ty->getTypeClass();2702 auto classs = ZigClangType_getTypeClass(ty);
2535 switch (classs) {2703 switch (classs) {
2536 case clang::Type::Builtin:2704 case ZigClangType_Builtin:
2537 {2705 {
2538 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);2706 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty);
2539 switch (builtin_ty->getKind()) {2707 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
2540 case clang::BuiltinType::Bool:2708 case ZigClangBuiltinTypeBool:
2541 case clang::BuiltinType::Char_U:2709 case ZigClangBuiltinTypeChar_U:
2542 case clang::BuiltinType::UChar:2710 case ZigClangBuiltinTypeUChar:
2543 case clang::BuiltinType::Char_S:2711 case ZigClangBuiltinTypeChar_S:
2544 case clang::BuiltinType::SChar:2712 case ZigClangBuiltinTypeSChar:
2545 case clang::BuiltinType::UShort:2713 case ZigClangBuiltinTypeUShort:
2546 case clang::BuiltinType::UInt:2714 case ZigClangBuiltinTypeUInt:
2547 case clang::BuiltinType::ULong:2715 case ZigClangBuiltinTypeULong:
2548 case clang::BuiltinType::ULongLong:2716 case ZigClangBuiltinTypeULongLong:
2549 case clang::BuiltinType::Short:2717 case ZigClangBuiltinTypeShort:
2550 case clang::BuiltinType::Int:2718 case ZigClangBuiltinTypeInt:
2551 case clang::BuiltinType::Long:2719 case ZigClangBuiltinTypeLong:
2552 case clang::BuiltinType::LongLong:2720 case ZigClangBuiltinTypeLongLong:
2553 case clang::BuiltinType::UInt128:2721 case ZigClangBuiltinTypeUInt128:
2554 case clang::BuiltinType::Int128:2722 case ZigClangBuiltinTypeInt128:
2555 case clang::BuiltinType::Float:2723 case ZigClangBuiltinTypeFloat:
2556 case clang::BuiltinType::Double:2724 case ZigClangBuiltinTypeDouble:
2557 case clang::BuiltinType::Float128:2725 case ZigClangBuiltinTypeFloat128:
2558 case clang::BuiltinType::LongDouble:2726 case ZigClangBuiltinTypeLongDouble:
2559 case clang::BuiltinType::WChar_U:2727 case ZigClangBuiltinTypeWChar_U:
2560 case clang::BuiltinType::Char8:2728 case ZigClangBuiltinTypeChar8:
2561 case clang::BuiltinType::Char16:2729 case ZigClangBuiltinTypeChar16:
2562 case clang::BuiltinType::Char32:2730 case ZigClangBuiltinTypeChar32:
2563 case clang::BuiltinType::WChar_S:2731 case ZigClangBuiltinTypeWChar_S:
2564 case clang::BuiltinType::Float16:2732 case ZigClangBuiltinTypeFloat16:
2565 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));2733 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2566 case clang::BuiltinType::NullPtr:2734 case ZigClangBuiltinTypeNullPtr:
2567 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,2735 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
2568 trans_create_node_unsigned(c, 0));2736 trans_create_node(c, NodeTypeNullLiteral));
25692737
2570 case clang::BuiltinType::Void:2738 case ZigClangBuiltinTypeVoid:
2571 case clang::BuiltinType::Half:2739 case ZigClangBuiltinTypeHalf:
2572 case clang::BuiltinType::ObjCId:2740 case ZigClangBuiltinTypeObjCId:
2573 case clang::BuiltinType::ObjCClass:2741 case ZigClangBuiltinTypeObjCClass:
2574 case clang::BuiltinType::ObjCSel:2742 case ZigClangBuiltinTypeObjCSel:
2575 case clang::BuiltinType::OMPArraySection:2743 case ZigClangBuiltinTypeOMPArraySection:
2576 case clang::BuiltinType::Dependent:2744 case ZigClangBuiltinTypeDependent:
2577 case clang::BuiltinType::Overload:2745 case ZigClangBuiltinTypeOverload:
2578 case clang::BuiltinType::BoundMember:2746 case ZigClangBuiltinTypeBoundMember:
2579 case clang::BuiltinType::PseudoObject:2747 case ZigClangBuiltinTypePseudoObject:
2580 case clang::BuiltinType::UnknownAny:2748 case ZigClangBuiltinTypeUnknownAny:
2581 case clang::BuiltinType::BuiltinFn:2749 case ZigClangBuiltinTypeBuiltinFn:
2582 case clang::BuiltinType::ARCUnbridgedCast:2750 case ZigClangBuiltinTypeARCUnbridgedCast:
2583 case clang::BuiltinType::OCLImage1dRO:2751 case ZigClangBuiltinTypeOCLImage1dRO:
2584 case clang::BuiltinType::OCLImage1dArrayRO:2752 case ZigClangBuiltinTypeOCLImage1dArrayRO:
2585 case clang::BuiltinType::OCLImage1dBufferRO:2753 case ZigClangBuiltinTypeOCLImage1dBufferRO:
2586 case clang::BuiltinType::OCLImage2dRO:2754 case ZigClangBuiltinTypeOCLImage2dRO:
2587 case clang::BuiltinType::OCLImage2dArrayRO:2755 case ZigClangBuiltinTypeOCLImage2dArrayRO:
2588 case clang::BuiltinType::OCLImage2dDepthRO:2756 case ZigClangBuiltinTypeOCLImage2dDepthRO:
2589 case clang::BuiltinType::OCLImage2dArrayDepthRO:2757 case ZigClangBuiltinTypeOCLImage2dArrayDepthRO:
2590 case clang::BuiltinType::OCLImage2dMSAARO:2758 case ZigClangBuiltinTypeOCLImage2dMSAARO:
2591 case clang::BuiltinType::OCLImage2dArrayMSAARO:2759 case ZigClangBuiltinTypeOCLImage2dArrayMSAARO:
2592 case clang::BuiltinType::OCLImage2dMSAADepthRO:2760 case ZigClangBuiltinTypeOCLImage2dMSAADepthRO:
2593 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:2761 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO:
2594 case clang::BuiltinType::OCLImage3dRO:2762 case ZigClangBuiltinTypeOCLImage3dRO:
2595 case clang::BuiltinType::OCLImage1dWO:2763 case ZigClangBuiltinTypeOCLImage1dWO:
2596 case clang::BuiltinType::OCLImage1dArrayWO:2764 case ZigClangBuiltinTypeOCLImage1dArrayWO:
2597 case clang::BuiltinType::OCLImage1dBufferWO:2765 case ZigClangBuiltinTypeOCLImage1dBufferWO:
2598 case clang::BuiltinType::OCLImage2dWO:2766 case ZigClangBuiltinTypeOCLImage2dWO:
2599 case clang::BuiltinType::OCLImage2dArrayWO:2767 case ZigClangBuiltinTypeOCLImage2dArrayWO:
2600 case clang::BuiltinType::OCLImage2dDepthWO:2768 case ZigClangBuiltinTypeOCLImage2dDepthWO:
2601 case clang::BuiltinType::OCLImage2dArrayDepthWO:2769 case ZigClangBuiltinTypeOCLImage2dArrayDepthWO:
2602 case clang::BuiltinType::OCLImage2dMSAAWO:2770 case ZigClangBuiltinTypeOCLImage2dMSAAWO:
2603 case clang::BuiltinType::OCLImage2dArrayMSAAWO:2771 case ZigClangBuiltinTypeOCLImage2dArrayMSAAWO:
2604 case clang::BuiltinType::OCLImage2dMSAADepthWO:2772 case ZigClangBuiltinTypeOCLImage2dMSAADepthWO:
2605 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:2773 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO:
2606 case clang::BuiltinType::OCLImage3dWO:2774 case ZigClangBuiltinTypeOCLImage3dWO:
2607 case clang::BuiltinType::OCLImage1dRW:2775 case ZigClangBuiltinTypeOCLImage1dRW:
2608 case clang::BuiltinType::OCLImage1dArrayRW:2776 case ZigClangBuiltinTypeOCLImage1dArrayRW:
2609 case clang::BuiltinType::OCLImage1dBufferRW:2777 case ZigClangBuiltinTypeOCLImage1dBufferRW:
2610 case clang::BuiltinType::OCLImage2dRW:2778 case ZigClangBuiltinTypeOCLImage2dRW:
2611 case clang::BuiltinType::OCLImage2dArrayRW:2779 case ZigClangBuiltinTypeOCLImage2dArrayRW:
2612 case clang::BuiltinType::OCLImage2dDepthRW:2780 case ZigClangBuiltinTypeOCLImage2dDepthRW:
2613 case clang::BuiltinType::OCLImage2dArrayDepthRW:2781 case ZigClangBuiltinTypeOCLImage2dArrayDepthRW:
2614 case clang::BuiltinType::OCLImage2dMSAARW:2782 case ZigClangBuiltinTypeOCLImage2dMSAARW:
2615 case clang::BuiltinType::OCLImage2dArrayMSAARW:2783 case ZigClangBuiltinTypeOCLImage2dArrayMSAARW:
2616 case clang::BuiltinType::OCLImage2dMSAADepthRW:2784 case ZigClangBuiltinTypeOCLImage2dMSAADepthRW:
2617 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:2785 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW:
2618 case clang::BuiltinType::OCLImage3dRW:2786 case ZigClangBuiltinTypeOCLImage3dRW:
2619 case clang::BuiltinType::OCLSampler:2787 case ZigClangBuiltinTypeOCLSampler:
2620 case clang::BuiltinType::OCLEvent:2788 case ZigClangBuiltinTypeOCLEvent:
2621 case clang::BuiltinType::OCLClkEvent:2789 case ZigClangBuiltinTypeOCLClkEvent:
2622 case clang::BuiltinType::OCLQueue:2790 case ZigClangBuiltinTypeOCLQueue:
2623 case clang::BuiltinType::OCLReserveID:2791 case ZigClangBuiltinTypeOCLReserveID:
2624 case clang::BuiltinType::ShortAccum:2792 case ZigClangBuiltinTypeShortAccum:
2625 case clang::BuiltinType::Accum:2793 case ZigClangBuiltinTypeAccum:
2626 case clang::BuiltinType::LongAccum:2794 case ZigClangBuiltinTypeLongAccum:
2627 case clang::BuiltinType::UShortAccum:2795 case ZigClangBuiltinTypeUShortAccum:
2628 case clang::BuiltinType::UAccum:2796 case ZigClangBuiltinTypeUAccum:
2629 case clang::BuiltinType::ULongAccum:2797 case ZigClangBuiltinTypeULongAccum:
2630 case clang::BuiltinType::ShortFract:2798 case ZigClangBuiltinTypeShortFract:
2631 case clang::BuiltinType::Fract:2799 case ZigClangBuiltinTypeFract:
2632 case clang::BuiltinType::LongFract:2800 case ZigClangBuiltinTypeLongFract:
2633 case clang::BuiltinType::UShortFract:2801 case ZigClangBuiltinTypeUShortFract:
2634 case clang::BuiltinType::UFract:2802 case ZigClangBuiltinTypeUFract:
2635 case clang::BuiltinType::ULongFract:2803 case ZigClangBuiltinTypeULongFract:
2636 case clang::BuiltinType::SatShortAccum:2804 case ZigClangBuiltinTypeSatShortAccum:
2637 case clang::BuiltinType::SatAccum:2805 case ZigClangBuiltinTypeSatAccum:
2638 case clang::BuiltinType::SatLongAccum:2806 case ZigClangBuiltinTypeSatLongAccum:
2639 case clang::BuiltinType::SatUShortAccum:2807 case ZigClangBuiltinTypeSatUShortAccum:
2640 case clang::BuiltinType::SatUAccum:2808 case ZigClangBuiltinTypeSatUAccum:
2641 case clang::BuiltinType::SatULongAccum:2809 case ZigClangBuiltinTypeSatULongAccum:
2642 case clang::BuiltinType::SatShortFract:2810 case ZigClangBuiltinTypeSatShortFract:
2643 case clang::BuiltinType::SatFract:2811 case ZigClangBuiltinTypeSatFract:
2644 case clang::BuiltinType::SatLongFract:2812 case ZigClangBuiltinTypeSatLongFract:
2645 case clang::BuiltinType::SatUShortFract:2813 case ZigClangBuiltinTypeSatUShortFract:
2646 case clang::BuiltinType::SatUFract:2814 case ZigClangBuiltinTypeSatUFract:
2647 case clang::BuiltinType::SatULongFract:2815 case ZigClangBuiltinTypeSatULongFract:
2648 case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:2816 case ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload:
2649 case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:2817 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload:
2650 case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:2818 case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload:
2651 case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:2819 case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload:
2652 case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:2820 case ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult:
2653 case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:2821 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult:
2654 case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:2822 case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult:
2655 case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:2823 case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult:
2656 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:2824 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout:
2657 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:2825 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout:
2658 case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:2826 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin:
2659 case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:2827 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin:
2660 return res;2828 return res;
2661 }2829 }
2662 break;2830 break;
2663 }2831 }
2664 case clang::Type::Pointer:2832 case ZigClangType_Pointer:
2665 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,2833 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2666 trans_create_node_unsigned(c, 0));
26672834
2668 case clang::Type::Typedef:2835 case ZigClangType_Typedef:
2669 {2836 {
2670 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);2837 const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
2671 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();2838 const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
2672 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());2839 auto existing_entry = c->decl_table.maybe_get((void*)ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl));
2673 if (existing_entry) {2840 if (existing_entry) {
2674 return existing_entry->value;2841 return existing_entry->value;
2675 }2842 }
...@@ -2677,19 +2844,20 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2677,19 +2844,20 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2677 return res;2844 return res;
2678 }2845 }
26792846
2680 case clang::Type::Enum:2847 case ZigClangType_Enum:
2681 {2848 {
2682 const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);2849 const ZigClangEnumType *enum_ty = reinterpret_cast<const ZigClangEnumType *>(ty);
2683 AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());2850 AstNode *enum_type = resolve_enum_decl(c, ZigClangEnumType_getDecl(enum_ty));
2684 return to_enum_zero_cmp(c, res, enum_type);2851 return to_enum_zero_cmp(c, res, enum_type);
2685 }2852 }
26862853
2687 case clang::Type::Elaborated:2854 case ZigClangType_Elaborated:
2688 {2855 {
2689 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);2856 const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty);
2690 switch (elaborated_ty->getKeyword()) {2857 switch (elaborated_ty->getKeyword()) {
2691 case clang::ETK_Enum: {2858 case clang::ETK_Enum: {
2692 AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginLoc());2859 AstNode *enum_type = trans_qual_type(c, bitcast(elaborated_ty->getNamedType()),
2860 ZigClangExpr_getBeginLoc(expr));
2693 return to_enum_zero_cmp(c, res, enum_type);2861 return to_enum_zero_cmp(c, res, enum_type);
2694 }2862 }
2695 case clang::ETK_Struct:2863 case clang::ETK_Struct:
...@@ -2702,48 +2870,48 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2702,48 +2870,48 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2702 }2870 }
2703 }2871 }
27042872
2705 case clang::Type::FunctionProto:2873 case ZigClangType_FunctionProto:
2706 case clang::Type::Record:2874 case ZigClangType_Record:
2707 case clang::Type::ConstantArray:2875 case ZigClangType_ConstantArray:
2708 case clang::Type::Paren:2876 case ZigClangType_Paren:
2709 case clang::Type::Decayed:2877 case ZigClangType_Decayed:
2710 case clang::Type::Attributed:2878 case ZigClangType_Attributed:
2711 case clang::Type::IncompleteArray:2879 case ZigClangType_IncompleteArray:
2712 case clang::Type::BlockPointer:2880 case ZigClangType_BlockPointer:
2713 case clang::Type::LValueReference:2881 case ZigClangType_LValueReference:
2714 case clang::Type::RValueReference:2882 case ZigClangType_RValueReference:
2715 case clang::Type::MemberPointer:2883 case ZigClangType_MemberPointer:
2716 case clang::Type::VariableArray:2884 case ZigClangType_VariableArray:
2717 case clang::Type::DependentSizedArray:2885 case ZigClangType_DependentSizedArray:
2718 case clang::Type::DependentSizedExtVector:2886 case ZigClangType_DependentSizedExtVector:
2719 case clang::Type::Vector:2887 case ZigClangType_Vector:
2720 case clang::Type::ExtVector:2888 case ZigClangType_ExtVector:
2721 case clang::Type::FunctionNoProto:2889 case ZigClangType_FunctionNoProto:
2722 case clang::Type::UnresolvedUsing:2890 case ZigClangType_UnresolvedUsing:
2723 case clang::Type::Adjusted:2891 case ZigClangType_Adjusted:
2724 case clang::Type::TypeOfExpr:2892 case ZigClangType_TypeOfExpr:
2725 case clang::Type::TypeOf:2893 case ZigClangType_TypeOf:
2726 case clang::Type::Decltype:2894 case ZigClangType_Decltype:
2727 case clang::Type::UnaryTransform:2895 case ZigClangType_UnaryTransform:
2728 case clang::Type::TemplateTypeParm:2896 case ZigClangType_TemplateTypeParm:
2729 case clang::Type::SubstTemplateTypeParm:2897 case ZigClangType_SubstTemplateTypeParm:
2730 case clang::Type::SubstTemplateTypeParmPack:2898 case ZigClangType_SubstTemplateTypeParmPack:
2731 case clang::Type::TemplateSpecialization:2899 case ZigClangType_TemplateSpecialization:
2732 case clang::Type::Auto:2900 case ZigClangType_Auto:
2733 case clang::Type::InjectedClassName:2901 case ZigClangType_InjectedClassName:
2734 case clang::Type::DependentName:2902 case ZigClangType_DependentName:
2735 case clang::Type::DependentTemplateSpecialization:2903 case ZigClangType_DependentTemplateSpecialization:
2736 case clang::Type::PackExpansion:2904 case ZigClangType_PackExpansion:
2737 case clang::Type::ObjCObject:2905 case ZigClangType_ObjCObject:
2738 case clang::Type::ObjCInterface:2906 case ZigClangType_ObjCInterface:
2739 case clang::Type::Complex:2907 case ZigClangType_Complex:
2740 case clang::Type::ObjCObjectPointer:2908 case ZigClangType_ObjCObjectPointer:
2741 case clang::Type::Atomic:2909 case ZigClangType_Atomic:
2742 case clang::Type::Pipe:2910 case ZigClangType_Pipe:
2743 case clang::Type::ObjCTypeParam:2911 case ZigClangType_ObjCTypeParam:
2744 case clang::Type::DeducedTemplateSpecialization:2912 case ZigClangType_DeducedTemplateSpecialization:
2745 case clang::Type::DependentAddressSpace:2913 case ZigClangType_DependentAddressSpace:
2746 case clang::Type::DependentVector:2914 case ZigClangType_DependentVector:
2747 return res;2915 return res;
2748 }2916 }
2749 zig_unreachable();2917 zig_unreachable();
...@@ -2752,11 +2920,12 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2752,11 +2920,12 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2752static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) {2920static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) {
2753 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);2921 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
27542922
2755 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);2923 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope,
2924 bitcast(stmt->getCond()), TransRValue);
2756 if (while_scope->node->data.while_expr.condition == nullptr)2925 if (while_scope->node->data.while_expr.condition == nullptr)
2757 return nullptr;2926 return nullptr;
27582927
2759 TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(),2928 TransScope *body_scope = trans_stmt(c, &while_scope->base, bitcast(stmt->getBody()),
2760 &while_scope->node->data.while_expr.body);2929 &while_scope->node->data.while_expr.body);
2761 if (body_scope == nullptr)2930 if (body_scope == nullptr)
2762 return nullptr;2931 return nullptr;
...@@ -2769,17 +2938,18 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::I...@@ -2769,17 +2938,18 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::I
2769 // if (c) t else e2938 // if (c) t else e
2770 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);2939 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
27712940
2772 TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block);2941 TransScope *then_scope = trans_stmt(c, scope, bitcast(stmt->getThen()), &if_node->data.if_bool_expr.then_block);
2773 if (then_scope == nullptr)2942 if (then_scope == nullptr)
2774 return nullptr;2943 return nullptr;
27752944
2776 if (stmt->getElse() != nullptr) {2945 if (stmt->getElse() != nullptr) {
2777 TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node);2946 TransScope *else_scope = trans_stmt(c, scope, bitcast(stmt->getElse()), &if_node->data.if_bool_expr.else_node);
2778 if (else_scope == nullptr)2947 if (else_scope == nullptr)
2779 return nullptr;2948 return nullptr;
2780 }2949 }
27812950
2782 if_node->data.if_bool_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);2951 if_node->data.if_bool_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, bitcast(stmt->getCond()),
2952 TransRValue);
2783 if (if_node->data.if_bool_expr.condition == nullptr)2953 if (if_node->data.if_bool_expr.condition == nullptr)
2784 return nullptr;2954 return nullptr;
27852955
...@@ -2789,18 +2959,18 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::I...@@ -2789,18 +2959,18 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::I
2789static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) {2959static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) {
2790 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);2960 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
27912961
2792 AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue);2962 AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getCallee()), TransRValue);
2793 if (callee_raw_node == nullptr)2963 if (callee_raw_node == nullptr)
2794 return nullptr;2964 return nullptr;
27952965
2796 bool is_ptr = false;2966 bool is_ptr = false;
2797 const clang::FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);2967 const clang::FunctionProtoType *fn_ty = qual_type_get_fn_proto(bitcast(stmt->getCallee()->getType()), &is_ptr);
2798 AstNode *callee_node = nullptr;2968 AstNode *callee_node = nullptr;
2799 if (is_ptr && fn_ty) {2969 if (is_ptr && fn_ty) {
2800 if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {2970 if ((ZigClangStmtClass)stmt->getCallee()->getStmtClass() == ZigClangStmt_ImplicitCastExprClass) {
2801 const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee());2971 const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee());
2802 if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) {2972 if ((ZigClangCK)implicit_cast->getCastKind() == ZigClangCK_FunctionToPointerDecay) {
2803 if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) {2973 if ((ZigClangStmtClass)implicit_cast->getSubExpr()->getStmtClass() == ZigClangStmt_DeclRefExprClass) {
2804 const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr());2974 const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr());
2805 const clang::Decl *decl = decl_ref->getFoundDecl();2975 const clang::Decl *decl = decl_ref->getFoundDecl();
2806 if (decl->getKind() == clang::Decl::Function) {2976 if (decl->getKind() == clang::Decl::Function) {
...@@ -2819,7 +2989,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2819,7 +2989,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
2819 node->data.fn_call_expr.fn_ref_expr = callee_node;2989 node->data.fn_call_expr.fn_ref_expr = callee_node;
28202990
2821 unsigned num_args = stmt->getNumArgs();2991 unsigned num_args = stmt->getNumArgs();
2822 const clang::Expr * const* args = stmt->getArgs();2992 const ZigClangExpr * const* args = reinterpret_cast<const ZigClangExpr * const*>(stmt->getArgs());
2823 for (unsigned i = 0; i < num_args; i += 1) {2993 for (unsigned i = 0; i < num_args; i += 1) {
2824 AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);2994 AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);
2825 if (arg_node == nullptr)2995 if (arg_node == nullptr)
...@@ -2828,7 +2998,9 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2828,7 +2998,9 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
2828 node->data.fn_call_expr.params.append(arg_node);2998 node->data.fn_call_expr.params.append(arg_node);
2829 }2999 }
28303000
2831 if (result_used == ResultUsedNo && fn_ty && !qual_type_canon(fn_ty->getReturnType())->isVoidType()) {3001 if (result_used == ResultUsedNo && fn_ty &&
3002 !ZigClangType_isVoidType(qual_type_canon(bitcast(fn_ty->getReturnType()))))
3003 {
2832 node = trans_create_node_bin_op(c, trans_create_node_symbol_str(c, "_"), BinOpTypeAssign, node);3004 node = trans_create_node_bin_op(c, trans_create_node_symbol_str(c, "_"), BinOpTypeAssign, node);
2833 }3005 }
28343006
...@@ -2838,7 +3010,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2838,7 +3010,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
2838static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope *scope,3010static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope *scope,
2839 const clang::MemberExpr *stmt)3011 const clang::MemberExpr *stmt)
2840{3012{
2841 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);3013 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getBase()), TransRValue);
2842 if (container_node == nullptr)3014 if (container_node == nullptr)
2843 return nullptr;3015 return nullptr;
28443016
...@@ -2846,18 +3018,18 @@ static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope...@@ -2846,18 +3018,18 @@ static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope
2846 container_node = trans_create_node_unwrap_null(c, container_node);3018 container_node = trans_create_node_unwrap_null(c, container_node);
2847 }3019 }
28483020
2849 const char *name = decl_name(stmt->getMemberDecl());3021 const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)stmt->getMemberDecl());
28503022
2851 AstNode *node = trans_create_node_field_access_str(c, container_node, name);3023 AstNode *node = trans_create_node_field_access_str(c, container_node, name);
2852 return maybe_suppress_result(c, result_used, node);3024 return maybe_suppress_result(c, result_used, node);
2853}3025}
28543026
2855static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ArraySubscriptExpr *stmt) {3027static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ArraySubscriptExpr *stmt) {
2856 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);3028 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getBase()), TransRValue);
2857 if (container_node == nullptr)3029 if (container_node == nullptr)
2858 return nullptr;3030 return nullptr;
28593031
2860 AstNode *idx_node = trans_expr(c, ResultUsedYes, scope, stmt->getIdx(), TransRValue);3032 AstNode *idx_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getIdx()), TransRValue);
2861 if (idx_node == nullptr)3033 if (idx_node == nullptr)
2862 return nullptr;3034 return nullptr;
28633035
...@@ -2871,11 +3043,12 @@ static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, T...@@ -2871,11 +3043,12 @@ static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, T
2871static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,3043static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,
2872 const clang::CStyleCastExpr *stmt, TransLRValue lrvalue)3044 const clang::CStyleCastExpr *stmt, TransLRValue lrvalue)
2873{3045{
2874 AstNode *sub_expr_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), lrvalue);3046 AstNode *sub_expr_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), lrvalue);
2875 if (sub_expr_node == nullptr)3047 if (sub_expr_node == nullptr)
2876 return nullptr;3048 return nullptr;
28773049
2878 AstNode *cast = trans_c_cast(c, stmt->getBeginLoc(), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node);3050 AstNode *cast = trans_c_cast(c, bitcast(stmt->getBeginLoc()), bitcast(stmt->getType()),
3051 bitcast(stmt->getSubExpr()->getType()), sub_expr_node);
2879 if (cast == nullptr)3052 if (cast == nullptr)
2880 return nullptr;3053 return nullptr;
28813054
...@@ -2885,7 +3058,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran...@@ -2885,7 +3058,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran
2885static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, ResultUsed result_used,3058static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, ResultUsed result_used,
2886 TransScope *scope, const clang::UnaryExprOrTypeTraitExpr *stmt)3059 TransScope *scope, const clang::UnaryExprOrTypeTraitExpr *stmt)
2887{3060{
2888 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getBeginLoc());3061 AstNode *type_node = trans_qual_type(c, bitcast(stmt->getTypeOfArgument()), bitcast(stmt->getBeginLoc()));
2889 if (type_node == nullptr)3062 if (type_node == nullptr)
2890 return nullptr;3063 return nullptr;
28913064
...@@ -2901,7 +3074,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:...@@ -2901,7 +3074,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:
29013074
2902 AstNode *body_node;3075 AstNode *body_node;
2903 TransScope *child_scope;3076 TransScope *child_scope;
2904 if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) {3077 if ((ZigClangStmtClass)stmt->getBody()->getStmtClass() == ZigClangStmt_CompoundStmtClass) {
2905 // there's already a block in C, so we'll append our condition to it.3078 // there's already a block in C, so we'll append our condition to it.
2906 // c: do {3079 // c: do {
2907 // c: a;3080 // c: a;
...@@ -2914,7 +3087,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:...@@ -2914,7 +3087,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:
2914 // zig: }3087 // zig: }
29153088
2916 // We call the low level function so that we can set child_scope to the scope of the generated block.3089 // We call the low level function so that we can set child_scope to the scope of the generated block.
2917 if (trans_stmt_extra(c, &while_scope->base, stmt->getBody(), ResultUsedNo, TransRValue, &body_node,3090 if (trans_stmt_extra(c, &while_scope->base, bitcast(stmt->getBody()), ResultUsedNo, TransRValue, &body_node,
2918 nullptr, &child_scope))3091 nullptr, &child_scope))
2919 {3092 {
2920 return nullptr;3093 return nullptr;
...@@ -2932,7 +3105,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:...@@ -2932,7 +3105,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:
2932 TransScopeBlock *child_block_scope = trans_scope_block_create(c, &while_scope->base);3105 TransScopeBlock *child_block_scope = trans_scope_block_create(c, &while_scope->base);
2933 body_node = child_block_scope->node;3106 body_node = child_block_scope->node;
2934 AstNode *child_statement;3107 AstNode *child_statement;
2935 child_scope = trans_stmt(c, &child_block_scope->base, stmt->getBody(), &child_statement);3108 child_scope = trans_stmt(c, &child_block_scope->base, bitcast(stmt->getBody()), &child_statement);
2936 if (child_scope == nullptr) return nullptr;3109 if (child_scope == nullptr) return nullptr;
2937 if (child_statement != nullptr) {3110 if (child_statement != nullptr) {
2938 body_node->data.block.statements.append(child_statement);3111 body_node->data.block.statements.append(child_statement);
...@@ -2940,7 +3113,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:...@@ -2940,7 +3113,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang:
2940 }3113 }
29413114
2942 // if (!cond) break;3115 // if (!cond) break;
2943 AstNode *condition_node = trans_expr(c, ResultUsedYes, child_scope, stmt->getCond(), TransRValue);3116 AstNode *condition_node = trans_expr(c, ResultUsedYes, child_scope, bitcast(stmt->getCond()), TransRValue);
2944 if (condition_node == nullptr) return nullptr;3117 if (condition_node == nullptr) return nullptr;
2945 AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr);3118 AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr);
2946 terminator_node->data.if_bool_expr.condition = trans_create_node_prefix_op(c, PrefixOpBoolNot, condition_node);3119 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...@@ -2958,7 +3131,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang
2958 AstNode *loop_block_node;3131 AstNode *loop_block_node;
2959 TransScopeWhile *while_scope;3132 TransScopeWhile *while_scope;
2960 TransScope *cond_scope;3133 TransScope *cond_scope;
2961 const clang::Stmt *init_stmt = stmt->getInit();3134 const ZigClangStmt *init_stmt = bitcast(stmt->getInit());
2962 if (init_stmt == nullptr) {3135 if (init_stmt == nullptr) {
2963 while_scope = trans_scope_while_create(c, parent_scope);3136 while_scope = trans_scope_while_create(c, parent_scope);
2964 loop_block_node = while_scope->node;3137 loop_block_node = while_scope->node;
...@@ -2979,35 +3152,27 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang...@@ -2979,35 +3152,27 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang
2979 child_scope->node->data.block.statements.append(while_scope->node);3152 child_scope->node->data.block.statements.append(while_scope->node);
2980 }3153 }
29813154
2982 const clang::Stmt *cond_stmt = stmt->getCond();3155 const ZigClangExpr *cond_expr = bitcast(stmt->getCond());
2983 if (cond_stmt == nullptr) {3156 if (cond_expr == nullptr) {
2984 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);3157 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
2985 } else {3158 } else {
2986 if (clang::Expr::classof(cond_stmt)) {3159 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope,
2987 const clang::Expr *cond_expr = static_cast<const clang::Expr*>(cond_stmt);3160 cond_expr, TransRValue);
2988 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
29893161
2990 if (while_scope->node->data.while_expr.condition == nullptr)3162 if (while_scope->node->data.while_expr.condition == nullptr)
2991 return nullptr;3163 return nullptr;
2992 } else {
2993 TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt,
2994 &while_scope->node->data.while_expr.condition);
2995 if (end_cond_scope == nullptr)
2996 return nullptr;
2997 }
2998 }3164 }
29993165
3000 const clang::Stmt *inc_stmt = stmt->getInc();3166 const ZigClangExpr *inc_expr = bitcast(stmt->getInc());
3001 if (inc_stmt != nullptr) {3167 if (inc_expr != nullptr) {
3002 AstNode *inc_node;3168 AstNode *inc_node = trans_expr(c, ResultUsedNo, cond_scope, inc_expr, TransRValue);
3003 TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node);3169 if (inc_node == nullptr)
3004 if (inc_scope == nullptr)
3005 return nullptr;3170 return nullptr;
3006 while_scope->node->data.while_expr.continue_expr = inc_node;3171 while_scope->node->data.while_expr.continue_expr = inc_node;
3007 }3172 }
30083173
3009 AstNode *body_statement;3174 AstNode *body_statement;
3010 TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(), &body_statement);3175 TransScope *body_scope = trans_stmt(c, &while_scope->base, bitcast(stmt->getBody()), &body_statement);
3011 if (body_scope == nullptr)3176 if (body_scope == nullptr)
3012 return nullptr;3177 return nullptr;
30133178
...@@ -3030,7 +3195,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl...@@ -3030,7 +3195,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl
3030 switch_scope = trans_scope_switch_create(c, &block_scope->base);3195 switch_scope = trans_scope_switch_create(c, &block_scope->base);
3031 } else {3196 } else {
3032 AstNode *vars_node;3197 AstNode *vars_node;
3033 TransScope *var_scope = trans_stmt(c, &block_scope->base, var_decl_stmt, &vars_node);3198 TransScope *var_scope = trans_stmt(c, &block_scope->base, (const ZigClangStmt *)var_decl_stmt, &vars_node);
3034 if (var_scope == nullptr)3199 if (var_scope == nullptr)
3035 return nullptr;3200 return nullptr;
3036 if (vars_node != nullptr)3201 if (vars_node != nullptr)
...@@ -3044,7 +3209,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl...@@ -3044,7 +3209,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl
3044 switch_scope->end_label_name = end_label_name;3209 switch_scope->end_label_name = end_label_name;
3045 block_scope->node->data.block.name = end_label_name;3210 block_scope->node->data.block.name = end_label_name;
30463211
3047 const clang::Expr *cond_expr = stmt->getCond();3212 const ZigClangExpr *cond_expr = bitcast(stmt->getCond());
3048 assert(cond_expr != nullptr);3213 assert(cond_expr != nullptr);
30493214
3050 AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue);3215 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...@@ -3053,9 +3218,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl
3053 switch_scope->switch_node->data.switch_expr.expr = expr_node;3218 switch_scope->switch_node->data.switch_expr.expr = expr_node;
30543219
3055 AstNode *body_node;3220 AstNode *body_node;
3056 const clang::Stmt *body_stmt = stmt->getBody();3221 const ZigClangStmt *body_stmt = bitcast(stmt->getBody());
3057 if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) {3222 if (ZigClangStmt_getStmtClass(body_stmt) == ZigClangStmt_CompoundStmtClass) {
3058 if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt,3223 if (trans_compound_stmt_inline(c, &switch_scope->base, (const ZigClangCompoundStmt *)body_stmt,
3059 block_scope->node, nullptr))3224 block_scope->node, nullptr))
3060 {3225 {
3061 return nullptr;3226 return nullptr;
...@@ -3092,7 +3257,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::...@@ -3092,7 +3257,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::
3092 *out_node = nullptr;3257 *out_node = nullptr;
30933258
3094 if (stmt->getRHS() != nullptr) {3259 if (stmt->getRHS() != nullptr) {
3095 emit_warning(c, stmt->getBeginLoc(), "TODO support GNU switch case a ... b extension");3260 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support GNU switch case a ... b extension");
3096 return ErrorUnexpected;3261 return ErrorUnexpected;
3097 }3262 }
30983263
...@@ -3105,7 +3270,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::...@@ -3105,7 +3270,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::
3105 {3270 {
3106 // Add the prong3271 // Add the prong
3107 AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng);3272 AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng);
3108 AstNode *item_node = trans_expr(c, ResultUsedYes, &switch_scope->base, stmt->getLHS(), TransRValue);3273 AstNode *item_node = trans_expr(c, ResultUsedYes, &switch_scope->base, bitcast(stmt->getLHS()), TransRValue);
3109 if (item_node == nullptr)3274 if (item_node == nullptr)
3110 return ErrorUnexpected;3275 return ErrorUnexpected;
3111 prong_node->data.switch_prong.items.append(item_node);3276 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::...@@ -3122,7 +3287,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::
3122 scope_block->node->data.block.statements.append(case_block);3287 scope_block->node->data.block.statements.append(case_block);
31233288
3124 AstNode *sub_stmt_node;3289 AstNode *sub_stmt_node;
3125 TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node);3290 TransScope *new_scope = trans_stmt(c, parent_scope, bitcast(stmt->getSubStmt()), &sub_stmt_node);
3126 if (new_scope == nullptr)3291 if (new_scope == nullptr)
3127 return ErrorUnexpected;3292 return ErrorUnexpected;
3128 if (sub_stmt_node != nullptr)3293 if (sub_stmt_node != nullptr)
...@@ -3159,7 +3324,7 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const clan...@@ -3159,7 +3324,7 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const clan
3159 scope_block->node->data.block.statements.append(case_block);3324 scope_block->node->data.block.statements.append(case_block);
31603325
3161 AstNode *sub_stmt_node;3326 AstNode *sub_stmt_node;
3162 TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node);3327 TransScope *new_scope = trans_stmt(c, parent_scope, bitcast(stmt->getSubStmt()), &sub_stmt_node);
3163 if (new_scope == nullptr)3328 if (new_scope == nullptr)
3164 return ErrorUnexpected;3329 return ErrorUnexpected;
3165 if (sub_stmt_node != nullptr)3330 if (sub_stmt_node != nullptr)
...@@ -3177,13 +3342,13 @@ static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransSc...@@ -3177,13 +3342,13 @@ static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransSc
3177 return maybe_suppress_result(c, result_used, node);3342 return maybe_suppress_result(c, result_used, node);
3178 }3343 }
3179 case clang::StringLiteral::UTF16:3344 case clang::StringLiteral::UTF16:
3180 emit_warning(c, stmt->getBeginLoc(), "TODO support UTF16 string literals");3345 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF16 string literals");
3181 return nullptr;3346 return nullptr;
3182 case clang::StringLiteral::UTF32:3347 case clang::StringLiteral::UTF32:
3183 emit_warning(c, stmt->getBeginLoc(), "TODO support UTF32 string literals");3348 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF32 string literals");
3184 return nullptr;3349 return nullptr;
3185 case clang::StringLiteral::Wide:3350 case clang::StringLiteral::Wide:
3186 emit_warning(c, stmt->getBeginLoc(), "TODO support wide string literals");3351 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support wide string literals");
3187 return nullptr;3352 return nullptr;
3188 }3353 }
3189 zig_unreachable();3354 zig_unreachable();
...@@ -3222,45 +3387,45 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_...@@ -3222,45 +3387,45 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_
3222 return ErrorNone;3387 return ErrorNone;
3223}3388}
32243389
3225static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,3390static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *stmt,
3226 ResultUsed result_used, TransLRValue lrvalue,3391 ResultUsed result_used, TransLRValue lrvalue,
3227 AstNode **out_node, TransScope **out_child_scope,3392 AstNode **out_node, TransScope **out_child_scope,
3228 TransScope **out_node_scope)3393 TransScope **out_node_scope)
3229{3394{
3230 clang::Stmt::StmtClass sc = stmt->getStmtClass();3395 ZigClangStmtClass sc = ZigClangStmt_getStmtClass(stmt);
3231 switch (sc) {3396 switch (sc) {
3232 case clang::Stmt::ReturnStmtClass:3397 case ZigClangStmt_ReturnStmtClass:
3233 return wrap_stmt(out_node, out_child_scope, scope,3398 return wrap_stmt(out_node, out_child_scope, scope,
3234 trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));3399 trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));
3235 case clang::Stmt::CompoundStmtClass:3400 case ZigClangStmt_CompoundStmtClass:
3236 return wrap_stmt(out_node, out_child_scope, scope,3401 return wrap_stmt(out_node, out_child_scope, scope,
3237 trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));3402 trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt, out_node_scope));
3238 case clang::Stmt::IntegerLiteralClass:3403 case ZigClangStmt_IntegerLiteralClass:
3239 return wrap_stmt(out_node, out_child_scope, scope,3404 return wrap_stmt(out_node, out_child_scope, scope,
3240 trans_integer_literal(c, result_used, (const clang::IntegerLiteral *)stmt));3405 trans_integer_literal(c, result_used, (const clang::IntegerLiteral *)stmt));
3241 case clang::Stmt::ConditionalOperatorClass:3406 case ZigClangStmt_ConditionalOperatorClass:
3242 return wrap_stmt(out_node, out_child_scope, scope,3407 return wrap_stmt(out_node, out_child_scope, scope,
3243 trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));3408 trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));
3244 case clang::Stmt::BinaryOperatorClass:3409 case ZigClangStmt_BinaryOperatorClass:
3245 return wrap_stmt(out_node, out_child_scope, scope,3410 return wrap_stmt(out_node, out_child_scope, scope,
3246 trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt));3411 trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt));
3247 case clang::Stmt::CompoundAssignOperatorClass:3412 case ZigClangStmt_CompoundAssignOperatorClass:
3248 return wrap_stmt(out_node, out_child_scope, scope,3413 return wrap_stmt(out_node, out_child_scope, scope,
3249 trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));3414 trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));
3250 case clang::Stmt::ImplicitCastExprClass:3415 case ZigClangStmt_ImplicitCastExprClass:
3251 return wrap_stmt(out_node, out_child_scope, scope,3416 return wrap_stmt(out_node, out_child_scope, scope,
3252 trans_implicit_cast_expr(c, result_used, scope, (const clang::ImplicitCastExpr *)stmt));3417 trans_implicit_cast_expr(c, result_used, scope, (const clang::ImplicitCastExpr *)stmt));
3253 case clang::Stmt::DeclRefExprClass:3418 case ZigClangStmt_DeclRefExprClass:
3254 return wrap_stmt(out_node, out_child_scope, scope,3419 return wrap_stmt(out_node, out_child_scope, scope,
3255 trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));3420 trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));
3256 case clang::Stmt::UnaryOperatorClass:3421 case ZigClangStmt_UnaryOperatorClass:
3257 return wrap_stmt(out_node, out_child_scope, scope,3422 return wrap_stmt(out_node, out_child_scope, scope,
3258 trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt));3423 trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt));
3259 case clang::Stmt::DeclStmtClass:3424 case ZigClangStmt_DeclStmtClass:
3260 return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope);3425 return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope);
3261 case clang::Stmt::DoStmtClass:3426 case ZigClangStmt_DoStmtClass:
3262 case clang::Stmt::WhileStmtClass: {3427 case ZigClangStmt_WhileStmtClass: {
3263 AstNode *while_node = sc == clang::Stmt::DoStmtClass3428 AstNode *while_node = sc == ZigClangStmt_DoStmtClass
3264 ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt)3429 ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt)
3265 : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt);3430 : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt);
32663431
...@@ -3273,572 +3438,574 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st...@@ -3273,572 +3438,574 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st
32733438
3274 return wrap_stmt(out_node, out_child_scope, scope, while_node);3439 return wrap_stmt(out_node, out_child_scope, scope, while_node);
3275 }3440 }
3276 case clang::Stmt::IfStmtClass:3441 case ZigClangStmt_IfStmtClass:
3277 return wrap_stmt(out_node, out_child_scope, scope,3442 return wrap_stmt(out_node, out_child_scope, scope,
3278 trans_if_statement(c, scope, (const clang::IfStmt *)stmt));3443 trans_if_statement(c, scope, (const clang::IfStmt *)stmt));
3279 case clang::Stmt::CallExprClass:3444 case ZigClangStmt_CallExprClass:
3280 return wrap_stmt(out_node, out_child_scope, scope,3445 return wrap_stmt(out_node, out_child_scope, scope,
3281 trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));3446 trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));
3282 case clang::Stmt::NullStmtClass:3447 case ZigClangStmt_NullStmtClass:
3283 *out_node = trans_create_node(c, NodeTypeBlock);3448 *out_node = trans_create_node(c, NodeTypeBlock);
3284 *out_child_scope = scope;3449 *out_child_scope = scope;
3285 return ErrorNone;3450 return ErrorNone;
3286 case clang::Stmt::MemberExprClass:3451 case ZigClangStmt_MemberExprClass:
3287 return wrap_stmt(out_node, out_child_scope, scope,3452 return wrap_stmt(out_node, out_child_scope, scope,
3288 trans_member_expr(c, result_used, scope, (const clang::MemberExpr *)stmt));3453 trans_member_expr(c, result_used, scope, (const clang::MemberExpr *)stmt));
3289 case clang::Stmt::ArraySubscriptExprClass:3454 case ZigClangStmt_ArraySubscriptExprClass:
3290 return wrap_stmt(out_node, out_child_scope, scope,3455 return wrap_stmt(out_node, out_child_scope, scope,
3291 trans_array_subscript_expr(c, result_used, scope, (const clang::ArraySubscriptExpr *)stmt));3456 trans_array_subscript_expr(c, result_used, scope, (const clang::ArraySubscriptExpr *)stmt));
3292 case clang::Stmt::CStyleCastExprClass:3457 case ZigClangStmt_CStyleCastExprClass:
3293 return wrap_stmt(out_node, out_child_scope, scope,3458 return wrap_stmt(out_node, out_child_scope, scope,
3294 trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));3459 trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));
3295 case clang::Stmt::UnaryExprOrTypeTraitExprClass:3460 case ZigClangStmt_UnaryExprOrTypeTraitExprClass:
3296 return wrap_stmt(out_node, out_child_scope, scope,3461 return wrap_stmt(out_node, out_child_scope, scope,
3297 trans_unary_expr_or_type_trait_expr(c, result_used, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));3462 trans_unary_expr_or_type_trait_expr(c, result_used, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
3298 case clang::Stmt::ForStmtClass: {3463 case ZigClangStmt_ForStmtClass: {
3299 AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);3464 AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);
3300 return wrap_stmt(out_node, out_child_scope, scope, node);3465 return wrap_stmt(out_node, out_child_scope, scope, node);
3301 }3466 }
3302 case clang::Stmt::StringLiteralClass:3467 case ZigClangStmt_StringLiteralClass:
3303 return wrap_stmt(out_node, out_child_scope, scope,3468 return wrap_stmt(out_node, out_child_scope, scope,
3304 trans_string_literal(c, result_used, scope, (const clang::StringLiteral *)stmt));3469 trans_string_literal(c, result_used, scope, (const clang::StringLiteral *)stmt));
3305 case clang::Stmt::BreakStmtClass:3470 case ZigClangStmt_BreakStmtClass:
3306 return wrap_stmt(out_node, out_child_scope, scope,3471 return wrap_stmt(out_node, out_child_scope, scope,
3307 trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));3472 trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));
3308 case clang::Stmt::ContinueStmtClass:3473 case ZigClangStmt_ContinueStmtClass:
3309 return wrap_stmt(out_node, out_child_scope, scope,3474 return wrap_stmt(out_node, out_child_scope, scope,
3310 trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt));3475 trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt));
3311 case clang::Stmt::ParenExprClass:3476 case ZigClangStmt_ParenExprClass:
3312 return wrap_stmt(out_node, out_child_scope, scope,3477 return wrap_stmt(out_node, out_child_scope, scope,
3313 trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue));3478 trans_expr(c, result_used, scope,
3314 case clang::Stmt::SwitchStmtClass:3479 bitcast(((const clang::ParenExpr*)stmt)->getSubExpr()), lrvalue));
3480 case ZigClangStmt_SwitchStmtClass:
3315 return wrap_stmt(out_node, out_child_scope, scope,3481 return wrap_stmt(out_node, out_child_scope, scope,
3316 trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt));3482 trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt));
3317 case clang::Stmt::CaseStmtClass:3483 case ZigClangStmt_CaseStmtClass:
3318 return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope);3484 return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope);
3319 case clang::Stmt::DefaultStmtClass:3485 case ZigClangStmt_DefaultStmtClass:
3320 return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope);3486 return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope);
3321 case clang::Stmt::ConstantExprClass:3487 case ZigClangStmt_ConstantExprClass:
3322 return wrap_stmt(out_node, out_child_scope, scope,3488 return wrap_stmt(out_node, out_child_scope, scope,
3323 trans_constant_expr(c, result_used, (const clang::ConstantExpr *)stmt));3489 trans_constant_expr(c, result_used, (const clang::ConstantExpr *)stmt));
3324 case clang::Stmt::PredefinedExprClass:3490 case ZigClangStmt_PredefinedExprClass:
3325 return wrap_stmt(out_node, out_child_scope, scope,3491 return wrap_stmt(out_node, out_child_scope, scope,
3326 trans_predefined_expr(c, result_used, scope, (const clang::PredefinedExpr *)stmt));3492 trans_predefined_expr(c, result_used, scope, (const clang::PredefinedExpr *)stmt));
3327 case clang::Stmt::StmtExprClass:3493 case ZigClangStmt_StmtExprClass:
3328 return wrap_stmt(out_node, out_child_scope, scope,3494 return wrap_stmt(out_node, out_child_scope, scope,
3329 trans_stmt_expr(c, result_used, scope, (const clang::StmtExpr *)stmt, out_node_scope));3495 trans_stmt_expr(c, result_used, scope, (const clang::StmtExpr *)stmt, out_node_scope));
3330 case clang::Stmt::NoStmtClass:3496 case ZigClangStmt_NoStmtClass:
3331 emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoStmtClass");3497 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C NoStmtClass");
3332 return ErrorUnexpected;
3333 case clang::Stmt::GCCAsmStmtClass:
3334 emit_warning(c, stmt->getBeginLoc(), "TODO handle C GCCAsmStmtClass");
3335 return ErrorUnexpected;3498 return ErrorUnexpected;
3336 case clang::Stmt::MSAsmStmtClass:3499 case ZigClangStmt_GCCAsmStmtClass:
3337 emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSAsmStmtClass");3500 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GCCAsmStmtClass");
3338 return ErrorUnexpected;3501 return ErrorUnexpected;
3339 case clang::Stmt::AttributedStmtClass:3502 case ZigClangStmt_MSAsmStmtClass:
3340 emit_warning(c, stmt->getBeginLoc(), "TODO handle C AttributedStmtClass");3503 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSAsmStmtClass");
3341 return ErrorUnexpected;3504 return ErrorUnexpected;
3342 case clang::Stmt::CXXCatchStmtClass:3505 case ZigClangStmt_AttributedStmtClass:
3343 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXCatchStmtClass");3506 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AttributedStmtClass");
3344 return ErrorUnexpected;3507 return ErrorUnexpected;
3345 case clang::Stmt::CXXForRangeStmtClass:3508 case ZigClangStmt_CXXCatchStmtClass:
3346 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXForRangeStmtClass");3509 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXCatchStmtClass");
3347 return ErrorUnexpected;3510 return ErrorUnexpected;
3348 case clang::Stmt::CXXTryStmtClass:3511 case ZigClangStmt_CXXForRangeStmtClass:
3349 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTryStmtClass");3512 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXForRangeStmtClass");
3350 return ErrorUnexpected;3513 return ErrorUnexpected;
3351 case clang::Stmt::CapturedStmtClass:3514 case ZigClangStmt_CXXTryStmtClass:
3352 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CapturedStmtClass");3515 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTryStmtClass");
3353 return ErrorUnexpected;3516 return ErrorUnexpected;
3354 case clang::Stmt::CoreturnStmtClass:3517 case ZigClangStmt_CapturedStmtClass:
3355 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoreturnStmtClass");3518 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CapturedStmtClass");
3356 return ErrorUnexpected;3519 return ErrorUnexpected;
3357 case clang::Stmt::CoroutineBodyStmtClass:3520 case ZigClangStmt_CoreturnStmtClass:
3358 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoroutineBodyStmtClass");3521 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoreturnStmtClass");
3359 return ErrorUnexpected;3522 return ErrorUnexpected;
3360 case clang::Stmt::BinaryConditionalOperatorClass:3523 case ZigClangStmt_CoroutineBodyStmtClass:
3361 emit_warning(c, stmt->getBeginLoc(), "TODO handle C BinaryConditionalOperatorClass");3524 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoroutineBodyStmtClass");
3362 return ErrorUnexpected;3525 return ErrorUnexpected;
3363 case clang::Stmt::AddrLabelExprClass:3526 case ZigClangStmt_BinaryConditionalOperatorClass:
3364 emit_warning(c, stmt->getBeginLoc(), "TODO handle C AddrLabelExprClass");3527 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C BinaryConditionalOperatorClass");
3365 return ErrorUnexpected;3528 return ErrorUnexpected;
3366 case clang::Stmt::ArrayInitIndexExprClass:3529 case ZigClangStmt_AddrLabelExprClass:
3367 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitIndexExprClass");3530 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AddrLabelExprClass");
3368 return ErrorUnexpected;3531 return ErrorUnexpected;
3369 case clang::Stmt::ArrayInitLoopExprClass:3532 case ZigClangStmt_ArrayInitIndexExprClass:
3370 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitLoopExprClass");3533 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayInitIndexExprClass");
3371 return ErrorUnexpected;3534 return ErrorUnexpected;
3372 case clang::Stmt::ArrayTypeTraitExprClass:3535 case ZigClangStmt_ArrayInitLoopExprClass:
3373 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayTypeTraitExprClass");3536 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayInitLoopExprClass");
3374 return ErrorUnexpected;3537 return ErrorUnexpected;
3375 case clang::Stmt::AsTypeExprClass:3538 case ZigClangStmt_ArrayTypeTraitExprClass:
3376 emit_warning(c, stmt->getBeginLoc(), "TODO handle C AsTypeExprClass");3539 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayTypeTraitExprClass");
3377 return ErrorUnexpected;3540 return ErrorUnexpected;
3378 case clang::Stmt::AtomicExprClass:3541 case ZigClangStmt_AsTypeExprClass:
3379 emit_warning(c, stmt->getBeginLoc(), "TODO handle C AtomicExprClass");3542 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AsTypeExprClass");
3380 return ErrorUnexpected;3543 return ErrorUnexpected;
3381 case clang::Stmt::BlockExprClass:3544 case ZigClangStmt_AtomicExprClass:
3382 emit_warning(c, stmt->getBeginLoc(), "TODO handle C BlockExprClass");3545 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AtomicExprClass");
3383 return ErrorUnexpected;3546 return ErrorUnexpected;
3384 case clang::Stmt::CXXBindTemporaryExprClass:3547 case ZigClangStmt_BlockExprClass:
3385 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBindTemporaryExprClass");3548 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C BlockExprClass");
3386 return ErrorUnexpected;3549 return ErrorUnexpected;
3387 case clang::Stmt::CXXBoolLiteralExprClass:3550 case ZigClangStmt_CXXBindTemporaryExprClass:
3388 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBoolLiteralExprClass");3551 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXBindTemporaryExprClass");
3389 return ErrorUnexpected;3552 return ErrorUnexpected;
3390 case clang::Stmt::CXXConstructExprClass:3553 case ZigClangStmt_CXXBoolLiteralExprClass:
3391 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstructExprClass");3554 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXBoolLiteralExprClass");
3392 return ErrorUnexpected;3555 return ErrorUnexpected;
3393 case clang::Stmt::CXXTemporaryObjectExprClass:3556 case ZigClangStmt_CXXConstructExprClass:
3394 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTemporaryObjectExprClass");3557 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXConstructExprClass");
3395 return ErrorUnexpected;3558 return ErrorUnexpected;
3396 case clang::Stmt::CXXDefaultArgExprClass:3559 case ZigClangStmt_CXXTemporaryObjectExprClass:
3397 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultArgExprClass");3560 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTemporaryObjectExprClass");
3398 return ErrorUnexpected;3561 return ErrorUnexpected;
3399 case clang::Stmt::CXXDefaultInitExprClass:3562 case ZigClangStmt_CXXDefaultArgExprClass:
3400 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultInitExprClass");3563 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDefaultArgExprClass");
3401 return ErrorUnexpected;3564 return ErrorUnexpected;
3402 case clang::Stmt::CXXDeleteExprClass:3565 case ZigClangStmt_CXXDefaultInitExprClass:
3403 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDeleteExprClass");3566 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDefaultInitExprClass");
3404 return ErrorUnexpected;3567 return ErrorUnexpected;
3405 case clang::Stmt::CXXDependentScopeMemberExprClass:3568 case ZigClangStmt_CXXDeleteExprClass:
3406 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDependentScopeMemberExprClass");3569 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDeleteExprClass");
3407 return ErrorUnexpected;3570 return ErrorUnexpected;
3408 case clang::Stmt::CXXFoldExprClass:3571 case ZigClangStmt_CXXDependentScopeMemberExprClass:
3409 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFoldExprClass");3572 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDependentScopeMemberExprClass");
3410 return ErrorUnexpected;3573 return ErrorUnexpected;
3411 case clang::Stmt::CXXInheritedCtorInitExprClass:3574 case ZigClangStmt_CXXFoldExprClass:
3412 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXInheritedCtorInitExprClass");3575 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXFoldExprClass");
3413 return ErrorUnexpected;3576 return ErrorUnexpected;
3414 case clang::Stmt::CXXNewExprClass:3577 case ZigClangStmt_CXXInheritedCtorInitExprClass:
3415 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNewExprClass");3578 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXInheritedCtorInitExprClass");
3416 return ErrorUnexpected;3579 return ErrorUnexpected;
3417 case clang::Stmt::CXXNoexceptExprClass:3580 case ZigClangStmt_CXXNewExprClass:
3418 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNoexceptExprClass");3581 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNewExprClass");
3419 return ErrorUnexpected;3582 return ErrorUnexpected;
3420 case clang::Stmt::CXXNullPtrLiteralExprClass:3583 case ZigClangStmt_CXXNoexceptExprClass:
3421 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNullPtrLiteralExprClass");3584 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNoexceptExprClass");
3422 return ErrorUnexpected;3585 return ErrorUnexpected;
3423 case clang::Stmt::CXXPseudoDestructorExprClass:3586 case ZigClangStmt_CXXNullPtrLiteralExprClass:
3424 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXPseudoDestructorExprClass");3587 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNullPtrLiteralExprClass");
3425 return ErrorUnexpected;3588 return ErrorUnexpected;
3426 case clang::Stmt::CXXScalarValueInitExprClass:3589 case ZigClangStmt_CXXPseudoDestructorExprClass:
3427 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXScalarValueInitExprClass");3590 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXPseudoDestructorExprClass");
3428 return ErrorUnexpected;3591 return ErrorUnexpected;
3429 case clang::Stmt::CXXStdInitializerListExprClass:3592 case ZigClangStmt_CXXScalarValueInitExprClass:
3430 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStdInitializerListExprClass");3593 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXScalarValueInitExprClass");
3431 return ErrorUnexpected;3594 return ErrorUnexpected;
3432 case clang::Stmt::CXXThisExprClass:3595 case ZigClangStmt_CXXStdInitializerListExprClass:
3433 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThisExprClass");3596 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXStdInitializerListExprClass");
3434 return ErrorUnexpected;3597 return ErrorUnexpected;
3435 case clang::Stmt::CXXThrowExprClass:3598 case ZigClangStmt_CXXThisExprClass:
3436 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThrowExprClass");3599 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXThisExprClass");
3437 return ErrorUnexpected;3600 return ErrorUnexpected;
3438 case clang::Stmt::CXXTypeidExprClass:3601 case ZigClangStmt_CXXThrowExprClass:
3439 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTypeidExprClass");3602 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXThrowExprClass");
3440 return ErrorUnexpected;3603 return ErrorUnexpected;
3441 case clang::Stmt::CXXUnresolvedConstructExprClass:3604 case ZigClangStmt_CXXTypeidExprClass:
3442 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUnresolvedConstructExprClass");3605 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTypeidExprClass");
3443 return ErrorUnexpected;3606 return ErrorUnexpected;
3444 case clang::Stmt::CXXUuidofExprClass:3607 case ZigClangStmt_CXXUnresolvedConstructExprClass:
3445 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUuidofExprClass");3608 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXUnresolvedConstructExprClass");
3446 return ErrorUnexpected;3609 return ErrorUnexpected;
3447 case clang::Stmt::CUDAKernelCallExprClass:3610 case ZigClangStmt_CXXUuidofExprClass:
3448 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CUDAKernelCallExprClass");3611 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXUuidofExprClass");
3449 return ErrorUnexpected;3612 return ErrorUnexpected;
3450 case clang::Stmt::CXXMemberCallExprClass:3613 case ZigClangStmt_CUDAKernelCallExprClass:
3451 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXMemberCallExprClass");3614 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CUDAKernelCallExprClass");
3452 return ErrorUnexpected;3615 return ErrorUnexpected;
3453 case clang::Stmt::CXXOperatorCallExprClass:3616 case ZigClangStmt_CXXMemberCallExprClass:
3454 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXOperatorCallExprClass");3617 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXMemberCallExprClass");
3455 return ErrorUnexpected;3618 return ErrorUnexpected;
3456 case clang::Stmt::UserDefinedLiteralClass:3619 case ZigClangStmt_CXXOperatorCallExprClass:
3457 emit_warning(c, stmt->getBeginLoc(), "TODO handle C UserDefinedLiteralClass");3620 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXOperatorCallExprClass");
3458 return ErrorUnexpected;3621 return ErrorUnexpected;
3459 case clang::Stmt::CXXFunctionalCastExprClass:3622 case ZigClangStmt_UserDefinedLiteralClass:
3460 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFunctionalCastExprClass");3623 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UserDefinedLiteralClass");
3461 return ErrorUnexpected;3624 return ErrorUnexpected;
3462 case clang::Stmt::CXXConstCastExprClass:3625 case ZigClangStmt_CXXFunctionalCastExprClass:
3463 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstCastExprClass");3626 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXFunctionalCastExprClass");
3464 return ErrorUnexpected;3627 return ErrorUnexpected;
3465 case clang::Stmt::CXXDynamicCastExprClass:3628 case ZigClangStmt_CXXConstCastExprClass:
3466 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDynamicCastExprClass");3629 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXConstCastExprClass");
3467 return ErrorUnexpected;3630 return ErrorUnexpected;
3468 case clang::Stmt::CXXReinterpretCastExprClass:3631 case ZigClangStmt_CXXDynamicCastExprClass:
3469 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXReinterpretCastExprClass");3632 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDynamicCastExprClass");
3470 return ErrorUnexpected;3633 return ErrorUnexpected;
3471 case clang::Stmt::CXXStaticCastExprClass:3634 case ZigClangStmt_CXXReinterpretCastExprClass:
3472 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStaticCastExprClass");3635 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXReinterpretCastExprClass");
3473 return ErrorUnexpected;3636 return ErrorUnexpected;
3474 case clang::Stmt::ObjCBridgedCastExprClass:3637 case ZigClangStmt_CXXStaticCastExprClass:
3475 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBridgedCastExprClass");3638 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXStaticCastExprClass");
3476 return ErrorUnexpected;3639 return ErrorUnexpected;
3477 case clang::Stmt::CharacterLiteralClass:3640 case ZigClangStmt_ObjCBridgedCastExprClass:
3478 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CharacterLiteralClass");3641 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass");
3479 return ErrorUnexpected;3642 return ErrorUnexpected;
3480 case clang::Stmt::ChooseExprClass:3643 case ZigClangStmt_CharacterLiteralClass:
3481 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ChooseExprClass");3644 return wrap_stmt(out_node, out_child_scope, scope,
3645 trans_character_literal(c, result_used, (const clang::CharacterLiteral *)stmt));
3482 return ErrorUnexpected;3646 return ErrorUnexpected;
3483 case clang::Stmt::CompoundLiteralExprClass:3647 case ZigClangStmt_ChooseExprClass:
3484 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CompoundLiteralExprClass");3648 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ChooseExprClass");
3485 return ErrorUnexpected;3649 return ErrorUnexpected;
3486 case clang::Stmt::ConvertVectorExprClass:3650 case ZigClangStmt_CompoundLiteralExprClass:
3487 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ConvertVectorExprClass");3651 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CompoundLiteralExprClass");
3488 return ErrorUnexpected;3652 return ErrorUnexpected;
3489 case clang::Stmt::CoawaitExprClass:3653 case ZigClangStmt_ConvertVectorExprClass:
3490 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoawaitExprClass");3654 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ConvertVectorExprClass");
3491 return ErrorUnexpected;3655 return ErrorUnexpected;
3492 case clang::Stmt::CoyieldExprClass:3656 case ZigClangStmt_CoawaitExprClass:
3493 emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoyieldExprClass");3657 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoawaitExprClass");
3494 return ErrorUnexpected;3658 return ErrorUnexpected;
3495 case clang::Stmt::DependentCoawaitExprClass:3659 case ZigClangStmt_CoyieldExprClass:
3496 emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentCoawaitExprClass");3660 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoyieldExprClass");
3497 return ErrorUnexpected;3661 return ErrorUnexpected;
3498 case clang::Stmt::DependentScopeDeclRefExprClass:3662 case ZigClangStmt_DependentCoawaitExprClass:
3499 emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentScopeDeclRefExprClass");3663 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DependentCoawaitExprClass");
3500 return ErrorUnexpected;3664 return ErrorUnexpected;
3501 case clang::Stmt::DesignatedInitExprClass:3665 case ZigClangStmt_DependentScopeDeclRefExprClass:
3502 emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitExprClass");3666 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DependentScopeDeclRefExprClass");
3503 return ErrorUnexpected;3667 return ErrorUnexpected;
3504 case clang::Stmt::DesignatedInitUpdateExprClass:3668 case ZigClangStmt_DesignatedInitExprClass:
3505 emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitUpdateExprClass");3669 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DesignatedInitExprClass");
3506 return ErrorUnexpected;3670 return ErrorUnexpected;
3507 case clang::Stmt::ExpressionTraitExprClass:3671 case ZigClangStmt_DesignatedInitUpdateExprClass:
3508 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExpressionTraitExprClass");3672 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DesignatedInitUpdateExprClass");
3509 return ErrorUnexpected;3673 return ErrorUnexpected;
3510 case clang::Stmt::ExtVectorElementExprClass:3674 case ZigClangStmt_ExpressionTraitExprClass:
3511 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExtVectorElementExprClass");3675 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExpressionTraitExprClass");
3512 return ErrorUnexpected;3676 return ErrorUnexpected;
3513 case clang::Stmt::FixedPointLiteralClass:3677 case ZigClangStmt_ExtVectorElementExprClass:
3514 emit_warning(c, stmt->getBeginLoc(), "TODO handle C FixedPointLiteralClass");3678 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExtVectorElementExprClass");
3515 return ErrorUnexpected;3679 return ErrorUnexpected;
3516 case clang::Stmt::FloatingLiteralClass:3680 case ZigClangStmt_FixedPointLiteralClass:
3517 emit_warning(c, stmt->getBeginLoc(), "TODO handle C FloatingLiteralClass");3681 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass");
3518 return ErrorUnexpected;3682 return ErrorUnexpected;
3519 case clang::Stmt::ExprWithCleanupsClass:3683 case ZigClangStmt_FloatingLiteralClass:
3520 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExprWithCleanupsClass");3684 return wrap_stmt(out_node, out_child_scope, scope,
3685 trans_floating_literal(c, result_used, (const clang::FloatingLiteral *)stmt));
3686 case ZigClangStmt_ExprWithCleanupsClass:
3687 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExprWithCleanupsClass");
3521 return ErrorUnexpected;3688 return ErrorUnexpected;
3522 case clang::Stmt::FunctionParmPackExprClass:3689 case ZigClangStmt_FunctionParmPackExprClass:
3523 emit_warning(c, stmt->getBeginLoc(), "TODO handle C FunctionParmPackExprClass");3690 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FunctionParmPackExprClass");
3524 return ErrorUnexpected;3691 return ErrorUnexpected;
3525 case clang::Stmt::GNUNullExprClass:3692 case ZigClangStmt_GNUNullExprClass:
3526 emit_warning(c, stmt->getBeginLoc(), "TODO handle C GNUNullExprClass");3693 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GNUNullExprClass");
3527 return ErrorUnexpected;3694 return ErrorUnexpected;
3528 case clang::Stmt::GenericSelectionExprClass:3695 case ZigClangStmt_GenericSelectionExprClass:
3529 emit_warning(c, stmt->getBeginLoc(), "TODO handle C GenericSelectionExprClass");3696 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GenericSelectionExprClass");
3530 return ErrorUnexpected;3697 return ErrorUnexpected;
3531 case clang::Stmt::ImaginaryLiteralClass:3698 case ZigClangStmt_ImaginaryLiteralClass:
3532 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImaginaryLiteralClass");3699 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ImaginaryLiteralClass");
3533 return ErrorUnexpected;3700 return ErrorUnexpected;
3534 case clang::Stmt::ImplicitValueInitExprClass:3701 case ZigClangStmt_ImplicitValueInitExprClass:
3535 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImplicitValueInitExprClass");3702 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ImplicitValueInitExprClass");
3536 return ErrorUnexpected;3703 return ErrorUnexpected;
3537 case clang::Stmt::InitListExprClass:3704 case ZigClangStmt_InitListExprClass:
3538 emit_warning(c, stmt->getBeginLoc(), "TODO handle C InitListExprClass");3705 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C InitListExprClass");
3539 return ErrorUnexpected;3706 return ErrorUnexpected;
3540 case clang::Stmt::LambdaExprClass:3707 case ZigClangStmt_LambdaExprClass:
3541 emit_warning(c, stmt->getBeginLoc(), "TODO handle C LambdaExprClass");3708 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C LambdaExprClass");
3542 return ErrorUnexpected;3709 return ErrorUnexpected;
3543 case clang::Stmt::MSPropertyRefExprClass:3710 case ZigClangStmt_MSPropertyRefExprClass:
3544 emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertyRefExprClass");3711 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSPropertyRefExprClass");
3545 return ErrorUnexpected;3712 return ErrorUnexpected;
3546 case clang::Stmt::MSPropertySubscriptExprClass:3713 case ZigClangStmt_MSPropertySubscriptExprClass:
3547 emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertySubscriptExprClass");3714 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSPropertySubscriptExprClass");
3548 return ErrorUnexpected;3715 return ErrorUnexpected;
3549 case clang::Stmt::MaterializeTemporaryExprClass:3716 case ZigClangStmt_MaterializeTemporaryExprClass:
3550 emit_warning(c, stmt->getBeginLoc(), "TODO handle C MaterializeTemporaryExprClass");3717 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MaterializeTemporaryExprClass");
3551 return ErrorUnexpected;3718 return ErrorUnexpected;
3552 case clang::Stmt::NoInitExprClass:3719 case ZigClangStmt_NoInitExprClass:
3553 emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoInitExprClass");3720 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C NoInitExprClass");
3554 return ErrorUnexpected;3721 return ErrorUnexpected;
3555 case clang::Stmt::OMPArraySectionExprClass:3722 case ZigClangStmt_OMPArraySectionExprClass:
3556 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPArraySectionExprClass");3723 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPArraySectionExprClass");
3557 return ErrorUnexpected;3724 return ErrorUnexpected;
3558 case clang::Stmt::ObjCArrayLiteralClass:3725 case ZigClangStmt_ObjCArrayLiteralClass:
3559 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCArrayLiteralClass");3726 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCArrayLiteralClass");
3560 return ErrorUnexpected;3727 return ErrorUnexpected;
3561 case clang::Stmt::ObjCAvailabilityCheckExprClass:3728 case ZigClangStmt_ObjCAvailabilityCheckExprClass:
3562 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAvailabilityCheckExprClass");3729 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAvailabilityCheckExprClass");
3563 return ErrorUnexpected;3730 return ErrorUnexpected;
3564 case clang::Stmt::ObjCBoolLiteralExprClass:3731 case ZigClangStmt_ObjCBoolLiteralExprClass:
3565 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoolLiteralExprClass");3732 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBoolLiteralExprClass");
3566 return ErrorUnexpected;3733 return ErrorUnexpected;
3567 case clang::Stmt::ObjCBoxedExprClass:3734 case ZigClangStmt_ObjCBoxedExprClass:
3568 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoxedExprClass");3735 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBoxedExprClass");
3569 return ErrorUnexpected;3736 return ErrorUnexpected;
3570 case clang::Stmt::ObjCDictionaryLiteralClass:3737 case ZigClangStmt_ObjCDictionaryLiteralClass:
3571 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCDictionaryLiteralClass");3738 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCDictionaryLiteralClass");
3572 return ErrorUnexpected;3739 return ErrorUnexpected;
3573 case clang::Stmt::ObjCEncodeExprClass:3740 case ZigClangStmt_ObjCEncodeExprClass:
3574 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCEncodeExprClass");3741 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCEncodeExprClass");
3575 return ErrorUnexpected;3742 return ErrorUnexpected;
3576 case clang::Stmt::ObjCIndirectCopyRestoreExprClass:3743 case ZigClangStmt_ObjCIndirectCopyRestoreExprClass:
3577 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIndirectCopyRestoreExprClass");3744 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIndirectCopyRestoreExprClass");
3578 return ErrorUnexpected;3745 return ErrorUnexpected;
3579 case clang::Stmt::ObjCIsaExprClass:3746 case ZigClangStmt_ObjCIsaExprClass:
3580 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIsaExprClass");3747 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIsaExprClass");
3581 return ErrorUnexpected;3748 return ErrorUnexpected;
3582 case clang::Stmt::ObjCIvarRefExprClass:3749 case ZigClangStmt_ObjCIvarRefExprClass:
3583 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIvarRefExprClass");3750 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIvarRefExprClass");
3584 return ErrorUnexpected;3751 return ErrorUnexpected;
3585 case clang::Stmt::ObjCMessageExprClass:3752 case ZigClangStmt_ObjCMessageExprClass:
3586 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCMessageExprClass");3753 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCMessageExprClass");
3587 return ErrorUnexpected;3754 return ErrorUnexpected;
3588 case clang::Stmt::ObjCPropertyRefExprClass:3755 case ZigClangStmt_ObjCPropertyRefExprClass:
3589 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCPropertyRefExprClass");3756 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCPropertyRefExprClass");
3590 return ErrorUnexpected;3757 return ErrorUnexpected;
3591 case clang::Stmt::ObjCProtocolExprClass:3758 case ZigClangStmt_ObjCProtocolExprClass:
3592 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProtocolExprClass");3759 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCProtocolExprClass");
3593 return ErrorUnexpected;3760 return ErrorUnexpected;
3594 case clang::Stmt::ObjCSelectorExprClass:3761 case ZigClangStmt_ObjCSelectorExprClass:
3595 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSelectorExprClass");3762 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCSelectorExprClass");
3596 return ErrorUnexpected;3763 return ErrorUnexpected;
3597 case clang::Stmt::ObjCStringLiteralClass:3764 case ZigClangStmt_ObjCStringLiteralClass:
3598 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCStringLiteralClass");3765 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCStringLiteralClass");
3599 return ErrorUnexpected;3766 return ErrorUnexpected;
3600 case clang::Stmt::ObjCSubscriptRefExprClass:3767 case ZigClangStmt_ObjCSubscriptRefExprClass:
3601 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSubscriptRefExprClass");3768 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCSubscriptRefExprClass");
3602 return ErrorUnexpected;3769 return ErrorUnexpected;
3603 case clang::Stmt::OffsetOfExprClass:3770 case ZigClangStmt_OffsetOfExprClass:
3604 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OffsetOfExprClass");3771 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OffsetOfExprClass");
3605 return ErrorUnexpected;3772 return ErrorUnexpected;
3606 case clang::Stmt::OpaqueValueExprClass:3773 case ZigClangStmt_OpaqueValueExprClass:
3607 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OpaqueValueExprClass");3774 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OpaqueValueExprClass");
3608 return ErrorUnexpected;3775 return ErrorUnexpected;
3609 case clang::Stmt::UnresolvedLookupExprClass:3776 case ZigClangStmt_UnresolvedLookupExprClass:
3610 emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedLookupExprClass");3777 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UnresolvedLookupExprClass");
3611 return ErrorUnexpected;3778 return ErrorUnexpected;
3612 case clang::Stmt::UnresolvedMemberExprClass:3779 case ZigClangStmt_UnresolvedMemberExprClass:
3613 emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedMemberExprClass");3780 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UnresolvedMemberExprClass");
3614 return ErrorUnexpected;3781 return ErrorUnexpected;
3615 case clang::Stmt::PackExpansionExprClass:3782 case ZigClangStmt_PackExpansionExprClass:
3616 emit_warning(c, stmt->getBeginLoc(), "TODO handle C PackExpansionExprClass");3783 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C PackExpansionExprClass");
3617 return ErrorUnexpected;3784 return ErrorUnexpected;
3618 case clang::Stmt::ParenListExprClass:3785 case ZigClangStmt_ParenListExprClass:
3619 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ParenListExprClass");3786 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ParenListExprClass");
3620 return ErrorUnexpected;3787 return ErrorUnexpected;
3621 case clang::Stmt::PseudoObjectExprClass:3788 case ZigClangStmt_PseudoObjectExprClass:
3622 emit_warning(c, stmt->getBeginLoc(), "TODO handle C PseudoObjectExprClass");3789 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C PseudoObjectExprClass");
3623 return ErrorUnexpected;3790 return ErrorUnexpected;
3624 case clang::Stmt::ShuffleVectorExprClass:3791 case ZigClangStmt_ShuffleVectorExprClass:
3625 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ShuffleVectorExprClass");3792 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ShuffleVectorExprClass");
3626 return ErrorUnexpected;3793 return ErrorUnexpected;
3627 case clang::Stmt::SizeOfPackExprClass:3794 case ZigClangStmt_SizeOfPackExprClass:
3628 emit_warning(c, stmt->getBeginLoc(), "TODO handle C SizeOfPackExprClass");3795 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SizeOfPackExprClass");
3629 return ErrorUnexpected;3796 return ErrorUnexpected;
3630 case clang::Stmt::SubstNonTypeTemplateParmExprClass:3797 case ZigClangStmt_SubstNonTypeTemplateParmExprClass:
3631 emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmExprClass");3798 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SubstNonTypeTemplateParmExprClass");
3632 return ErrorUnexpected;3799 return ErrorUnexpected;
3633 case clang::Stmt::SubstNonTypeTemplateParmPackExprClass:3800 case ZigClangStmt_SubstNonTypeTemplateParmPackExprClass:
3634 emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmPackExprClass");3801 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
3635 return ErrorUnexpected;3802 return ErrorUnexpected;
3636 case clang::Stmt::TypeTraitExprClass:3803 case ZigClangStmt_TypeTraitExprClass:
3637 emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeTraitExprClass");3804 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C TypeTraitExprClass");
3638 return ErrorUnexpected;3805 return ErrorUnexpected;
3639 case clang::Stmt::TypoExprClass:3806 case ZigClangStmt_TypoExprClass:
3640 emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypoExprClass");3807 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C TypoExprClass");
3641 return ErrorUnexpected;3808 return ErrorUnexpected;
3642 case clang::Stmt::VAArgExprClass:3809 case ZigClangStmt_VAArgExprClass:
3643 emit_warning(c, stmt->getBeginLoc(), "TODO handle C VAArgExprClass");3810 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C VAArgExprClass");
3644 return ErrorUnexpected;3811 return ErrorUnexpected;
3645 case clang::Stmt::GotoStmtClass:3812 case ZigClangStmt_GotoStmtClass:
3646 emit_warning(c, stmt->getBeginLoc(), "TODO handle C GotoStmtClass");3813 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GotoStmtClass");
3647 return ErrorUnexpected;3814 return ErrorUnexpected;
3648 case clang::Stmt::IndirectGotoStmtClass:3815 case ZigClangStmt_IndirectGotoStmtClass:
3649 emit_warning(c, stmt->getBeginLoc(), "TODO handle C IndirectGotoStmtClass");3816 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C IndirectGotoStmtClass");
3650 return ErrorUnexpected;3817 return ErrorUnexpected;
3651 case clang::Stmt::LabelStmtClass:3818 case ZigClangStmt_LabelStmtClass:
3652 emit_warning(c, stmt->getBeginLoc(), "TODO handle C LabelStmtClass");3819 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C LabelStmtClass");
3653 return ErrorUnexpected;3820 return ErrorUnexpected;
3654 case clang::Stmt::MSDependentExistsStmtClass:3821 case ZigClangStmt_MSDependentExistsStmtClass:
3655 emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSDependentExistsStmtClass");3822 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSDependentExistsStmtClass");
3656 return ErrorUnexpected;3823 return ErrorUnexpected;
3657 case clang::Stmt::OMPAtomicDirectiveClass:3824 case ZigClangStmt_OMPAtomicDirectiveClass:
3658 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPAtomicDirectiveClass");3825 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPAtomicDirectiveClass");
3659 return ErrorUnexpected;3826 return ErrorUnexpected;
3660 case clang::Stmt::OMPBarrierDirectiveClass:3827 case ZigClangStmt_OMPBarrierDirectiveClass:
3661 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPBarrierDirectiveClass");3828 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPBarrierDirectiveClass");
3662 return ErrorUnexpected;3829 return ErrorUnexpected;
3663 case clang::Stmt::OMPCancelDirectiveClass:3830 case ZigClangStmt_OMPCancelDirectiveClass:
3664 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancelDirectiveClass");3831 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCancelDirectiveClass");
3665 return ErrorUnexpected;3832 return ErrorUnexpected;
3666 case clang::Stmt::OMPCancellationPointDirectiveClass:3833 case ZigClangStmt_OMPCancellationPointDirectiveClass:
3667 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancellationPointDirectiveClass");3834 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCancellationPointDirectiveClass");
3668 return ErrorUnexpected;3835 return ErrorUnexpected;
3669 case clang::Stmt::OMPCriticalDirectiveClass:3836 case ZigClangStmt_OMPCriticalDirectiveClass:
3670 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCriticalDirectiveClass");3837 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCriticalDirectiveClass");
3671 return ErrorUnexpected;3838 return ErrorUnexpected;
3672 case clang::Stmt::OMPFlushDirectiveClass:3839 case ZigClangStmt_OMPFlushDirectiveClass:
3673 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPFlushDirectiveClass");3840 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPFlushDirectiveClass");
3674 return ErrorUnexpected;3841 return ErrorUnexpected;
3675 case clang::Stmt::OMPDistributeDirectiveClass:3842 case ZigClangStmt_OMPDistributeDirectiveClass:
3676 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeDirectiveClass");3843 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeDirectiveClass");
3677 return ErrorUnexpected;3844 return ErrorUnexpected;
3678 case clang::Stmt::OMPDistributeParallelForDirectiveClass:3845 case ZigClangStmt_OMPDistributeParallelForDirectiveClass:
3679 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForDirectiveClass");3846 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeParallelForDirectiveClass");
3680 return ErrorUnexpected;3847 return ErrorUnexpected;
3681 case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass:3848 case ZigClangStmt_OMPDistributeParallelForSimdDirectiveClass:
3682 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");3849 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
3683 return ErrorUnexpected;3850 return ErrorUnexpected;
3684 case clang::Stmt::OMPDistributeSimdDirectiveClass:3851 case ZigClangStmt_OMPDistributeSimdDirectiveClass:
3685 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeSimdDirectiveClass");3852 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeSimdDirectiveClass");
3686 return ErrorUnexpected;3853 return ErrorUnexpected;
3687 case clang::Stmt::OMPForDirectiveClass:3854 case ZigClangStmt_OMPForDirectiveClass:
3688 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForDirectiveClass");3855 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPForDirectiveClass");
3689 return ErrorUnexpected;3856 return ErrorUnexpected;
3690 case clang::Stmt::OMPForSimdDirectiveClass:3857 case ZigClangStmt_OMPForSimdDirectiveClass:
3691 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForSimdDirectiveClass");3858 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPForSimdDirectiveClass");
3692 return ErrorUnexpected;3859 return ErrorUnexpected;
3693 case clang::Stmt::OMPParallelForDirectiveClass:3860 case ZigClangStmt_OMPParallelForDirectiveClass:
3694 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForDirectiveClass");3861 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelForDirectiveClass");
3695 return ErrorUnexpected;3862 return ErrorUnexpected;
3696 case clang::Stmt::OMPParallelForSimdDirectiveClass:3863 case ZigClangStmt_OMPParallelForSimdDirectiveClass:
3697 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForSimdDirectiveClass");3864 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelForSimdDirectiveClass");
3698 return ErrorUnexpected;3865 return ErrorUnexpected;
3699 case clang::Stmt::OMPSimdDirectiveClass:3866 case ZigClangStmt_OMPSimdDirectiveClass:
3700 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSimdDirectiveClass");3867 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSimdDirectiveClass");
3701 return ErrorUnexpected;3868 return ErrorUnexpected;
3702 case clang::Stmt::OMPTargetParallelForSimdDirectiveClass:3869 case ZigClangStmt_OMPTargetParallelForSimdDirectiveClass:
3703 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForSimdDirectiveClass");3870 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
3704 return ErrorUnexpected;3871 return ErrorUnexpected;
3705 case clang::Stmt::OMPTargetSimdDirectiveClass:3872 case ZigClangStmt_OMPTargetSimdDirectiveClass:
3706 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetSimdDirectiveClass");3873 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetSimdDirectiveClass");
3707 return ErrorUnexpected;3874 return ErrorUnexpected;
3708 case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass:3875 case ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass:
3709 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");3876 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
3710 return ErrorUnexpected;3877 return ErrorUnexpected;
3711 case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:3878 case ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass:
3712 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");3879 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
3713 return ErrorUnexpected;3880 return ErrorUnexpected;
3714 case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:3881 case ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
3715 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");3882 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
3716 return ErrorUnexpected;3883 return ErrorUnexpected;
3717 case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:3884 case ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass:
3718 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");3885 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
3719 return ErrorUnexpected;3886 return ErrorUnexpected;
3720 case clang::Stmt::OMPTaskLoopDirectiveClass:3887 case ZigClangStmt_OMPTaskLoopDirectiveClass:
3721 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopDirectiveClass");3888 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskLoopDirectiveClass");
3722 return ErrorUnexpected;3889 return ErrorUnexpected;
3723 case clang::Stmt::OMPTaskLoopSimdDirectiveClass:3890 case ZigClangStmt_OMPTaskLoopSimdDirectiveClass:
3724 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopSimdDirectiveClass");3891 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskLoopSimdDirectiveClass");
3725 return ErrorUnexpected;3892 return ErrorUnexpected;
3726 case clang::Stmt::OMPTeamsDistributeDirectiveClass:3893 case ZigClangStmt_OMPTeamsDistributeDirectiveClass:
3727 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeDirectiveClass");3894 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeDirectiveClass");
3728 return ErrorUnexpected;3895 return ErrorUnexpected;
3729 case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass:3896 case ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass:
3730 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");3897 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
3731 return ErrorUnexpected;3898 return ErrorUnexpected;
3732 case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:3899 case ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass:
3733 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");3900 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
3734 return ErrorUnexpected;3901 return ErrorUnexpected;
3735 case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass:3902 case ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass:
3736 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");3903 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
3737 return ErrorUnexpected;3904 return ErrorUnexpected;
3738 case clang::Stmt::OMPMasterDirectiveClass:3905 case ZigClangStmt_OMPMasterDirectiveClass:
3739 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPMasterDirectiveClass");3906 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPMasterDirectiveClass");
3740 return ErrorUnexpected;3907 return ErrorUnexpected;
3741 case clang::Stmt::OMPOrderedDirectiveClass:3908 case ZigClangStmt_OMPOrderedDirectiveClass:
3742 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPOrderedDirectiveClass");3909 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPOrderedDirectiveClass");
3743 return ErrorUnexpected;3910 return ErrorUnexpected;
3744 case clang::Stmt::OMPParallelDirectiveClass:3911 case ZigClangStmt_OMPParallelDirectiveClass:
3745 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelDirectiveClass");3912 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelDirectiveClass");
3746 return ErrorUnexpected;3913 return ErrorUnexpected;
3747 case clang::Stmt::OMPParallelSectionsDirectiveClass:3914 case ZigClangStmt_OMPParallelSectionsDirectiveClass:
3748 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelSectionsDirectiveClass");3915 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelSectionsDirectiveClass");
3749 return ErrorUnexpected;3916 return ErrorUnexpected;
3750 case clang::Stmt::OMPSectionDirectiveClass:3917 case ZigClangStmt_OMPSectionDirectiveClass:
3751 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionDirectiveClass");3918 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSectionDirectiveClass");
3752 return ErrorUnexpected;3919 return ErrorUnexpected;
3753 case clang::Stmt::OMPSectionsDirectiveClass:3920 case ZigClangStmt_OMPSectionsDirectiveClass:
3754 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionsDirectiveClass");3921 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSectionsDirectiveClass");
3755 return ErrorUnexpected;3922 return ErrorUnexpected;
3756 case clang::Stmt::OMPSingleDirectiveClass:3923 case ZigClangStmt_OMPSingleDirectiveClass:
3757 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSingleDirectiveClass");3924 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSingleDirectiveClass");
3758 return ErrorUnexpected;3925 return ErrorUnexpected;
3759 case clang::Stmt::OMPTargetDataDirectiveClass:3926 case ZigClangStmt_OMPTargetDataDirectiveClass:
3760 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDataDirectiveClass");3927 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetDataDirectiveClass");
3761 return ErrorUnexpected;3928 return ErrorUnexpected;
3762 case clang::Stmt::OMPTargetDirectiveClass:3929 case ZigClangStmt_OMPTargetDirectiveClass:
3763 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDirectiveClass");3930 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetDirectiveClass");
3764 return ErrorUnexpected;3931 return ErrorUnexpected;
3765 case clang::Stmt::OMPTargetEnterDataDirectiveClass:3932 case ZigClangStmt_OMPTargetEnterDataDirectiveClass:
3766 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetEnterDataDirectiveClass");3933 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetEnterDataDirectiveClass");
3767 return ErrorUnexpected;3934 return ErrorUnexpected;
3768 case clang::Stmt::OMPTargetExitDataDirectiveClass:3935 case ZigClangStmt_OMPTargetExitDataDirectiveClass:
3769 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetExitDataDirectiveClass");3936 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetExitDataDirectiveClass");
3770 return ErrorUnexpected;3937 return ErrorUnexpected;
3771 case clang::Stmt::OMPTargetParallelDirectiveClass:3938 case ZigClangStmt_OMPTargetParallelDirectiveClass:
3772 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelDirectiveClass");3939 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelDirectiveClass");
3773 return ErrorUnexpected;3940 return ErrorUnexpected;
3774 case clang::Stmt::OMPTargetParallelForDirectiveClass:3941 case ZigClangStmt_OMPTargetParallelForDirectiveClass:
3775 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForDirectiveClass");3942 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelForDirectiveClass");
3776 return ErrorUnexpected;3943 return ErrorUnexpected;
3777 case clang::Stmt::OMPTargetTeamsDirectiveClass:3944 case ZigClangStmt_OMPTargetTeamsDirectiveClass:
3778 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDirectiveClass");3945 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDirectiveClass");
3779 return ErrorUnexpected;3946 return ErrorUnexpected;
3780 case clang::Stmt::OMPTargetUpdateDirectiveClass:3947 case ZigClangStmt_OMPTargetUpdateDirectiveClass:
3781 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetUpdateDirectiveClass");3948 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetUpdateDirectiveClass");
3782 return ErrorUnexpected;3949 return ErrorUnexpected;
3783 case clang::Stmt::OMPTaskDirectiveClass:3950 case ZigClangStmt_OMPTaskDirectiveClass:
3784 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskDirectiveClass");3951 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskDirectiveClass");
3785 return ErrorUnexpected;3952 return ErrorUnexpected;
3786 case clang::Stmt::OMPTaskgroupDirectiveClass:3953 case ZigClangStmt_OMPTaskgroupDirectiveClass:
3787 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskgroupDirectiveClass");3954 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskgroupDirectiveClass");
3788 return ErrorUnexpected;3955 return ErrorUnexpected;
3789 case clang::Stmt::OMPTaskwaitDirectiveClass:3956 case ZigClangStmt_OMPTaskwaitDirectiveClass:
3790 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskwaitDirectiveClass");3957 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskwaitDirectiveClass");
3791 return ErrorUnexpected;3958 return ErrorUnexpected;
3792 case clang::Stmt::OMPTaskyieldDirectiveClass:3959 case ZigClangStmt_OMPTaskyieldDirectiveClass:
3793 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskyieldDirectiveClass");3960 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskyieldDirectiveClass");
3794 return ErrorUnexpected;3961 return ErrorUnexpected;
3795 case clang::Stmt::OMPTeamsDirectiveClass:3962 case ZigClangStmt_OMPTeamsDirectiveClass:
3796 emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDirectiveClass");3963 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDirectiveClass");
3797 return ErrorUnexpected;3964 return ErrorUnexpected;
3798 case clang::Stmt::ObjCAtCatchStmtClass:3965 case ZigClangStmt_ObjCAtCatchStmtClass:
3799 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtCatchStmtClass");3966 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtCatchStmtClass");
3800 return ErrorUnexpected;3967 return ErrorUnexpected;
3801 case clang::Stmt::ObjCAtFinallyStmtClass:3968 case ZigClangStmt_ObjCAtFinallyStmtClass:
3802 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtFinallyStmtClass");3969 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtFinallyStmtClass");
3803 return ErrorUnexpected;3970 return ErrorUnexpected;
3804 case clang::Stmt::ObjCAtSynchronizedStmtClass:3971 case ZigClangStmt_ObjCAtSynchronizedStmtClass:
3805 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtSynchronizedStmtClass");3972 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtSynchronizedStmtClass");
3806 return ErrorUnexpected;3973 return ErrorUnexpected;
3807 case clang::Stmt::ObjCAtThrowStmtClass:3974 case ZigClangStmt_ObjCAtThrowStmtClass:
3808 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtThrowStmtClass");3975 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtThrowStmtClass");
3809 return ErrorUnexpected;3976 return ErrorUnexpected;
3810 case clang::Stmt::ObjCAtTryStmtClass:3977 case ZigClangStmt_ObjCAtTryStmtClass:
3811 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtTryStmtClass");3978 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtTryStmtClass");
3812 return ErrorUnexpected;3979 return ErrorUnexpected;
3813 case clang::Stmt::ObjCAutoreleasePoolStmtClass:3980 case ZigClangStmt_ObjCAutoreleasePoolStmtClass:
3814 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAutoreleasePoolStmtClass");3981 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAutoreleasePoolStmtClass");
3815 return ErrorUnexpected;3982 return ErrorUnexpected;
3816 case clang::Stmt::ObjCForCollectionStmtClass:3983 case ZigClangStmt_ObjCForCollectionStmtClass:
3817 emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCForCollectionStmtClass");3984 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCForCollectionStmtClass");
3818 return ErrorUnexpected;3985 return ErrorUnexpected;
3819 case clang::Stmt::SEHExceptStmtClass:3986 case ZigClangStmt_SEHExceptStmtClass:
3820 emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHExceptStmtClass");3987 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHExceptStmtClass");
3821 return ErrorUnexpected;3988 return ErrorUnexpected;
3822 case clang::Stmt::SEHFinallyStmtClass:3989 case ZigClangStmt_SEHFinallyStmtClass:
3823 emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHFinallyStmtClass");3990 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHFinallyStmtClass");
3824 return ErrorUnexpected;3991 return ErrorUnexpected;
3825 case clang::Stmt::SEHLeaveStmtClass:3992 case ZigClangStmt_SEHLeaveStmtClass:
3826 emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHLeaveStmtClass");3993 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHLeaveStmtClass");
3827 return ErrorUnexpected;3994 return ErrorUnexpected;
3828 case clang::Stmt::SEHTryStmtClass:3995 case ZigClangStmt_SEHTryStmtClass:
3829 emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHTryStmtClass");3996 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHTryStmtClass");
3830 return ErrorUnexpected;3997 return ErrorUnexpected;
3831 }3998 }
3832 zig_unreachable();3999 zig_unreachable();
3833}4000}
38344001
3835// Returns null if there was an error4002// Returns null if there was an error
3836static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr,4003static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr,
3837 TransLRValue lrval)4004 TransLRValue lrval)
3838{4005{
3839 AstNode *result_node;4006 AstNode *result_node;
3840 TransScope *result_scope;4007 TransScope *result_scope;
3841 if (trans_stmt_extra(c, scope, expr, result_used, lrval, &result_node, &result_scope, nullptr)) {4008 if (trans_stmt_extra(c, scope, (const ZigClangStmt *)expr, result_used, lrval, &result_node, &result_scope, nullptr)) {
3842 return nullptr;4009 return nullptr;
3843 }4010 }
3844 return result_node;4011 return result_node;
...@@ -3846,7 +4013,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope...@@ -3846,7 +4013,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope
38464013
3847// Statements have no result and no concept of L or R value.4014// Statements have no result and no concept of L or R value.
3848// Returns child scope, or null if there was an error4015// Returns child scope, or null if there was an error
3849static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node) {4016static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt *stmt, AstNode **out_node) {
3850 TransScope *child_scope;4017 TransScope *child_scope;
3851 if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {4018 if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {
3852 return nullptr;4019 return nullptr;
...@@ -3854,34 +4021,36 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *...@@ -3854,34 +4021,36 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *
3854 return child_scope;4021 return child_scope;
3855}4022}
38564023
3857static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {4024static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
3858 Buf *fn_name = buf_create_from_str(decl_name(fn_decl));4025 Buf *fn_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)fn_decl));
38594026
3860 if (get_global(c, fn_name)) {4027 if (get_global(c, fn_name)) {
3861 // we already saw this function4028 // we already saw this function
3862 return;4029 return;
3863 }4030 }
38644031
3865 AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), fn_decl->getLocation());4032 AstNode *proto_node = trans_qual_type(c, ZigClangFunctionDecl_getType(fn_decl),
4033 ZigClangFunctionDecl_getLocation(fn_decl));
3866 if (proto_node == nullptr) {4034 if (proto_node == nullptr) {
3867 emit_warning(c, fn_decl->getLocation(), "unable to resolve prototype of function '%s'", buf_ptr(fn_name));4035 emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl),
4036 "unable to resolve prototype of function '%s'", buf_ptr(fn_name));
3868 return;4037 return;
3869 }4038 }
38704039
3871 proto_node->data.fn_proto.name = fn_name;4040 proto_node->data.fn_proto.name = fn_name;
3872 proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();4041 proto_node->data.fn_proto.is_extern = !ZigClangFunctionDecl_hasBody(fn_decl);
38734042
3874 clang::StorageClass sc = fn_decl->getStorageClass();4043 ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl);
3875 if (sc == clang::SC_None) {4044 if (sc == ZigClangStorageClass_None) {
3876 proto_node->data.fn_proto.visib_mod = c->visib_mod;4045 proto_node->data.fn_proto.visib_mod = c->visib_mod;
3877 proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false;4046 proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false;
3878 } else if (sc == clang::SC_Extern || sc == clang::SC_Static) {4047 } else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) {
3879 proto_node->data.fn_proto.visib_mod = c->visib_mod;4048 proto_node->data.fn_proto.visib_mod = c->visib_mod;
3880 } else if (sc == clang::SC_PrivateExtern) {4049 } else if (sc == ZigClangStorageClass_PrivateExtern) {
3881 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");4050 emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern");
3882 return;4051 return;
3883 } else {4052 } else {
3884 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: unknown");4053 emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: unknown");
3885 return;4054 return;
3886 }4055 }
38874056
...@@ -3889,8 +4058,8 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {...@@ -3889,8 +4058,8 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
38894058
3890 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {4059 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
3891 AstNode *param_node = proto_node->data.fn_proto.params.at(i);4060 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
3892 const clang::ParmVarDecl *param = fn_decl->getParamDecl(i);4061 const ZigClangParmVarDecl *param = ZigClangFunctionDecl_getParamDecl(fn_decl, i);
3893 const char *name = decl_name(param);4062 const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)param);
38944063
3895 Buf *proto_param_name;4064 Buf *proto_param_name;
3896 if (strlen(name) != 0) {4065 if (strlen(name) != 0) {
...@@ -3908,7 +4077,7 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {...@@ -3908,7 +4077,7 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
3908 param_node->data.param_decl.name = scope_var->zig_name;4077 param_node->data.param_decl.name = scope_var->zig_name;
3909 }4078 }
39104079
3911 if (!fn_decl->hasBody()) {4080 if (!ZigClangFunctionDecl_hasBody(fn_decl)) {
3912 // just a prototype4081 // just a prototype
3913 add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node);4082 add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node);
3914 return;4083 return;
...@@ -3916,11 +4085,11 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {...@@ -3916,11 +4085,11 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
39164085
3917 // actual function definition with body4086 // actual function definition with body
3918 c->ptr_params.clear();4087 c->ptr_params.clear();
3919 clang::Stmt *body = fn_decl->getBody();4088 const ZigClangStmt *body = ZigClangFunctionDecl_getBody(fn_decl);
3920 AstNode *actual_body_node;4089 AstNode *actual_body_node;
3921 TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);4090 TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
3922 if (result_scope == nullptr) {4091 if (result_scope == nullptr) {
3923 emit_warning(c, fn_decl->getLocation(), "unable to translate function");4092 emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unable to translate function");
3924 return;4093 return;
3925 }4094 }
3926 assert(actual_body_node != nullptr);4095 assert(actual_body_node != nullptr);
...@@ -3958,20 +4127,20 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {...@@ -3958,20 +4127,20 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
3958 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);4127 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
3959}4128}
39604129
3961static AstNode *resolve_typdef_as_builtin(Context *c, const clang::TypedefNameDecl *typedef_decl, const char *primitive_name) {4130static AstNode *resolve_typdef_as_builtin(Context *c, const ZigClangTypedefNameDecl *typedef_decl, const char *primitive_name) {
3962 AstNode *node = trans_create_node_symbol_str(c, primitive_name);4131 AstNode *node = trans_create_node_symbol_str(c, primitive_name);
3963 c->decl_table.put(typedef_decl, node);4132 c->decl_table.put(typedef_decl, node);
3964 return node;4133 return node;
3965}4134}
39664135
3967static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) {4136static AstNode *resolve_typedef_decl(Context *c, const ZigClangTypedefNameDecl *typedef_decl) {
3968 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());4137 auto existing_entry = c->decl_table.maybe_get((void*)ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl));
3969 if (existing_entry) {4138 if (existing_entry) {
3970 return existing_entry->value;4139 return existing_entry->value;
3971 }4140 }
39724141
3973 clang::QualType child_qt = typedef_decl->getUnderlyingType();4142 ZigClangQualType child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
3974 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));4143 Buf *type_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl));
39754144
3976 if (buf_eql_str(type_name, "uint8_t")) {4145 if (buf_eql_str(type_name, "uint8_t")) {
3977 return resolve_typdef_as_builtin(c, typedef_decl, "u8");4146 return resolve_typdef_as_builtin(c, typedef_decl, "u8");
...@@ -4005,11 +4174,12 @@ static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *t...@@ -4005,11 +4174,12 @@ static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *t
40054174
4006 // trans_qual_type here might cause us to look at this typedef again so we put the item in the map first4175 // trans_qual_type here might cause us to look at this typedef again so we put the item in the map first
4007 AstNode *symbol_node = trans_create_node_symbol(c, type_name);4176 AstNode *symbol_node = trans_create_node_symbol(c, type_name);
4008 c->decl_table.put(typedef_decl->getCanonicalDecl(), symbol_node);4177 c->decl_table.put(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl), symbol_node);
40094178
4010 AstNode *type_node = trans_qual_type(c, child_qt, typedef_decl->getLocation());4179 AstNode *type_node = trans_qual_type(c, child_qt, ZigClangTypedefNameDecl_getLocation(typedef_decl));
4011 if (type_node == nullptr) {4180 if (type_node == nullptr) {
4012 emit_warning(c, typedef_decl->getLocation(), "typedef %s - unresolved child type", buf_ptr(type_name));4181 emit_warning(c, ZigClangTypedefNameDecl_getLocation(typedef_decl),
4182 "typedef %s - unresolved child type", buf_ptr(type_name));
4013 c->decl_table.put(typedef_decl, nullptr);4183 c->decl_table.put(typedef_decl, nullptr);
4014 // TODO add global var with type_name equal to @compileError("unable to resolve C type") 4184 // TODO add global var with type_name equal to @compileError("unable to resolve C type")
4015 return nullptr;4185 return nullptr;
...@@ -4019,33 +4189,33 @@ static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *t...@@ -4019,33 +4189,33 @@ static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *t
4019 return symbol_node;4189 return symbol_node;
4020}4190}
40214191
4022struct AstNode *demote_enum_to_opaque(Context *c, const clang::EnumDecl *enum_decl,4192struct AstNode *demote_enum_to_opaque(Context *c, const ZigClangEnumDecl *enum_decl, Buf *full_type_name,
4023 Buf *full_type_name, Buf *bare_name)4193 Buf *bare_name)
4024{4194{
4025 AstNode *opaque_node = trans_create_node_opaque(c);4195 AstNode *opaque_node = trans_create_node_opaque(c);
4026 if (full_type_name == nullptr) {4196 if (full_type_name == nullptr) {
4027 c->decl_table.put(enum_decl->getCanonicalDecl(), opaque_node);4197 c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), opaque_node);
4028 return opaque_node;4198 return opaque_node;
4029 }4199 }
4030 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);4200 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
4031 add_global_weak_alias(c, bare_name, full_type_name);4201 add_global_weak_alias(c, bare_name, full_type_name);
4032 add_global_var(c, full_type_name, opaque_node);4202 add_global_var(c, full_type_name, opaque_node);
4033 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);4203 c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), symbol_node);
4034 return symbol_node;4204 return symbol_node;
4035}4205}
40364206
4037static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) {4207static AstNode *resolve_enum_decl(Context *c, const ZigClangEnumDecl *enum_decl) {
4038 auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());4208 auto existing_entry = c->decl_table.maybe_get(ZigClangEnumDecl_getCanonicalDecl(enum_decl));
4039 if (existing_entry) {4209 if (existing_entry) {
4040 return existing_entry->value;4210 return existing_entry->value;
4041 }4211 }
40424212
4043 const char *raw_name = decl_name(enum_decl);4213 const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_decl);
4044 bool is_anonymous = (raw_name[0] == 0);4214 bool is_anonymous = (raw_name[0] == 0);
4045 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);4215 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
4046 Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));4216 Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
40474217
4048 const clang::EnumDecl *enum_def = enum_decl->getDefinition();4218 const ZigClangEnumDecl *enum_def = ZigClangEnumDecl_getDefinition(enum_decl);
4049 if (!enum_def) {4219 if (!enum_def) {
4050 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);4220 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
4051 }4221 }
...@@ -4053,8 +4223,8 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)...@@ -4053,8 +4223,8 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
40534223
4054 bool pure_enum = true;4224 bool pure_enum = true;
4055 uint32_t field_count = 0;4225 uint32_t field_count = 0;
4056 for (auto it = enum_def->enumerator_begin(),4226 for (auto it = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_begin(),
4057 it_end = enum_def->enumerator_end();4227 it_end = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_end();
4058 it != it_end; ++it, field_count += 1)4228 it != it_end; ++it, field_count += 1)
4059 {4229 {
4060 const clang::EnumConstantDecl *enum_const = *it;4230 const clang::EnumConstantDecl *enum_const = *it;
...@@ -4062,7 +4232,8 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)...@@ -4062,7 +4232,8 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
4062 pure_enum = false;4232 pure_enum = false;
4063 }4233 }
4064 }4234 }
4065 AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation());4235 AstNode *tag_int_type = trans_qual_type(c, ZigClangEnumDecl_getIntegerType(enum_decl),
4236 ZigClangEnumDecl_getLocation(enum_decl));
4066 assert(tag_int_type);4237 assert(tag_int_type);
40674238
4068 AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);4239 AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);
...@@ -4071,20 +4242,20 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)...@@ -4071,20 +4242,20 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
4071 // TODO only emit this tag type if the enum tag type is not the default.4242 // TODO only emit this tag type if the enum tag type is not the default.
4072 // I don't know what the default is, need to figure out how clang is deciding.4243 // I don't know what the default is, need to figure out how clang is deciding.
4073 // it appears to at least be different across gcc/msvc4244 // it appears to at least be different across gcc/msvc
4074 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) &&4245 if (!c_is_builtin_type(c, ZigClangEnumDecl_getIntegerType(enum_decl), ZigClangBuiltinTypeUInt) &&
4075 !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int))4246 !c_is_builtin_type(c, ZigClangEnumDecl_getIntegerType(enum_decl), ZigClangBuiltinTypeInt))
4076 {4247 {
4077 enum_node->data.container_decl.init_arg_expr = tag_int_type;4248 enum_node->data.container_decl.init_arg_expr = tag_int_type;
4078 }4249 }
4079 enum_node->data.container_decl.fields.resize(field_count);4250 enum_node->data.container_decl.fields.resize(field_count);
4080 uint32_t i = 0;4251 uint32_t i = 0;
4081 for (auto it = enum_def->enumerator_begin(),4252 for (auto it = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_begin(),
4082 it_end = enum_def->enumerator_end();4253 it_end = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_end();
4083 it != it_end; ++it, i += 1)4254 it != it_end; ++it, i += 1)
4084 {4255 {
4085 const clang::EnumConstantDecl *enum_const = *it;4256 const clang::EnumConstantDecl *enum_const = *it;
40864257
4087 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));4258 Buf *enum_val_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_const));
4088 Buf *field_name;4259 Buf *field_name;
4089 if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) {4260 if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) {
4090 field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));4261 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)...@@ -4092,7 +4263,8 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
4092 field_name = enum_val_name;4263 field_name = enum_val_name;
4093 }4264 }
40944265
4095 AstNode *int_node = pure_enum && !is_anonymous ? nullptr : trans_create_node_apint(c, enum_const->getInitVal());4266 AstNode *int_node = pure_enum && !is_anonymous ?
4267 nullptr : trans_create_node_apint(c, bitcast(&enum_const->getInitVal()));
4096 AstNode *field_node = trans_create_node(c, NodeTypeStructField);4268 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
4097 field_node->data.struct_field.name = field_name;4269 field_node->data.struct_field.name = field_name;
4098 field_node->data.struct_field.type = nullptr;4270 field_node->data.struct_field.type = nullptr;
...@@ -4102,7 +4274,7 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)...@@ -4102,7 +4274,7 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
4102 // in C each enum value is in the global namespace. so we put them there too.4274 // in C each enum value is in the global namespace. so we put them there too.
4103 // at this point we can rely on the enum emitting successfully4275 // at this point we can rely on the enum emitting successfully
4104 if (is_anonymous) {4276 if (is_anonymous) {
4105 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));4277 Buf *enum_val_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_const));
4106 add_global_var(c, enum_val_name, int_node);4278 add_global_var(c, enum_val_name, int_node);
4107 } else {4279 } else {
4108 AstNode *field_access_node = trans_create_node_field_access(c,4280 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)...@@ -4112,73 +4284,74 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl)
4112 }4284 }
41134285
4114 if (is_anonymous) {4286 if (is_anonymous) {
4115 c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node);4287 c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), enum_node);
4116 return enum_node;4288 return enum_node;
4117 } else {4289 } else {
4118 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);4290 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
4119 add_global_weak_alias(c, bare_name, full_type_name);4291 add_global_weak_alias(c, bare_name, full_type_name);
4120 add_global_var(c, full_type_name, enum_node);4292 add_global_var(c, full_type_name, enum_node);
4121 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);4293 c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), symbol_node);
4122 return enum_node;4294 return enum_node;
4123 }4295 }
4124}4296}
41254297
4126static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl,4298static AstNode *demote_struct_to_opaque(Context *c, const ZigClangRecordDecl *record_decl,
4127 Buf *full_type_name, Buf *bare_name)4299 Buf *full_type_name, Buf *bare_name)
4128{4300{
4129 AstNode *opaque_node = trans_create_node_opaque(c);4301 AstNode *opaque_node = trans_create_node_opaque(c);
4130 if (full_type_name == nullptr) {4302 if (full_type_name == nullptr) {
4131 c->decl_table.put(record_decl->getCanonicalDecl(), opaque_node);4303 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), opaque_node);
4132 return opaque_node;4304 return opaque_node;
4133 }4305 }
4134 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);4306 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
4135 add_global_weak_alias(c, bare_name, full_type_name);4307 add_global_weak_alias(c, bare_name, full_type_name);
4136 add_global_var(c, full_type_name, opaque_node);4308 add_global_var(c, full_type_name, opaque_node);
4137 c->decl_table.put(record_decl->getCanonicalDecl(), symbol_node);4309 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), symbol_node);
4138 return symbol_node;4310 return symbol_node;
4139}4311}
41404312
4141static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) {4313static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl) {
4142 auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());4314 auto existing_entry = c->decl_table.maybe_get(ZigClangRecordDecl_getCanonicalDecl(record_decl));
4143 if (existing_entry) {4315 if (existing_entry) {
4144 return existing_entry->value;4316 return existing_entry->value;
4145 }4317 }
41464318
4147 const char *raw_name = decl_name(record_decl);4319 const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)record_decl);
4148 const char *container_kind_name;4320 const char *container_kind_name;
4149 ContainerKind container_kind;4321 ContainerKind container_kind;
4150 if (record_decl->isUnion()) {4322 if (ZigClangRecordDecl_isUnion(record_decl)) {
4151 container_kind_name = "union";4323 container_kind_name = "union";
4152 container_kind = ContainerKindUnion;4324 container_kind = ContainerKindUnion;
4153 } else if (record_decl->isStruct()) {4325 } else if (ZigClangRecordDecl_isStruct(record_decl)) {
4154 container_kind_name = "struct";4326 container_kind_name = "struct";
4155 container_kind = ContainerKindStruct;4327 container_kind = ContainerKindStruct;
4156 } else {4328 } else {
4157 emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct or union", raw_name);4329 emit_warning(c, ZigClangRecordDecl_getLocation(record_decl),
4158 c->decl_table.put(record_decl->getCanonicalDecl(), nullptr);4330 "skipping record %s, not a struct or union", raw_name);
4331 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), nullptr);
4159 return nullptr;4332 return nullptr;
4160 }4333 }
41614334
4162 bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0;4335 bool is_anonymous = ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) || raw_name[0] == 0;
4163 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);4336 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
4164 Buf *full_type_name = (bare_name == nullptr) ?4337 Buf *full_type_name = (bare_name == nullptr) ?
4165 nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));4338 nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));
41664339
4167 clang::RecordDecl *record_def = record_decl->getDefinition();4340 const ZigClangRecordDecl *record_def = ZigClangRecordDecl_getDefinition(record_decl);
4168 if (record_def == nullptr) {4341 if (record_def == nullptr) {
4169 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);4342 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
4170 }4343 }
41714344
4172 // count fields and validate4345 // count fields and validate
4173 uint32_t field_count = 0;4346 uint32_t field_count = 0;
4174 for (auto it = record_def->field_begin(),4347 for (auto it = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_begin(),
4175 it_end = record_def->field_end();4348 it_end = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_end();
4176 it != it_end; ++it, field_count += 1)4349 it != it_end; ++it, field_count += 1)
4177 {4350 {
4178 const clang::FieldDecl *field_decl = *it;4351 const clang::FieldDecl *field_decl = *it;
41794352
4180 if (field_decl->isBitField()) {4353 if (field_decl->isBitField()) {
4181 emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",4354 emit_warning(c, bitcast(field_decl->getLocation()), "%s %s demoted to opaque type - has bitfield",
4182 container_kind_name,4355 container_kind_name,
4183 is_anonymous ? "(anon)" : buf_ptr(bare_name));4356 is_anonymous ? "(anon)" : buf_ptr(bare_name));
4184 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);4357 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_...@@ -4195,24 +4368,25 @@ static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_
41954368
4196 // must be before fields in case a circular reference happens4369 // must be before fields in case a circular reference happens
4197 if (is_anonymous) {4370 if (is_anonymous) {
4198 c->decl_table.put(record_decl->getCanonicalDecl(), struct_node);4371 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), struct_node);
4199 } else {4372 } else {
4200 c->decl_table.put(record_decl->getCanonicalDecl(), trans_create_node_symbol(c, full_type_name));4373 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), trans_create_node_symbol(c, full_type_name));
4201 }4374 }
42024375
4203 uint32_t i = 0;4376 uint32_t i = 0;
4204 for (auto it = record_def->field_begin(),4377 for (auto it = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_begin(),
4205 it_end = record_def->field_end();4378 it_end = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_end();
4206 it != it_end; ++it, i += 1)4379 it != it_end; ++it, i += 1)
4207 {4380 {
4208 const clang::FieldDecl *field_decl = *it;4381 const clang::FieldDecl *field_decl = *it;
42094382
4210 AstNode *field_node = trans_create_node(c, NodeTypeStructField);4383 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
4211 field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));4384 field_node->data.struct_field.name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)field_decl));
4212 field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation());4385 field_node->data.struct_field.type = trans_qual_type(c, bitcast(field_decl->getType()),
4386 bitcast(field_decl->getLocation()));
42134387
4214 if (field_node->data.struct_field.type == nullptr) {4388 if (field_node->data.struct_field.type == nullptr) {
4215 emit_warning(c, field_decl->getLocation(),4389 emit_warning(c, bitcast(field_decl->getLocation()),
4216 "%s %s demoted to opaque type - unresolved type",4390 "%s %s demoted to opaque type - unresolved type",
4217 container_kind_name,4391 container_kind_name,
4218 is_anonymous ? "(anon)" : buf_ptr(bare_name));4392 is_anonymous ? "(anon)" : buf_ptr(bare_name));
...@@ -4232,17 +4406,19 @@ static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_...@@ -4232,17 +4406,19 @@ static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_
4232 }4406 }
4233}4407}
42344408
4235static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) {4409static AstNode *trans_ap_value(Context *c, const ZigClangAPValue *ap_value, ZigClangQualType qt,
4236 switch (ap_value->getKind()) {4410 ZigClangSourceLocation source_loc)
4237 case clang::APValue::Int:4411{
4238 return trans_create_node_apint(c, ap_value->getInt());4412 switch (ZigClangAPValue_getKind(ap_value)) {
4239 case clang::APValue::Uninitialized:4413 case ZigClangAPValueInt:
4414 return trans_create_node_apint(c, ZigClangAPValue_getInt(ap_value));
4415 case ZigClangAPValueUninitialized:
4240 return trans_create_node(c, NodeTypeUndefinedLiteral);4416 return trans_create_node(c, NodeTypeUndefinedLiteral);
4241 case clang::APValue::Array: {4417 case ZigClangAPValueArray: {
4242 emit_warning(c, source_loc, "TODO add a test case for this code");4418 emit_warning(c, source_loc, "TODO add a test case for this code");
42434419
4244 unsigned init_count = ap_value->getArrayInitializedElts();4420 unsigned init_count = ZigClangAPValue_getArrayInitializedElts(ap_value);
4245 unsigned all_count = ap_value->getArraySize();4421 unsigned all_count = ZigClangAPValue_getArraySize(ap_value);
4246 unsigned leftover_count = all_count - init_count;4422 unsigned leftover_count = all_count - init_count;
4247 AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);4423 AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
4248 AstNode *arr_type_node = trans_qual_type(c, qt, source_loc);4424 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...@@ -4252,11 +4428,12 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual
4252 init_node->data.container_init_expr.type = arr_type_node;4428 init_node->data.container_init_expr.type = arr_type_node;
4253 init_node->data.container_init_expr.kind = ContainerInitKindArray;4429 init_node->data.container_init_expr.kind = ContainerInitKindArray;
42544430
4255 clang::QualType child_qt = qt.getTypePtr()->getAsArrayTypeUnsafe()->getElementType();4431 const clang::Type *qt_type = reinterpret_cast<const clang::Type *>(ZigClangQualType_getTypePtr(qt));
4432 ZigClangQualType child_qt = bitcast(qt_type->getAsArrayTypeUnsafe()->getElementType());
42564433
4257 for (size_t i = 0; i < init_count; i += 1) {4434 for (size_t i = 0; i < init_count; i += 1) {
4258 clang::APValue &elem_ap_val = ap_value->getArrayInitializedElt(i);4435 const ZigClangAPValue *elem_ap_val = ZigClangAPValue_getArrayInitializedElt(ap_value, i);
4259 AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);4436 AstNode *elem_node = trans_ap_value(c, elem_ap_val, child_qt, source_loc);
4260 if (elem_node == nullptr)4437 if (elem_node == nullptr)
4261 return nullptr;4438 return nullptr;
4262 init_node->data.container_init_expr.entries.append(elem_node);4439 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...@@ -4265,8 +4442,8 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual
4265 return init_node;4442 return init_node;
4266 }4443 }
42674444
4268 clang::APValue &filler_ap_val = ap_value->getArrayFiller();4445 const ZigClangAPValue *filler_ap_val = ZigClangAPValue_getArrayFiller(ap_value);
4269 AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);4446 AstNode *filler_node = trans_ap_value(c, filler_ap_val, child_qt, source_loc);
4270 if (filler_node == nullptr)4447 if (filler_node == nullptr)
4271 return nullptr;4448 return nullptr;
42724449
...@@ -4293,37 +4470,37 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual...@@ -4293,37 +4470,37 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual
42934470
4294 return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);4471 return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
4295 }4472 }
4296 case clang::APValue::LValue: {4473 case ZigClangAPValueLValue: {
4297 const clang::APValue::LValueBase lval_base = ap_value->getLValueBase();4474 const ZigClangAPValueLValueBase lval_base = ZigClangAPValue_getLValueBase(ap_value);
4298 if (const clang::Expr *expr = lval_base.dyn_cast<const clang::Expr *>()) {4475 if (const ZigClangExpr *expr = ZigClangAPValueLValueBase_dyn_cast_Expr(lval_base)) {
4299 return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);4476 return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
4300 }4477 }
4301 //const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>();4478 //const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>();
4302 emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl");4479 emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl");
4303 return nullptr;4480 return nullptr;
4304 }4481 }
4305 case clang::APValue::Float:4482 case ZigClangAPValueFloat:
4306 emit_warning(c, source_loc, "unsupported initializer value kind: Float");4483 emit_warning(c, source_loc, "unsupported initializer value kind: Float");
4307 return nullptr;4484 return nullptr;
4308 case clang::APValue::ComplexInt:4485 case ZigClangAPValueComplexInt:
4309 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");4486 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
4310 return nullptr;4487 return nullptr;
4311 case clang::APValue::ComplexFloat:4488 case ZigClangAPValueComplexFloat:
4312 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");4489 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
4313 return nullptr;4490 return nullptr;
4314 case clang::APValue::Vector:4491 case ZigClangAPValueVector:
4315 emit_warning(c, source_loc, "unsupported initializer value kind: Vector");4492 emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
4316 return nullptr;4493 return nullptr;
4317 case clang::APValue::Struct:4494 case ZigClangAPValueStruct:
4318 emit_warning(c, source_loc, "unsupported initializer value kind: Struct");4495 emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
4319 return nullptr;4496 return nullptr;
4320 case clang::APValue::Union:4497 case ZigClangAPValueUnion:
4321 emit_warning(c, source_loc, "unsupported initializer value kind: Union");4498 emit_warning(c, source_loc, "unsupported initializer value kind: Union");
4322 return nullptr;4499 return nullptr;
4323 case clang::APValue::MemberPointer:4500 case ZigClangAPValueMemberPointer:
4324 emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");4501 emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
4325 return nullptr;4502 return nullptr;
4326 case clang::APValue::AddrLabelDiff:4503 case ZigClangAPValueAddrLabelDiff:
4327 emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");4504 emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
4328 return nullptr;4505 return nullptr;
4329 }4506 }
...@@ -4331,42 +4508,42 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual...@@ -4331,42 +4508,42 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual
4331}4508}
43324509
4333static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {4510static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
4334 Buf *name = buf_create_from_str(decl_name(var_decl));4511 Buf *name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)var_decl));
43354512
4336 switch (var_decl->getTLSKind()) {4513 switch (var_decl->getTLSKind()) {
4337 case clang::VarDecl::TLS_None:4514 case clang::VarDecl::TLS_None:
4338 break;4515 break;
4339 case clang::VarDecl::TLS_Static:4516 case clang::VarDecl::TLS_Static:
4340 emit_warning(c, var_decl->getLocation(),4517 emit_warning(c, bitcast(var_decl->getLocation()),
4341 "ignoring variable '%s' - static thread local storage", buf_ptr(name));4518 "ignoring variable '%s' - static thread local storage", buf_ptr(name));
4342 return;4519 return;
4343 case clang::VarDecl::TLS_Dynamic:4520 case clang::VarDecl::TLS_Dynamic:
4344 emit_warning(c, var_decl->getLocation(),4521 emit_warning(c, bitcast(var_decl->getLocation()),
4345 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));4522 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
4346 return;4523 return;
4347 }4524 }
43484525
4349 clang::QualType qt = var_decl->getType();4526 ZigClangQualType qt = bitcast(var_decl->getType());
4350 AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());4527 AstNode *var_type = trans_qual_type(c, qt, bitcast(var_decl->getLocation()));
4351 if (var_type == nullptr) {4528 if (var_type == nullptr) {
4352 emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));4529 emit_warning(c, bitcast(var_decl->getLocation()), "ignoring variable '%s' - unresolved type", buf_ptr(name));
4353 return;4530 return;
4354 }4531 }
43554532
4356 bool is_extern = var_decl->hasExternalStorage();4533 bool is_extern = var_decl->hasExternalStorage();
4357 bool is_static = var_decl->isFileVarDecl();4534 bool is_static = var_decl->isFileVarDecl();
4358 bool is_const = qt.isConstQualified();4535 bool is_const = ZigClangQualType_isConstQualified(qt);
43594536
4360 if (is_static && !is_extern) {4537 if (is_static && !is_extern) {
4361 AstNode *init_node;4538 AstNode *init_node;
4362 if (var_decl->hasInit()) {4539 if (var_decl->hasInit()) {
4363 clang::APValue *ap_value = var_decl->evaluateValue();4540 const ZigClangAPValue *ap_value = bitcast(var_decl->evaluateValue());
4364 if (ap_value == nullptr) {4541 if (ap_value == nullptr) {
4365 emit_warning(c, var_decl->getLocation(),4542 emit_warning(c, bitcast(var_decl->getLocation()),
4366 "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));4543 "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
4367 return;4544 return;
4368 }4545 }
4369 init_node = trans_ap_value(c, ap_value, qt, var_decl->getLocation());4546 init_node = trans_ap_value(c, ap_value, qt, bitcast(var_decl->getLocation()));
4370 if (init_node == nullptr)4547 if (init_node == nullptr)
4371 return;4548 return;
4372 } else {4549 } else {
...@@ -4385,33 +4562,32 @@ static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {...@@ -4385,33 +4562,32 @@ static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
4385 return;4562 return;
4386 }4563 }
43874564
4388 emit_warning(c, var_decl->getLocation(),4565 emit_warning(c, bitcast(var_decl->getLocation()),
4389 "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name));4566 "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name));
4390 return;4567 return;
4391}4568}
43924569
4393static bool decl_visitor(void *context, const ZigClangDecl *zdecl) {4570static bool decl_visitor(void *context, const ZigClangDecl *decl) {
4394 const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zdecl);
4395 Context *c = (Context*)context;4571 Context *c = (Context*)context;
43964572
4397 switch (decl->getKind()) {4573 switch (ZigClangDecl_getKind(decl)) {
4398 case clang::Decl::Function:4574 case ZigClangDeclFunction:
4399 visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl));4575 visit_fn_decl(c, reinterpret_cast<const ZigClangFunctionDecl*>(decl));
4400 break;4576 break;
4401 case clang::Decl::Typedef:4577 case ZigClangDeclTypedef:
4402 resolve_typedef_decl(c, static_cast<const clang::TypedefNameDecl *>(decl));4578 resolve_typedef_decl(c, reinterpret_cast<const ZigClangTypedefNameDecl *>(decl));
4403 break;4579 break;
4404 case clang::Decl::Enum:4580 case ZigClangDeclEnum:
4405 resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl));4581 resolve_enum_decl(c, reinterpret_cast<const ZigClangEnumDecl *>(decl));
4406 break;4582 break;
4407 case clang::Decl::Record:4583 case ZigClangDeclRecord:
4408 resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl));4584 resolve_record_decl(c, reinterpret_cast<const ZigClangRecordDecl *>(decl));
4409 break;4585 break;
4410 case clang::Decl::Var:4586 case ZigClangDeclVar:
4411 visit_var_decl(c, static_cast<const clang::VarDecl *>(decl));4587 visit_var_decl(c, reinterpret_cast<const clang::VarDecl *>(decl));
4412 break;4588 break;
4413 default:4589 default:
4414 emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());4590 emit_warning(c, ZigClangDecl_getLocation(decl), "ignoring %s decl", ZigClangDecl_getDeclKindName(decl));
4415 }4591 }
44164592
4417 return true;4593 return true;
...@@ -4720,6 +4896,8 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok...@@ -4720,6 +4896,8 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok
4720 case CTokIdAsterisk:4896 case CTokIdAsterisk:
4721 case CTokIdBang:4897 case CTokIdBang:
4722 case CTokIdTilde:4898 case CTokIdTilde:
4899 case CTokIdShl:
4900 case CTokIdLt:
4723 // not able to make sense of this4901 // not able to make sense of this
4724 return nullptr;4902 return nullptr;
4725 }4903 }
...@@ -4751,6 +4929,13 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t...@@ -4751,6 +4929,13 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
4751 *tok_i += 1;4929 *tok_i += 1;
47524930
4753 node = trans_create_node_ptr_type(c, false, false, node, PtrLenC);4931 node = trans_create_node_ptr_type(c, false, false, node, PtrLenC);
4932 } else if (first_tok->id == CTokIdShl) {
4933 *tok_i += 1;
4934
4935 AstNode *rhs_node = parse_ctok_expr(c, ctok, tok_i);
4936 if (rhs_node == nullptr)
4937 return nullptr;
4938 node = trans_create_node_bin_op(c, node, BinOpTypeBitShiftLeft, rhs_node);
4754 } else {4939 } else {
4755 return node;4940 return node;
4756 }4941 }
...@@ -4846,10 +5031,10 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {...@@ -4846,10 +5031,10 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
4846 clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity);5031 clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity);
4847 const char *raw_name = macro->getName()->getNameStart();5032 const char *raw_name = macro->getName()->getNameStart();
4848 clang::SourceRange range = macro->getSourceRange();5033 clang::SourceRange range = macro->getSourceRange();
4849 clang::SourceLocation begin_loc = range.getBegin();5034 ZigClangSourceLocation begin_loc = bitcast(range.getBegin());
4850 clang::SourceLocation end_loc = range.getEnd();5035 ZigClangSourceLocation end_loc = bitcast(range.getEnd());
48515036
4852 if (begin_loc == end_loc) {5037 if (ZigClangSourceLocation_eq(begin_loc, end_loc)) {
4853 // this means it is a macro without a value5038 // this means it is a macro without a value
4854 // we don't care about such things5039 // we don't care about such things
4855 continue;5040 continue;
...@@ -4859,21 +5044,22 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {...@@ -4859,21 +5044,22 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
4859 continue;5044 continue;
4860 }5045 }
48615046
4862 const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, bitcast(begin_loc));5047 const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, begin_loc);
4863 process_macro(c, &ctok, name, begin_c);5048 process_macro(c, &ctok, name, begin_c);
4864 }5049 }
4865 }5050 }
4866 }5051 }
4867}5052}
48685053
4869Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file,5054Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
4870 CodeGen *codegen, Buf *tmp_dep_file)5055 Stage2ErrorMsg **errors_ptr, size_t *errors_len,
5056 const char **args_begin, const char **args_end,
5057 Stage2TranslateMode mode, const char *resources_path)
4871{5058{
4872 Context context = {0};5059 Context context = {0};
4873 Context *c = &context;5060 Context *c = &context;
4874 c->warnings_on = codegen->verbose_cimport;5061 c->warnings_on = codegen->verbose_cimport;
4875 c->errors = errors;5062 if (mode == Stage2TranslateModeImport) {
4876 if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) {
4877 c->visib_mod = VisibModPub;5063 c->visib_mod = VisibModPub;
4878 c->want_export = false;5064 c->want_export = false;
4879 } else {5065 } else {
...@@ -4887,161 +5073,10 @@ Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const c...@@ -4887,161 +5073,10 @@ Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const c
4887 c->codegen = codegen;5073 c->codegen = codegen;
4888 c->global_scope = trans_scope_root_create(c);5074 c->global_scope = trans_scope_root_create(c);
48895075
4890 ZigList<const char *> clang_argv = {0};5076 ZigClangASTUnit *ast_unit = ZigClangLoadFromCommandLine(args_begin, args_end, errors_ptr, errors_len,
48915077 resources_path);
4892 clang_argv.append("-x");5078 if (ast_unit == nullptr) {
4893 clang_argv.append("c");5079 if (*errors_len == 0) return ErrorNoMem;
4894
4895 if (tmp_dep_file != nullptr) {
4896 clang_argv.append("-MD");
4897 clang_argv.append("-MV");
4898 clang_argv.append("-MF");
4899 clang_argv.append(buf_ptr(tmp_dep_file));
4900 }
4901
4902 if (c->codegen->zig_target->is_native) {
4903 char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS");
4904 if (ZIG_PARSEC_CFLAGS) {
4905 Buf tmp_buf = BUF_INIT;
4906 char *start = ZIG_PARSEC_CFLAGS;
4907 char *space = strstr(start, " ");
4908 while (space) {
4909 if (space - start > 0) {
4910 buf_init_from_mem(&tmp_buf, start, space - start);
4911 clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
4912 }
4913 start = space + 1;
4914 space = strstr(start, " ");
4915 }
4916 buf_init_from_str(&tmp_buf, start);
4917 clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
4918 }
4919 }
4920
4921 clang_argv.append("-nobuiltininc");
4922 clang_argv.append("-nostdinc");
4923 clang_argv.append("-nostdinc++");
4924 if (codegen->libc_link_lib == nullptr) {
4925 clang_argv.append("-nolibc");
4926 }
4927
4928 clang_argv.append("-isystem");
4929 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
4930
4931 for (size_t i = 0; i < codegen->libc_include_dir_len; i += 1) {
4932 Buf *include_dir = codegen->libc_include_dir_list[i];
4933 clang_argv.append("-isystem");
4934 clang_argv.append(buf_ptr(include_dir));
4935 }
4936
4937 // windows c runtime requires -D_DEBUG if using debug libraries
4938 if (codegen->build_mode == BuildModeDebug) {
4939 clang_argv.append("-D_DEBUG");
4940 }
4941
4942 for (size_t i = 0; i < codegen->clang_argv_len; i += 1) {
4943 clang_argv.append(codegen->clang_argv[i]);
4944 }
4945
4946 // we don't need spell checking and it slows things down
4947 clang_argv.append("-fno-spell-checking");
4948
4949 // this gives us access to preprocessing entities, presumably at
4950 // the cost of performance
4951 clang_argv.append("-Xclang");
4952 clang_argv.append("-detailed-preprocessing-record");
4953
4954 if (c->codegen->zig_target->is_native) {
4955 clang_argv.append("-march=native");
4956 } else {
4957 clang_argv.append("-target");
4958 clang_argv.append(buf_ptr(&c->codegen->triple_str));
4959 }
4960
4961 clang_argv.append(target_file);
4962
4963 if (codegen->verbose_cc) {
4964 fprintf(stderr, "clang");
4965 for (size_t i = 0; i < clang_argv.length; i += 1) {
4966 fprintf(stderr, " %s", clang_argv.at(i));
4967 }
4968 fprintf(stderr, "\n");
4969 }
4970
4971 // to make the [start...end] argument work
4972 clang_argv.append(nullptr);
4973
4974 clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
4975
4976 std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();
4977
4978 bool only_local_decls = true;
4979 bool capture_diagnostics = true;
4980 bool user_files_are_volatile = true;
4981 bool allow_pch_with_compiler_errors = false;
4982 bool single_file_parse = false;
4983 bool for_serialization = false;
4984 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
4985 std::unique_ptr<clang::ASTUnit> err_unit;
4986 ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine(
4987 &clang_argv.at(0), &clang_argv.last(),
4988 pch_container_ops, diags, resources_path,
4989 only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
4990 false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
4991 single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit,
4992 nullptr));
4993
4994 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
4995 if (!ast_unit && !err_unit) {
4996 return ErrorFileSystem;
4997 }
4998
4999 if (diags->getClient()->getNumErrors() > 0) {
5000 if (ast_unit) {
5001 err_unit = std::unique_ptr<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(ast_unit));
5002 }
5003
5004 for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
5005 it_end = err_unit->stored_diag_end();
5006 it != it_end; ++it)
5007 {
5008 switch (it->getLevel()) {
5009 case clang::DiagnosticsEngine::Ignored:
5010 case clang::DiagnosticsEngine::Note:
5011 case clang::DiagnosticsEngine::Remark:
5012 case clang::DiagnosticsEngine::Warning:
5013 continue;
5014 case clang::DiagnosticsEngine::Error:
5015 case clang::DiagnosticsEngine::Fatal:
5016 break;
5017 }
5018 llvm::StringRef msg_str_ref = it->getMessage();
5019 Buf *msg = string_ref_to_buf(msg_str_ref);
5020 clang::FullSourceLoc fsl = it->getLocation();
5021 if (fsl.hasManager()) {
5022 clang::FileID file_id = fsl.getFileID();
5023 clang::StringRef filename = fsl.getManager().getFilename(fsl);
5024 unsigned line = fsl.getSpellingLineNumber() - 1;
5025 unsigned column = fsl.getSpellingColumnNumber() - 1;
5026 unsigned offset = fsl.getManager().getFileOffset(fsl);
5027 const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
5028 Buf *path;
5029 if (filename.empty()) {
5030 path = buf_alloc();
5031 } else {
5032 path = string_ref_to_buf(filename);
5033 }
5034
5035 ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
5036
5037 c->errors->append(err_msg);
5038 } else {
5039 // NOTE the only known way this gets triggered right now is if you have a lot of errors
5040 // clang emits "too many errors emitted, stopping now"
5041 fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg));
5042 }
5043 }
5044
5045 return ErrorCCompileErrors;5080 return ErrorCCompileErrors;
5046 }5081 }
50475082
...@@ -5059,5 +5094,7 @@ Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const c...@@ -5059,5 +5094,7 @@ Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const c
50595094
5060 *out_root_node = c->root;5095 *out_root_node = c->root;
50615096
5097 ZigClangASTUnit_delete(ast_unit);
5098
5062 return ErrorNone;5099 return ErrorNone;
5063}5100}
src/translate_c.hpp+4-2
...@@ -11,7 +11,9 @@...@@ -11,7 +11,9 @@
1111
12#include "all_types.hpp"12#include "all_types.hpp"
1313
14Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file,14Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
15 CodeGen *codegen, Buf *tmp_dep_file);15 Stage2ErrorMsg **errors_ptr, size_t *errors_len,
16 const char **args_begin, const char **args_end,
17 Stage2TranslateMode mode, const char *resources_path);
1618
17#endif19#endif
src/userland.cpp created+44
...@@ -0,0 +1,44 @@
1// This file is a shim for zig1. The real implementations of these are in
2// src-self-hosted/stage1.zig
3
4#include "userland.h"
5#include "ast_render.hpp"
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
10Error stage2_translate_c(struct Stage2Ast **out_ast,
11 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
12 const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
13 const char *resources_path)
14{
15 const char *msg = "stage0 called stage2_translate_c";
16 stage2_panic(msg, strlen(msg));
17}
18
19void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) {
20 const char *msg = "stage0 called stage2_free_clang_errors";
21 stage2_panic(msg, strlen(msg));
22}
23
24void stage2_zen(const char **ptr, size_t *len) {
25 const char *msg = "stage0 called stage2_zen";
26 stage2_panic(msg, strlen(msg));
27}
28
29void stage2_panic(const char *ptr, size_t len) {
30 fwrite(ptr, 1, len, stderr);
31 fprintf(stderr, "\n");
32 fflush(stderr);
33 abort();
34}
35
36void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) {
37 const char *msg = "stage0 called stage2_render_ast";
38 stage2_panic(msg, strlen(msg));
39}
40
41int stage2_fmt(int argc, char **argv) {
42 const char *msg = "stage0 called stage2_fmt";
43 stage2_panic(msg, strlen(msg));
44}
src/userland.h created+120
...@@ -0,0 +1,120 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_USERLAND_H
9#define ZIG_USERLAND_H
10
11#include <stddef.h>
12#include <stdio.h>
13
14#ifdef __cplusplus
15#define ZIG_EXTERN_C extern "C"
16#else
17#define ZIG_EXTERN_C
18#endif
19
20#if defined(_MSC_VER)
21#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn)
22#else
23#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn))
24#endif
25
26// ABI warning: the types and declarations in this file must match both those in
27// userland.cpp and src-self-hosted/stage1.zig.
28
29// ABI warning
30enum Error {
31 ErrorNone,
32 ErrorNoMem,
33 ErrorInvalidFormat,
34 ErrorSemanticAnalyzeFail,
35 ErrorAccess,
36 ErrorInterrupted,
37 ErrorSystemResources,
38 ErrorFileNotFound,
39 ErrorFileSystem,
40 ErrorFileTooBig,
41 ErrorDivByZero,
42 ErrorOverflow,
43 ErrorPathAlreadyExists,
44 ErrorUnexpected,
45 ErrorExactDivRemainder,
46 ErrorNegativeDenominator,
47 ErrorShiftedOutOneBits,
48 ErrorCCompileErrors,
49 ErrorEndOfFile,
50 ErrorIsDir,
51 ErrorNotDir,
52 ErrorUnsupportedOperatingSystem,
53 ErrorSharingViolation,
54 ErrorPipeBusy,
55 ErrorPrimitiveTypeNotFound,
56 ErrorCacheUnavailable,
57 ErrorPathTooLong,
58 ErrorCCompilerCannotFindFile,
59 ErrorReadingDepFile,
60 ErrorInvalidDepFile,
61 ErrorMissingArchitecture,
62 ErrorMissingOperatingSystem,
63 ErrorUnknownArchitecture,
64 ErrorUnknownOperatingSystem,
65 ErrorUnknownABI,
66 ErrorInvalidFilename,
67 ErrorDiskQuota,
68 ErrorDiskSpace,
69 ErrorUnexpectedWriteFailure,
70 ErrorUnexpectedSeekFailure,
71 ErrorUnexpectedFileTruncationFailure,
72 ErrorUnimplemented,
73 ErrorOperationAborted,
74 ErrorBrokenPipe,
75 ErrorNoSpaceLeft,
76};
77
78// ABI warning
79enum Stage2TranslateMode {
80 Stage2TranslateModeImport,
81 Stage2TranslateModeTranslate,
82};
83
84// ABI warning
85struct Stage2ErrorMsg {
86 const char *filename_ptr; // can be null
87 size_t filename_len;
88 const char *msg_ptr;
89 size_t msg_len;
90 const char *source; // valid until the ASTUnit is freed. can be null
91 unsigned line; // 0 based
92 unsigned column; // 0 based
93 unsigned offset; // byte offset into source
94};
95
96// ABI warning
97struct Stage2Ast;
98
99// ABI warning
100ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast,
101 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
102 const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
103 const char *resources_path);
104
105// ABI warning
106ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
107
108// ABI warning
109ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
110
111// ABI warning
112ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
113
114// ABI warning
115ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
116
117// ABI warning
118ZIG_EXTERN_C int stage2_fmt(int argc, char **argv);
119
120#endif
src/util.cpp+9-1
...@@ -10,17 +10,25 @@...@@ -10,17 +10,25 @@
10#include <stdarg.h>10#include <stdarg.h>
1111
12#include "util.hpp"12#include "util.hpp"
13#include "userland.h"
1314
14void zig_panic(const char *format, ...) {15void zig_panic(const char *format, ...) {
15 va_list ap;16 va_list ap;
16 va_start(ap, format);17 va_start(ap, format);
17 vfprintf(stderr, format, ap);18 vfprintf(stderr, format, ap);
18 fprintf(stderr, "\n");
19 fflush(stderr);19 fflush(stderr);
20 va_end(ap);20 va_end(ap);
21 stage2_panic(nullptr, 0);
21 abort();22 abort();
22}23}
2324
25void assert(bool ok) {
26 if (!ok) {
27 const char *msg = "Assertion failed. This is a bug in the Zig compiler.";
28 stage2_panic(msg, strlen(msg));
29 }
30}
31
24uint32_t int_hash(int i) {32uint32_t int_hash(int i) {
25 return (uint32_t)(i % UINT32_MAX);33 return (uint32_t)(i % UINT32_MAX);
26}34}
src/util.hpp+4
...@@ -48,6 +48,10 @@ void zig_panic(const char *format, ...);...@@ -48,6 +48,10 @@ void zig_panic(const char *format, ...);
4848
49#define zig_unreachable() zig_panic("unreachable: %s:%s:%d", __FILE__, __func__, __LINE__)49#define zig_unreachable() zig_panic("unreachable: %s:%s:%d", __FILE__, __func__, __LINE__)
5050
51// Assertions in stage1 are always on, and they call zig @panic.
52#undef assert
53void assert(bool ok);
54
51#if defined(_MSC_VER)55#if defined(_MSC_VER)
52static inline int clzll(unsigned long long mask) {56static inline int clzll(unsigned long long mask) {
53 unsigned long lz;57 unsigned long lz;
src/zig_clang.cpp+1667-50
...@@ -28,41 +28,41 @@...@@ -28,41 +28,41 @@
28#endif28#endif
2929
30// Detect additions to the enum30// Detect additions to the enum
31void zig2clang_BO(ZigClangBO op) {31void ZigClang_detect_enum_BO(clang::BinaryOperatorKind op) {
32 switch (op) {32 switch (op) {
33 case ZigClangBO_PtrMemD:33 case clang::BO_PtrMemD:
34 case ZigClangBO_PtrMemI:34 case clang::BO_PtrMemI:
35 case ZigClangBO_Cmp:35 case clang::BO_Cmp:
36 case ZigClangBO_Mul:36 case clang::BO_Mul:
37 case ZigClangBO_Div:37 case clang::BO_Div:
38 case ZigClangBO_Rem:38 case clang::BO_Rem:
39 case ZigClangBO_Add:39 case clang::BO_Add:
40 case ZigClangBO_Sub:40 case clang::BO_Sub:
41 case ZigClangBO_Shl:41 case clang::BO_Shl:
42 case ZigClangBO_Shr:42 case clang::BO_Shr:
43 case ZigClangBO_LT:43 case clang::BO_LT:
44 case ZigClangBO_GT:44 case clang::BO_GT:
45 case ZigClangBO_LE:45 case clang::BO_LE:
46 case ZigClangBO_GE:46 case clang::BO_GE:
47 case ZigClangBO_EQ:47 case clang::BO_EQ:
48 case ZigClangBO_NE:48 case clang::BO_NE:
49 case ZigClangBO_And:49 case clang::BO_And:
50 case ZigClangBO_Xor:50 case clang::BO_Xor:
51 case ZigClangBO_Or:51 case clang::BO_Or:
52 case ZigClangBO_LAnd:52 case clang::BO_LAnd:
53 case ZigClangBO_LOr:53 case clang::BO_LOr:
54 case ZigClangBO_Assign:54 case clang::BO_Assign:
55 case ZigClangBO_Comma:55 case clang::BO_Comma:
56 case ZigClangBO_MulAssign:56 case clang::BO_MulAssign:
57 case ZigClangBO_DivAssign:57 case clang::BO_DivAssign:
58 case ZigClangBO_RemAssign:58 case clang::BO_RemAssign:
59 case ZigClangBO_AddAssign:59 case clang::BO_AddAssign:
60 case ZigClangBO_SubAssign:60 case clang::BO_SubAssign:
61 case ZigClangBO_ShlAssign:61 case clang::BO_ShlAssign:
62 case ZigClangBO_ShrAssign:62 case clang::BO_ShrAssign:
63 case ZigClangBO_AndAssign:63 case clang::BO_AndAssign:
64 case ZigClangBO_XorAssign:64 case clang::BO_XorAssign:
65 case ZigClangBO_OrAssign:65 case clang::BO_OrAssign:
66 break;66 break;
67 }67 }
68}68}
...@@ -101,23 +101,23 @@ static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAs...@@ -101,23 +101,23 @@ static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAs
101static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, "");101static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, "");
102static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, "");102static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, "");
103103
104// This function detects additions to the enum104// Detect additions to the enum
105void zig2clang_UO(ZigClangUO op) {105void ZigClang_detect_enum_UO(clang::UnaryOperatorKind op) {
106 switch (op) {106 switch (op) {
107 case ZigClangUO_AddrOf:107 case clang::UO_AddrOf:
108 case ZigClangUO_Coawait:108 case clang::UO_Coawait:
109 case ZigClangUO_Deref:109 case clang::UO_Deref:
110 case ZigClangUO_Extension:110 case clang::UO_Extension:
111 case ZigClangUO_Imag:111 case clang::UO_Imag:
112 case ZigClangUO_LNot:112 case clang::UO_LNot:
113 case ZigClangUO_Minus:113 case clang::UO_Minus:
114 case ZigClangUO_Not:114 case clang::UO_Not:
115 case ZigClangUO_Plus:115 case clang::UO_Plus:
116 case ZigClangUO_PostDec:116 case clang::UO_PostDec:
117 case ZigClangUO_PostInc:117 case clang::UO_PostInc:
118 case ZigClangUO_PreDec:118 case clang::UO_PreDec:
119 case ZigClangUO_PreInc:119 case clang::UO_PreInc:
120 case ZigClangUO_Real:120 case clang::UO_Real:
121 break;121 break;
122 }122 }
123}123}
...@@ -137,6 +137,1125 @@ static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, "...@@ -137,6 +137,1125 @@ static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, "
137static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, "");137static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, "");
138static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, "");138static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, "");
139139
140// Detect additions to the enum
141void ZigClang_detect_enum_CK(clang::CastKind x) {
142 switch (x) {
143 case clang::CK_ARCConsumeObject:
144 case clang::CK_ARCExtendBlockObject:
145 case clang::CK_ARCProduceObject:
146 case clang::CK_ARCReclaimReturnedObject:
147 case clang::CK_AddressSpaceConversion:
148 case clang::CK_AnyPointerToBlockPointerCast:
149 case clang::CK_ArrayToPointerDecay:
150 case clang::CK_AtomicToNonAtomic:
151 case clang::CK_BaseToDerived:
152 case clang::CK_BaseToDerivedMemberPointer:
153 case clang::CK_BitCast:
154 case clang::CK_BlockPointerToObjCPointerCast:
155 case clang::CK_BooleanToSignedIntegral:
156 case clang::CK_BuiltinFnToFnPtr:
157 case clang::CK_CPointerToObjCPointerCast:
158 case clang::CK_ConstructorConversion:
159 case clang::CK_CopyAndAutoreleaseBlockObject:
160 case clang::CK_Dependent:
161 case clang::CK_DerivedToBase:
162 case clang::CK_DerivedToBaseMemberPointer:
163 case clang::CK_Dynamic:
164 case clang::CK_FloatingCast:
165 case clang::CK_FloatingComplexCast:
166 case clang::CK_FloatingComplexToBoolean:
167 case clang::CK_FloatingComplexToIntegralComplex:
168 case clang::CK_FloatingComplexToReal:
169 case clang::CK_FloatingRealToComplex:
170 case clang::CK_FloatingToBoolean:
171 case clang::CK_FloatingToIntegral:
172 case clang::CK_FunctionToPointerDecay:
173 case clang::CK_IntToOCLSampler:
174 case clang::CK_IntegralCast:
175 case clang::CK_IntegralComplexCast:
176 case clang::CK_IntegralComplexToBoolean:
177 case clang::CK_IntegralComplexToFloatingComplex:
178 case clang::CK_IntegralComplexToReal:
179 case clang::CK_IntegralRealToComplex:
180 case clang::CK_IntegralToBoolean:
181 case clang::CK_IntegralToFloating:
182 case clang::CK_IntegralToPointer:
183 case clang::CK_LValueBitCast:
184 case clang::CK_LValueToRValue:
185 case clang::CK_MemberPointerToBoolean:
186 case clang::CK_NoOp:
187 case clang::CK_NonAtomicToAtomic:
188 case clang::CK_NullToMemberPointer:
189 case clang::CK_NullToPointer:
190 case clang::CK_ObjCObjectLValueCast:
191 case clang::CK_PointerToBoolean:
192 case clang::CK_PointerToIntegral:
193 case clang::CK_ReinterpretMemberPointer:
194 case clang::CK_ToUnion:
195 case clang::CK_ToVoid:
196 case clang::CK_UncheckedDerivedToBase:
197 case clang::CK_UserDefinedConversion:
198 case clang::CK_VectorSplat:
199 case clang::CK_ZeroToOCLOpaqueType:
200 case clang::CK_FixedPointCast:
201 case clang::CK_FixedPointToBoolean:
202 break;
203 }
204};
205
206static_assert((clang::CastKind)ZigClangCK_Dependent == clang::CK_Dependent, "");
207static_assert((clang::CastKind)ZigClangCK_BitCast == clang::CK_BitCast, "");
208static_assert((clang::CastKind)ZigClangCK_LValueBitCast == clang::CK_LValueBitCast, "");
209static_assert((clang::CastKind)ZigClangCK_LValueToRValue == clang::CK_LValueToRValue, "");
210static_assert((clang::CastKind)ZigClangCK_NoOp == clang::CK_NoOp, "");
211static_assert((clang::CastKind)ZigClangCK_BaseToDerived == clang::CK_BaseToDerived, "");
212static_assert((clang::CastKind)ZigClangCK_DerivedToBase == clang::CK_DerivedToBase, "");
213static_assert((clang::CastKind)ZigClangCK_UncheckedDerivedToBase == clang::CK_UncheckedDerivedToBase, "");
214static_assert((clang::CastKind)ZigClangCK_Dynamic == clang::CK_Dynamic, "");
215static_assert((clang::CastKind)ZigClangCK_ToUnion == clang::CK_ToUnion, "");
216static_assert((clang::CastKind)ZigClangCK_ArrayToPointerDecay == clang::CK_ArrayToPointerDecay, "");
217static_assert((clang::CastKind)ZigClangCK_FunctionToPointerDecay == clang::CK_FunctionToPointerDecay, "");
218static_assert((clang::CastKind)ZigClangCK_NullToPointer == clang::CK_NullToPointer, "");
219static_assert((clang::CastKind)ZigClangCK_NullToMemberPointer == clang::CK_NullToMemberPointer, "");
220static_assert((clang::CastKind)ZigClangCK_BaseToDerivedMemberPointer == clang::CK_BaseToDerivedMemberPointer, "");
221static_assert((clang::CastKind)ZigClangCK_DerivedToBaseMemberPointer == clang::CK_DerivedToBaseMemberPointer, "");
222static_assert((clang::CastKind)ZigClangCK_MemberPointerToBoolean == clang::CK_MemberPointerToBoolean, "");
223static_assert((clang::CastKind)ZigClangCK_ReinterpretMemberPointer == clang::CK_ReinterpretMemberPointer, "");
224static_assert((clang::CastKind)ZigClangCK_UserDefinedConversion == clang::CK_UserDefinedConversion, "");
225static_assert((clang::CastKind)ZigClangCK_ConstructorConversion == clang::CK_ConstructorConversion, "");
226static_assert((clang::CastKind)ZigClangCK_IntegralToPointer == clang::CK_IntegralToPointer, "");
227static_assert((clang::CastKind)ZigClangCK_PointerToIntegral == clang::CK_PointerToIntegral, "");
228static_assert((clang::CastKind)ZigClangCK_PointerToBoolean == clang::CK_PointerToBoolean, "");
229static_assert((clang::CastKind)ZigClangCK_ToVoid == clang::CK_ToVoid, "");
230static_assert((clang::CastKind)ZigClangCK_VectorSplat == clang::CK_VectorSplat, "");
231static_assert((clang::CastKind)ZigClangCK_IntegralCast == clang::CK_IntegralCast, "");
232static_assert((clang::CastKind)ZigClangCK_IntegralToBoolean == clang::CK_IntegralToBoolean, "");
233static_assert((clang::CastKind)ZigClangCK_IntegralToFloating == clang::CK_IntegralToFloating, "");
234static_assert((clang::CastKind)ZigClangCK_FixedPointCast == clang::CK_FixedPointCast, "");
235static_assert((clang::CastKind)ZigClangCK_FixedPointToBoolean == clang::CK_FixedPointToBoolean, "");
236static_assert((clang::CastKind)ZigClangCK_FloatingToIntegral == clang::CK_FloatingToIntegral, "");
237static_assert((clang::CastKind)ZigClangCK_FloatingToBoolean == clang::CK_FloatingToBoolean, "");
238static_assert((clang::CastKind)ZigClangCK_BooleanToSignedIntegral == clang::CK_BooleanToSignedIntegral, "");
239static_assert((clang::CastKind)ZigClangCK_FloatingCast == clang::CK_FloatingCast, "");
240static_assert((clang::CastKind)ZigClangCK_CPointerToObjCPointerCast == clang::CK_CPointerToObjCPointerCast, "");
241static_assert((clang::CastKind)ZigClangCK_BlockPointerToObjCPointerCast == clang::CK_BlockPointerToObjCPointerCast, "");
242static_assert((clang::CastKind)ZigClangCK_AnyPointerToBlockPointerCast == clang::CK_AnyPointerToBlockPointerCast, "");
243static_assert((clang::CastKind)ZigClangCK_ObjCObjectLValueCast == clang::CK_ObjCObjectLValueCast, "");
244static_assert((clang::CastKind)ZigClangCK_FloatingRealToComplex == clang::CK_FloatingRealToComplex, "");
245static_assert((clang::CastKind)ZigClangCK_FloatingComplexToReal == clang::CK_FloatingComplexToReal, "");
246static_assert((clang::CastKind)ZigClangCK_FloatingComplexToBoolean == clang::CK_FloatingComplexToBoolean, "");
247static_assert((clang::CastKind)ZigClangCK_FloatingComplexCast == clang::CK_FloatingComplexCast, "");
248static_assert((clang::CastKind)ZigClangCK_FloatingComplexToIntegralComplex == clang::CK_FloatingComplexToIntegralComplex, "");
249static_assert((clang::CastKind)ZigClangCK_IntegralRealToComplex == clang::CK_IntegralRealToComplex, "");
250static_assert((clang::CastKind)ZigClangCK_IntegralComplexToReal == clang::CK_IntegralComplexToReal, "");
251static_assert((clang::CastKind)ZigClangCK_IntegralComplexToBoolean == clang::CK_IntegralComplexToBoolean, "");
252static_assert((clang::CastKind)ZigClangCK_IntegralComplexCast == clang::CK_IntegralComplexCast, "");
253static_assert((clang::CastKind)ZigClangCK_IntegralComplexToFloatingComplex == clang::CK_IntegralComplexToFloatingComplex, "");
254static_assert((clang::CastKind)ZigClangCK_ARCProduceObject == clang::CK_ARCProduceObject, "");
255static_assert((clang::CastKind)ZigClangCK_ARCConsumeObject == clang::CK_ARCConsumeObject, "");
256static_assert((clang::CastKind)ZigClangCK_ARCReclaimReturnedObject == clang::CK_ARCReclaimReturnedObject, "");
257static_assert((clang::CastKind)ZigClangCK_ARCExtendBlockObject == clang::CK_ARCExtendBlockObject, "");
258static_assert((clang::CastKind)ZigClangCK_AtomicToNonAtomic == clang::CK_AtomicToNonAtomic, "");
259static_assert((clang::CastKind)ZigClangCK_NonAtomicToAtomic == clang::CK_NonAtomicToAtomic, "");
260static_assert((clang::CastKind)ZigClangCK_CopyAndAutoreleaseBlockObject == clang::CK_CopyAndAutoreleaseBlockObject, "");
261static_assert((clang::CastKind)ZigClangCK_BuiltinFnToFnPtr == clang::CK_BuiltinFnToFnPtr, "");
262static_assert((clang::CastKind)ZigClangCK_ZeroToOCLOpaqueType == clang::CK_ZeroToOCLOpaqueType, "");
263static_assert((clang::CastKind)ZigClangCK_AddressSpaceConversion == clang::CK_AddressSpaceConversion, "");
264static_assert((clang::CastKind)ZigClangCK_IntToOCLSampler == clang::CK_IntToOCLSampler, "");
265
266// Detect additions to the enum
267void ZigClang_detect_enum_TypeClass(clang::Type::TypeClass ty) {
268 switch (ty) {
269 case clang::Type::Builtin:
270 case clang::Type::Complex:
271 case clang::Type::Pointer:
272 case clang::Type::BlockPointer:
273 case clang::Type::LValueReference:
274 case clang::Type::RValueReference:
275 case clang::Type::MemberPointer:
276 case clang::Type::ConstantArray:
277 case clang::Type::IncompleteArray:
278 case clang::Type::VariableArray:
279 case clang::Type::DependentSizedArray:
280 case clang::Type::DependentSizedExtVector:
281 case clang::Type::DependentAddressSpace:
282 case clang::Type::Vector:
283 case clang::Type::DependentVector:
284 case clang::Type::ExtVector:
285 case clang::Type::FunctionProto:
286 case clang::Type::FunctionNoProto:
287 case clang::Type::UnresolvedUsing:
288 case clang::Type::Paren:
289 case clang::Type::Typedef:
290 case clang::Type::Adjusted:
291 case clang::Type::Decayed:
292 case clang::Type::TypeOfExpr:
293 case clang::Type::TypeOf:
294 case clang::Type::Decltype:
295 case clang::Type::UnaryTransform:
296 case clang::Type::Record:
297 case clang::Type::Enum:
298 case clang::Type::Elaborated:
299 case clang::Type::Attributed:
300 case clang::Type::TemplateTypeParm:
301 case clang::Type::SubstTemplateTypeParm:
302 case clang::Type::SubstTemplateTypeParmPack:
303 case clang::Type::TemplateSpecialization:
304 case clang::Type::Auto:
305 case clang::Type::DeducedTemplateSpecialization:
306 case clang::Type::InjectedClassName:
307 case clang::Type::DependentName:
308 case clang::Type::DependentTemplateSpecialization:
309 case clang::Type::PackExpansion:
310 case clang::Type::ObjCTypeParam:
311 case clang::Type::ObjCObject:
312 case clang::Type::ObjCInterface:
313 case clang::Type::ObjCObjectPointer:
314 case clang::Type::Pipe:
315 case clang::Type::Atomic:
316 break;
317 }
318}
319
320static_assert((clang::Type::TypeClass)ZigClangType_Builtin == clang::Type::Builtin, "");
321static_assert((clang::Type::TypeClass)ZigClangType_Complex == clang::Type::Complex, "");
322static_assert((clang::Type::TypeClass)ZigClangType_Pointer == clang::Type::Pointer, "");
323static_assert((clang::Type::TypeClass)ZigClangType_BlockPointer == clang::Type::BlockPointer, "");
324static_assert((clang::Type::TypeClass)ZigClangType_LValueReference == clang::Type::LValueReference, "");
325static_assert((clang::Type::TypeClass)ZigClangType_RValueReference == clang::Type::RValueReference, "");
326static_assert((clang::Type::TypeClass)ZigClangType_MemberPointer == clang::Type::MemberPointer, "");
327static_assert((clang::Type::TypeClass)ZigClangType_ConstantArray == clang::Type::ConstantArray, "");
328static_assert((clang::Type::TypeClass)ZigClangType_IncompleteArray == clang::Type::IncompleteArray, "");
329static_assert((clang::Type::TypeClass)ZigClangType_VariableArray == clang::Type::VariableArray, "");
330static_assert((clang::Type::TypeClass)ZigClangType_DependentSizedArray == clang::Type::DependentSizedArray, "");
331static_assert((clang::Type::TypeClass)ZigClangType_DependentSizedExtVector == clang::Type::DependentSizedExtVector, "");
332static_assert((clang::Type::TypeClass)ZigClangType_DependentAddressSpace == clang::Type::DependentAddressSpace, "");
333static_assert((clang::Type::TypeClass)ZigClangType_Vector == clang::Type::Vector, "");
334static_assert((clang::Type::TypeClass)ZigClangType_DependentVector == clang::Type::DependentVector, "");
335static_assert((clang::Type::TypeClass)ZigClangType_ExtVector == clang::Type::ExtVector, "");
336static_assert((clang::Type::TypeClass)ZigClangType_FunctionProto == clang::Type::FunctionProto, "");
337static_assert((clang::Type::TypeClass)ZigClangType_FunctionNoProto == clang::Type::FunctionNoProto, "");
338static_assert((clang::Type::TypeClass)ZigClangType_UnresolvedUsing == clang::Type::UnresolvedUsing, "");
339static_assert((clang::Type::TypeClass)ZigClangType_Paren == clang::Type::Paren, "");
340static_assert((clang::Type::TypeClass)ZigClangType_Typedef == clang::Type::Typedef, "");
341static_assert((clang::Type::TypeClass)ZigClangType_Adjusted == clang::Type::Adjusted, "");
342static_assert((clang::Type::TypeClass)ZigClangType_Decayed == clang::Type::Decayed, "");
343static_assert((clang::Type::TypeClass)ZigClangType_TypeOfExpr == clang::Type::TypeOfExpr, "");
344static_assert((clang::Type::TypeClass)ZigClangType_TypeOf == clang::Type::TypeOf, "");
345static_assert((clang::Type::TypeClass)ZigClangType_Decltype == clang::Type::Decltype, "");
346static_assert((clang::Type::TypeClass)ZigClangType_UnaryTransform == clang::Type::UnaryTransform, "");
347static_assert((clang::Type::TypeClass)ZigClangType_Record == clang::Type::Record, "");
348static_assert((clang::Type::TypeClass)ZigClangType_Enum == clang::Type::Enum, "");
349static_assert((clang::Type::TypeClass)ZigClangType_Elaborated == clang::Type::Elaborated, "");
350static_assert((clang::Type::TypeClass)ZigClangType_Attributed == clang::Type::Attributed, "");
351static_assert((clang::Type::TypeClass)ZigClangType_TemplateTypeParm == clang::Type::TemplateTypeParm, "");
352static_assert((clang::Type::TypeClass)ZigClangType_SubstTemplateTypeParm == clang::Type::SubstTemplateTypeParm, "");
353static_assert((clang::Type::TypeClass)ZigClangType_SubstTemplateTypeParmPack == clang::Type::SubstTemplateTypeParmPack, "");
354static_assert((clang::Type::TypeClass)ZigClangType_TemplateSpecialization == clang::Type::TemplateSpecialization, "");
355static_assert((clang::Type::TypeClass)ZigClangType_Auto == clang::Type::Auto, "");
356static_assert((clang::Type::TypeClass)ZigClangType_DeducedTemplateSpecialization == clang::Type::DeducedTemplateSpecialization, "");
357static_assert((clang::Type::TypeClass)ZigClangType_InjectedClassName == clang::Type::InjectedClassName, "");
358static_assert((clang::Type::TypeClass)ZigClangType_DependentName == clang::Type::DependentName, "");
359static_assert((clang::Type::TypeClass)ZigClangType_DependentTemplateSpecialization == clang::Type::DependentTemplateSpecialization, "");
360static_assert((clang::Type::TypeClass)ZigClangType_PackExpansion == clang::Type::PackExpansion, "");
361static_assert((clang::Type::TypeClass)ZigClangType_ObjCTypeParam == clang::Type::ObjCTypeParam, "");
362static_assert((clang::Type::TypeClass)ZigClangType_ObjCObject == clang::Type::ObjCObject, "");
363static_assert((clang::Type::TypeClass)ZigClangType_ObjCInterface == clang::Type::ObjCInterface, "");
364static_assert((clang::Type::TypeClass)ZigClangType_ObjCObjectPointer == clang::Type::ObjCObjectPointer, "");
365static_assert((clang::Type::TypeClass)ZigClangType_Pipe == clang::Type::Pipe, "");
366static_assert((clang::Type::TypeClass)ZigClangType_Atomic == clang::Type::Atomic, "");
367
368// Detect additions to the enum
369void ZigClang_detect_enum_StmtClass(clang::Stmt::StmtClass x) {
370 switch (x) {
371 case clang::Stmt::NoStmtClass:
372 case clang::Stmt::NullStmtClass:
373 case clang::Stmt::CompoundStmtClass:
374 case clang::Stmt::LabelStmtClass:
375 case clang::Stmt::AttributedStmtClass:
376 case clang::Stmt::IfStmtClass:
377 case clang::Stmt::SwitchStmtClass:
378 case clang::Stmt::WhileStmtClass:
379 case clang::Stmt::DoStmtClass:
380 case clang::Stmt::ForStmtClass:
381 case clang::Stmt::GotoStmtClass:
382 case clang::Stmt::IndirectGotoStmtClass:
383 case clang::Stmt::ContinueStmtClass:
384 case clang::Stmt::BreakStmtClass:
385 case clang::Stmt::ReturnStmtClass:
386 case clang::Stmt::DeclStmtClass:
387 case clang::Stmt::CaseStmtClass:
388 case clang::Stmt::DefaultStmtClass:
389 case clang::Stmt::CapturedStmtClass:
390 case clang::Stmt::GCCAsmStmtClass:
391 case clang::Stmt::MSAsmStmtClass:
392 case clang::Stmt::ObjCAtTryStmtClass:
393 case clang::Stmt::ObjCAtCatchStmtClass:
394 case clang::Stmt::ObjCAtFinallyStmtClass:
395 case clang::Stmt::ObjCAtThrowStmtClass:
396 case clang::Stmt::ObjCAtSynchronizedStmtClass:
397 case clang::Stmt::ObjCForCollectionStmtClass:
398 case clang::Stmt::ObjCAutoreleasePoolStmtClass:
399 case clang::Stmt::CXXCatchStmtClass:
400 case clang::Stmt::CXXTryStmtClass:
401 case clang::Stmt::CXXForRangeStmtClass:
402 case clang::Stmt::CoroutineBodyStmtClass:
403 case clang::Stmt::CoreturnStmtClass:
404 case clang::Stmt::PredefinedExprClass:
405 case clang::Stmt::DeclRefExprClass:
406 case clang::Stmt::IntegerLiteralClass:
407 case clang::Stmt::FixedPointLiteralClass:
408 case clang::Stmt::FloatingLiteralClass:
409 case clang::Stmt::ImaginaryLiteralClass:
410 case clang::Stmt::StringLiteralClass:
411 case clang::Stmt::CharacterLiteralClass:
412 case clang::Stmt::ParenExprClass:
413 case clang::Stmt::UnaryOperatorClass:
414 case clang::Stmt::OffsetOfExprClass:
415 case clang::Stmt::UnaryExprOrTypeTraitExprClass:
416 case clang::Stmt::ArraySubscriptExprClass:
417 case clang::Stmt::OMPArraySectionExprClass:
418 case clang::Stmt::CallExprClass:
419 case clang::Stmt::MemberExprClass:
420 case clang::Stmt::BinaryOperatorClass:
421 case clang::Stmt::CompoundAssignOperatorClass:
422 case clang::Stmt::ConditionalOperatorClass:
423 case clang::Stmt::BinaryConditionalOperatorClass:
424 case clang::Stmt::ImplicitCastExprClass:
425 case clang::Stmt::CStyleCastExprClass:
426 case clang::Stmt::CompoundLiteralExprClass:
427 case clang::Stmt::ExtVectorElementExprClass:
428 case clang::Stmt::InitListExprClass:
429 case clang::Stmt::DesignatedInitExprClass:
430 case clang::Stmt::DesignatedInitUpdateExprClass:
431 case clang::Stmt::ImplicitValueInitExprClass:
432 case clang::Stmt::NoInitExprClass:
433 case clang::Stmt::ArrayInitLoopExprClass:
434 case clang::Stmt::ArrayInitIndexExprClass:
435 case clang::Stmt::ParenListExprClass:
436 case clang::Stmt::VAArgExprClass:
437 case clang::Stmt::GenericSelectionExprClass:
438 case clang::Stmt::PseudoObjectExprClass:
439 case clang::Stmt::ConstantExprClass:
440 case clang::Stmt::AtomicExprClass:
441 case clang::Stmt::AddrLabelExprClass:
442 case clang::Stmt::StmtExprClass:
443 case clang::Stmt::ChooseExprClass:
444 case clang::Stmt::GNUNullExprClass:
445 case clang::Stmt::CXXOperatorCallExprClass:
446 case clang::Stmt::CXXMemberCallExprClass:
447 case clang::Stmt::CXXStaticCastExprClass:
448 case clang::Stmt::CXXDynamicCastExprClass:
449 case clang::Stmt::CXXReinterpretCastExprClass:
450 case clang::Stmt::CXXConstCastExprClass:
451 case clang::Stmt::CXXFunctionalCastExprClass:
452 case clang::Stmt::CXXTypeidExprClass:
453 case clang::Stmt::UserDefinedLiteralClass:
454 case clang::Stmt::CXXBoolLiteralExprClass:
455 case clang::Stmt::CXXNullPtrLiteralExprClass:
456 case clang::Stmt::CXXThisExprClass:
457 case clang::Stmt::CXXThrowExprClass:
458 case clang::Stmt::CXXDefaultArgExprClass:
459 case clang::Stmt::CXXDefaultInitExprClass:
460 case clang::Stmt::CXXScalarValueInitExprClass:
461 case clang::Stmt::CXXStdInitializerListExprClass:
462 case clang::Stmt::CXXNewExprClass:
463 case clang::Stmt::CXXDeleteExprClass:
464 case clang::Stmt::CXXPseudoDestructorExprClass:
465 case clang::Stmt::TypeTraitExprClass:
466 case clang::Stmt::ArrayTypeTraitExprClass:
467 case clang::Stmt::ExpressionTraitExprClass:
468 case clang::Stmt::DependentScopeDeclRefExprClass:
469 case clang::Stmt::CXXConstructExprClass:
470 case clang::Stmt::CXXInheritedCtorInitExprClass:
471 case clang::Stmt::CXXBindTemporaryExprClass:
472 case clang::Stmt::ExprWithCleanupsClass:
473 case clang::Stmt::CXXTemporaryObjectExprClass:
474 case clang::Stmt::CXXUnresolvedConstructExprClass:
475 case clang::Stmt::CXXDependentScopeMemberExprClass:
476 case clang::Stmt::UnresolvedLookupExprClass:
477 case clang::Stmt::UnresolvedMemberExprClass:
478 case clang::Stmt::CXXNoexceptExprClass:
479 case clang::Stmt::PackExpansionExprClass:
480 case clang::Stmt::SizeOfPackExprClass:
481 case clang::Stmt::SubstNonTypeTemplateParmExprClass:
482 case clang::Stmt::SubstNonTypeTemplateParmPackExprClass:
483 case clang::Stmt::FunctionParmPackExprClass:
484 case clang::Stmt::MaterializeTemporaryExprClass:
485 case clang::Stmt::LambdaExprClass:
486 case clang::Stmt::CXXFoldExprClass:
487 case clang::Stmt::CoawaitExprClass:
488 case clang::Stmt::DependentCoawaitExprClass:
489 case clang::Stmt::CoyieldExprClass:
490 case clang::Stmt::ObjCStringLiteralClass:
491 case clang::Stmt::ObjCBoxedExprClass:
492 case clang::Stmt::ObjCArrayLiteralClass:
493 case clang::Stmt::ObjCDictionaryLiteralClass:
494 case clang::Stmt::ObjCEncodeExprClass:
495 case clang::Stmt::ObjCMessageExprClass:
496 case clang::Stmt::ObjCSelectorExprClass:
497 case clang::Stmt::ObjCProtocolExprClass:
498 case clang::Stmt::ObjCIvarRefExprClass:
499 case clang::Stmt::ObjCPropertyRefExprClass:
500 case clang::Stmt::ObjCIsaExprClass:
501 case clang::Stmt::ObjCIndirectCopyRestoreExprClass:
502 case clang::Stmt::ObjCBoolLiteralExprClass:
503 case clang::Stmt::ObjCSubscriptRefExprClass:
504 case clang::Stmt::ObjCAvailabilityCheckExprClass:
505 case clang::Stmt::ObjCBridgedCastExprClass:
506 case clang::Stmt::CUDAKernelCallExprClass:
507 case clang::Stmt::ShuffleVectorExprClass:
508 case clang::Stmt::ConvertVectorExprClass:
509 case clang::Stmt::BlockExprClass:
510 case clang::Stmt::OpaqueValueExprClass:
511 case clang::Stmt::TypoExprClass:
512 case clang::Stmt::MSPropertyRefExprClass:
513 case clang::Stmt::MSPropertySubscriptExprClass:
514 case clang::Stmt::CXXUuidofExprClass:
515 case clang::Stmt::SEHTryStmtClass:
516 case clang::Stmt::SEHExceptStmtClass:
517 case clang::Stmt::SEHFinallyStmtClass:
518 case clang::Stmt::SEHLeaveStmtClass:
519 case clang::Stmt::MSDependentExistsStmtClass:
520 case clang::Stmt::AsTypeExprClass:
521 case clang::Stmt::OMPParallelDirectiveClass:
522 case clang::Stmt::OMPSimdDirectiveClass:
523 case clang::Stmt::OMPForDirectiveClass:
524 case clang::Stmt::OMPForSimdDirectiveClass:
525 case clang::Stmt::OMPSectionsDirectiveClass:
526 case clang::Stmt::OMPSectionDirectiveClass:
527 case clang::Stmt::OMPSingleDirectiveClass:
528 case clang::Stmt::OMPMasterDirectiveClass:
529 case clang::Stmt::OMPCriticalDirectiveClass:
530 case clang::Stmt::OMPParallelForDirectiveClass:
531 case clang::Stmt::OMPParallelForSimdDirectiveClass:
532 case clang::Stmt::OMPParallelSectionsDirectiveClass:
533 case clang::Stmt::OMPTaskDirectiveClass:
534 case clang::Stmt::OMPTaskyieldDirectiveClass:
535 case clang::Stmt::OMPBarrierDirectiveClass:
536 case clang::Stmt::OMPTaskwaitDirectiveClass:
537 case clang::Stmt::OMPTaskgroupDirectiveClass:
538 case clang::Stmt::OMPFlushDirectiveClass:
539 case clang::Stmt::OMPOrderedDirectiveClass:
540 case clang::Stmt::OMPAtomicDirectiveClass:
541 case clang::Stmt::OMPTargetDirectiveClass:
542 case clang::Stmt::OMPTargetDataDirectiveClass:
543 case clang::Stmt::OMPTargetEnterDataDirectiveClass:
544 case clang::Stmt::OMPTargetExitDataDirectiveClass:
545 case clang::Stmt::OMPTargetParallelDirectiveClass:
546 case clang::Stmt::OMPTargetParallelForDirectiveClass:
547 case clang::Stmt::OMPTargetUpdateDirectiveClass:
548 case clang::Stmt::OMPTeamsDirectiveClass:
549 case clang::Stmt::OMPCancellationPointDirectiveClass:
550 case clang::Stmt::OMPCancelDirectiveClass:
551 case clang::Stmt::OMPTaskLoopDirectiveClass:
552 case clang::Stmt::OMPTaskLoopSimdDirectiveClass:
553 case clang::Stmt::OMPDistributeDirectiveClass:
554 case clang::Stmt::OMPDistributeParallelForDirectiveClass:
555 case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass:
556 case clang::Stmt::OMPDistributeSimdDirectiveClass:
557 case clang::Stmt::OMPTargetParallelForSimdDirectiveClass:
558 case clang::Stmt::OMPTargetSimdDirectiveClass:
559 case clang::Stmt::OMPTeamsDistributeDirectiveClass:
560 case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass:
561 case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
562 case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass:
563 case clang::Stmt::OMPTargetTeamsDirectiveClass:
564 case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass:
565 case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
566 case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
567 case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
568 break;
569 }
570}
571
572static_assert((clang::Stmt::StmtClass)ZigClangStmt_NoStmtClass == clang::Stmt::NoStmtClass, "");
573static_assert((clang::Stmt::StmtClass)ZigClangStmt_NullStmtClass == clang::Stmt::NullStmtClass, "");
574static_assert((clang::Stmt::StmtClass)ZigClangStmt_CompoundStmtClass == clang::Stmt::CompoundStmtClass, "");
575static_assert((clang::Stmt::StmtClass)ZigClangStmt_LabelStmtClass == clang::Stmt::LabelStmtClass, "");
576static_assert((clang::Stmt::StmtClass)ZigClangStmt_AttributedStmtClass == clang::Stmt::AttributedStmtClass, "");
577static_assert((clang::Stmt::StmtClass)ZigClangStmt_IfStmtClass == clang::Stmt::IfStmtClass, "");
578static_assert((clang::Stmt::StmtClass)ZigClangStmt_SwitchStmtClass == clang::Stmt::SwitchStmtClass, "");
579static_assert((clang::Stmt::StmtClass)ZigClangStmt_WhileStmtClass == clang::Stmt::WhileStmtClass, "");
580static_assert((clang::Stmt::StmtClass)ZigClangStmt_DoStmtClass == clang::Stmt::DoStmtClass, "");
581static_assert((clang::Stmt::StmtClass)ZigClangStmt_ForStmtClass == clang::Stmt::ForStmtClass, "");
582static_assert((clang::Stmt::StmtClass)ZigClangStmt_GotoStmtClass == clang::Stmt::GotoStmtClass, "");
583static_assert((clang::Stmt::StmtClass)ZigClangStmt_IndirectGotoStmtClass == clang::Stmt::IndirectGotoStmtClass, "");
584static_assert((clang::Stmt::StmtClass)ZigClangStmt_ContinueStmtClass == clang::Stmt::ContinueStmtClass, "");
585static_assert((clang::Stmt::StmtClass)ZigClangStmt_BreakStmtClass == clang::Stmt::BreakStmtClass, "");
586static_assert((clang::Stmt::StmtClass)ZigClangStmt_ReturnStmtClass == clang::Stmt::ReturnStmtClass, "");
587static_assert((clang::Stmt::StmtClass)ZigClangStmt_DeclStmtClass == clang::Stmt::DeclStmtClass, "");
588static_assert((clang::Stmt::StmtClass)ZigClangStmt_CaseStmtClass == clang::Stmt::CaseStmtClass, "");
589static_assert((clang::Stmt::StmtClass)ZigClangStmt_DefaultStmtClass == clang::Stmt::DefaultStmtClass, "");
590static_assert((clang::Stmt::StmtClass)ZigClangStmt_CapturedStmtClass == clang::Stmt::CapturedStmtClass, "");
591static_assert((clang::Stmt::StmtClass)ZigClangStmt_GCCAsmStmtClass == clang::Stmt::GCCAsmStmtClass, "");
592static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSAsmStmtClass == clang::Stmt::MSAsmStmtClass, "");
593static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtTryStmtClass == clang::Stmt::ObjCAtTryStmtClass, "");
594static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtCatchStmtClass == clang::Stmt::ObjCAtCatchStmtClass, "");
595static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtFinallyStmtClass == clang::Stmt::ObjCAtFinallyStmtClass, "");
596static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtThrowStmtClass == clang::Stmt::ObjCAtThrowStmtClass, "");
597static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtSynchronizedStmtClass == clang::Stmt::ObjCAtSynchronizedStmtClass, "");
598static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCForCollectionStmtClass == clang::Stmt::ObjCForCollectionStmtClass, "");
599static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAutoreleasePoolStmtClass == clang::Stmt::ObjCAutoreleasePoolStmtClass, "");
600static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXCatchStmtClass == clang::Stmt::CXXCatchStmtClass, "");
601static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXTryStmtClass == clang::Stmt::CXXTryStmtClass, "");
602static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXForRangeStmtClass == clang::Stmt::CXXForRangeStmtClass, "");
603static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoroutineBodyStmtClass == clang::Stmt::CoroutineBodyStmtClass, "");
604static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoreturnStmtClass == clang::Stmt::CoreturnStmtClass, "");
605static_assert((clang::Stmt::StmtClass)ZigClangStmt_PredefinedExprClass == clang::Stmt::PredefinedExprClass, "");
606static_assert((clang::Stmt::StmtClass)ZigClangStmt_DeclRefExprClass == clang::Stmt::DeclRefExprClass, "");
607static_assert((clang::Stmt::StmtClass)ZigClangStmt_IntegerLiteralClass == clang::Stmt::IntegerLiteralClass, "");
608static_assert((clang::Stmt::StmtClass)ZigClangStmt_FixedPointLiteralClass == clang::Stmt::FixedPointLiteralClass, "");
609static_assert((clang::Stmt::StmtClass)ZigClangStmt_FloatingLiteralClass == clang::Stmt::FloatingLiteralClass, "");
610static_assert((clang::Stmt::StmtClass)ZigClangStmt_ImaginaryLiteralClass == clang::Stmt::ImaginaryLiteralClass, "");
611static_assert((clang::Stmt::StmtClass)ZigClangStmt_StringLiteralClass == clang::Stmt::StringLiteralClass, "");
612static_assert((clang::Stmt::StmtClass)ZigClangStmt_CharacterLiteralClass == clang::Stmt::CharacterLiteralClass, "");
613static_assert((clang::Stmt::StmtClass)ZigClangStmt_ParenExprClass == clang::Stmt::ParenExprClass, "");
614static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnaryOperatorClass == clang::Stmt::UnaryOperatorClass, "");
615static_assert((clang::Stmt::StmtClass)ZigClangStmt_OffsetOfExprClass == clang::Stmt::OffsetOfExprClass, "");
616static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnaryExprOrTypeTraitExprClass == clang::Stmt::UnaryExprOrTypeTraitExprClass, "");
617static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArraySubscriptExprClass == clang::Stmt::ArraySubscriptExprClass, "");
618static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPArraySectionExprClass == clang::Stmt::OMPArraySectionExprClass, "");
619static_assert((clang::Stmt::StmtClass)ZigClangStmt_CallExprClass == clang::Stmt::CallExprClass, "");
620static_assert((clang::Stmt::StmtClass)ZigClangStmt_MemberExprClass == clang::Stmt::MemberExprClass, "");
621static_assert((clang::Stmt::StmtClass)ZigClangStmt_BinaryOperatorClass == clang::Stmt::BinaryOperatorClass, "");
622static_assert((clang::Stmt::StmtClass)ZigClangStmt_CompoundAssignOperatorClass == clang::Stmt::CompoundAssignOperatorClass, "");
623static_assert((clang::Stmt::StmtClass)ZigClangStmt_ConditionalOperatorClass == clang::Stmt::ConditionalOperatorClass, "");
624static_assert((clang::Stmt::StmtClass)ZigClangStmt_BinaryConditionalOperatorClass == clang::Stmt::BinaryConditionalOperatorClass, "");
625static_assert((clang::Stmt::StmtClass)ZigClangStmt_ImplicitCastExprClass == clang::Stmt::ImplicitCastExprClass, "");
626static_assert((clang::Stmt::StmtClass)ZigClangStmt_CStyleCastExprClass == clang::Stmt::CStyleCastExprClass, "");
627static_assert((clang::Stmt::StmtClass)ZigClangStmt_CompoundLiteralExprClass == clang::Stmt::CompoundLiteralExprClass, "");
628static_assert((clang::Stmt::StmtClass)ZigClangStmt_ExtVectorElementExprClass == clang::Stmt::ExtVectorElementExprClass, "");
629static_assert((clang::Stmt::StmtClass)ZigClangStmt_InitListExprClass == clang::Stmt::InitListExprClass, "");
630static_assert((clang::Stmt::StmtClass)ZigClangStmt_DesignatedInitExprClass == clang::Stmt::DesignatedInitExprClass, "");
631static_assert((clang::Stmt::StmtClass)ZigClangStmt_DesignatedInitUpdateExprClass == clang::Stmt::DesignatedInitUpdateExprClass, "");
632static_assert((clang::Stmt::StmtClass)ZigClangStmt_ImplicitValueInitExprClass == clang::Stmt::ImplicitValueInitExprClass, "");
633static_assert((clang::Stmt::StmtClass)ZigClangStmt_NoInitExprClass == clang::Stmt::NoInitExprClass, "");
634static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArrayInitLoopExprClass == clang::Stmt::ArrayInitLoopExprClass, "");
635static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArrayInitIndexExprClass == clang::Stmt::ArrayInitIndexExprClass, "");
636static_assert((clang::Stmt::StmtClass)ZigClangStmt_ParenListExprClass == clang::Stmt::ParenListExprClass, "");
637static_assert((clang::Stmt::StmtClass)ZigClangStmt_VAArgExprClass == clang::Stmt::VAArgExprClass, "");
638static_assert((clang::Stmt::StmtClass)ZigClangStmt_GenericSelectionExprClass == clang::Stmt::GenericSelectionExprClass, "");
639static_assert((clang::Stmt::StmtClass)ZigClangStmt_PseudoObjectExprClass == clang::Stmt::PseudoObjectExprClass, "");
640static_assert((clang::Stmt::StmtClass)ZigClangStmt_ConstantExprClass == clang::Stmt::ConstantExprClass, "");
641static_assert((clang::Stmt::StmtClass)ZigClangStmt_AtomicExprClass == clang::Stmt::AtomicExprClass, "");
642static_assert((clang::Stmt::StmtClass)ZigClangStmt_AddrLabelExprClass == clang::Stmt::AddrLabelExprClass, "");
643static_assert((clang::Stmt::StmtClass)ZigClangStmt_StmtExprClass == clang::Stmt::StmtExprClass, "");
644static_assert((clang::Stmt::StmtClass)ZigClangStmt_ChooseExprClass == clang::Stmt::ChooseExprClass, "");
645static_assert((clang::Stmt::StmtClass)ZigClangStmt_GNUNullExprClass == clang::Stmt::GNUNullExprClass, "");
646static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXOperatorCallExprClass == clang::Stmt::CXXOperatorCallExprClass, "");
647static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXMemberCallExprClass == clang::Stmt::CXXMemberCallExprClass, "");
648static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXStaticCastExprClass == clang::Stmt::CXXStaticCastExprClass, "");
649static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDynamicCastExprClass == clang::Stmt::CXXDynamicCastExprClass, "");
650static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXReinterpretCastExprClass == clang::Stmt::CXXReinterpretCastExprClass, "");
651static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXConstCastExprClass == clang::Stmt::CXXConstCastExprClass, "");
652static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXFunctionalCastExprClass == clang::Stmt::CXXFunctionalCastExprClass, "");
653static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXTypeidExprClass == clang::Stmt::CXXTypeidExprClass, "");
654static_assert((clang::Stmt::StmtClass)ZigClangStmt_UserDefinedLiteralClass == clang::Stmt::UserDefinedLiteralClass, "");
655static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXBoolLiteralExprClass == clang::Stmt::CXXBoolLiteralExprClass, "");
656static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXNullPtrLiteralExprClass == clang::Stmt::CXXNullPtrLiteralExprClass, "");
657static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXThisExprClass == clang::Stmt::CXXThisExprClass, "");
658static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXThrowExprClass == clang::Stmt::CXXThrowExprClass, "");
659static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDefaultArgExprClass == clang::Stmt::CXXDefaultArgExprClass, "");
660static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDefaultInitExprClass == clang::Stmt::CXXDefaultInitExprClass, "");
661static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXScalarValueInitExprClass == clang::Stmt::CXXScalarValueInitExprClass, "");
662static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXStdInitializerListExprClass == clang::Stmt::CXXStdInitializerListExprClass, "");
663static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXNewExprClass == clang::Stmt::CXXNewExprClass, "");
664static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDeleteExprClass == clang::Stmt::CXXDeleteExprClass, "");
665static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXPseudoDestructorExprClass == clang::Stmt::CXXPseudoDestructorExprClass, "");
666static_assert((clang::Stmt::StmtClass)ZigClangStmt_TypeTraitExprClass == clang::Stmt::TypeTraitExprClass, "");
667static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArrayTypeTraitExprClass == clang::Stmt::ArrayTypeTraitExprClass, "");
668static_assert((clang::Stmt::StmtClass)ZigClangStmt_ExpressionTraitExprClass == clang::Stmt::ExpressionTraitExprClass, "");
669static_assert((clang::Stmt::StmtClass)ZigClangStmt_DependentScopeDeclRefExprClass == clang::Stmt::DependentScopeDeclRefExprClass, "");
670static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXConstructExprClass == clang::Stmt::CXXConstructExprClass, "");
671static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXInheritedCtorInitExprClass == clang::Stmt::CXXInheritedCtorInitExprClass, "");
672static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXBindTemporaryExprClass == clang::Stmt::CXXBindTemporaryExprClass, "");
673static_assert((clang::Stmt::StmtClass)ZigClangStmt_ExprWithCleanupsClass == clang::Stmt::ExprWithCleanupsClass, "");
674static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXTemporaryObjectExprClass == clang::Stmt::CXXTemporaryObjectExprClass, "");
675static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXUnresolvedConstructExprClass == clang::Stmt::CXXUnresolvedConstructExprClass, "");
676static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDependentScopeMemberExprClass == clang::Stmt::CXXDependentScopeMemberExprClass, "");
677static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnresolvedLookupExprClass == clang::Stmt::UnresolvedLookupExprClass, "");
678static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnresolvedMemberExprClass == clang::Stmt::UnresolvedMemberExprClass, "");
679static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXNoexceptExprClass == clang::Stmt::CXXNoexceptExprClass, "");
680static_assert((clang::Stmt::StmtClass)ZigClangStmt_PackExpansionExprClass == clang::Stmt::PackExpansionExprClass, "");
681static_assert((clang::Stmt::StmtClass)ZigClangStmt_SizeOfPackExprClass == clang::Stmt::SizeOfPackExprClass, "");
682static_assert((clang::Stmt::StmtClass)ZigClangStmt_SubstNonTypeTemplateParmExprClass == clang::Stmt::SubstNonTypeTemplateParmExprClass, "");
683static_assert((clang::Stmt::StmtClass)ZigClangStmt_SubstNonTypeTemplateParmPackExprClass == clang::Stmt::SubstNonTypeTemplateParmPackExprClass, "");
684static_assert((clang::Stmt::StmtClass)ZigClangStmt_FunctionParmPackExprClass == clang::Stmt::FunctionParmPackExprClass, "");
685static_assert((clang::Stmt::StmtClass)ZigClangStmt_MaterializeTemporaryExprClass == clang::Stmt::MaterializeTemporaryExprClass, "");
686static_assert((clang::Stmt::StmtClass)ZigClangStmt_LambdaExprClass == clang::Stmt::LambdaExprClass, "");
687static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXFoldExprClass == clang::Stmt::CXXFoldExprClass, "");
688static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoawaitExprClass == clang::Stmt::CoawaitExprClass, "");
689static_assert((clang::Stmt::StmtClass)ZigClangStmt_DependentCoawaitExprClass == clang::Stmt::DependentCoawaitExprClass, "");
690static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoyieldExprClass == clang::Stmt::CoyieldExprClass, "");
691static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCStringLiteralClass == clang::Stmt::ObjCStringLiteralClass, "");
692static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCBoxedExprClass == clang::Stmt::ObjCBoxedExprClass, "");
693static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCArrayLiteralClass == clang::Stmt::ObjCArrayLiteralClass, "");
694static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCDictionaryLiteralClass == clang::Stmt::ObjCDictionaryLiteralClass, "");
695static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCEncodeExprClass == clang::Stmt::ObjCEncodeExprClass, "");
696static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCMessageExprClass == clang::Stmt::ObjCMessageExprClass, "");
697static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCSelectorExprClass == clang::Stmt::ObjCSelectorExprClass, "");
698static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCProtocolExprClass == clang::Stmt::ObjCProtocolExprClass, "");
699static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCIvarRefExprClass == clang::Stmt::ObjCIvarRefExprClass, "");
700static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCPropertyRefExprClass == clang::Stmt::ObjCPropertyRefExprClass, "");
701static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCIsaExprClass == clang::Stmt::ObjCIsaExprClass, "");
702static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCIndirectCopyRestoreExprClass == clang::Stmt::ObjCIndirectCopyRestoreExprClass, "");
703static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCBoolLiteralExprClass == clang::Stmt::ObjCBoolLiteralExprClass, "");
704static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCSubscriptRefExprClass == clang::Stmt::ObjCSubscriptRefExprClass, "");
705static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAvailabilityCheckExprClass == clang::Stmt::ObjCAvailabilityCheckExprClass, "");
706static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCBridgedCastExprClass == clang::Stmt::ObjCBridgedCastExprClass, "");
707static_assert((clang::Stmt::StmtClass)ZigClangStmt_CUDAKernelCallExprClass == clang::Stmt::CUDAKernelCallExprClass, "");
708static_assert((clang::Stmt::StmtClass)ZigClangStmt_ShuffleVectorExprClass == clang::Stmt::ShuffleVectorExprClass, "");
709static_assert((clang::Stmt::StmtClass)ZigClangStmt_ConvertVectorExprClass == clang::Stmt::ConvertVectorExprClass, "");
710static_assert((clang::Stmt::StmtClass)ZigClangStmt_BlockExprClass == clang::Stmt::BlockExprClass, "");
711static_assert((clang::Stmt::StmtClass)ZigClangStmt_OpaqueValueExprClass == clang::Stmt::OpaqueValueExprClass, "");
712static_assert((clang::Stmt::StmtClass)ZigClangStmt_TypoExprClass == clang::Stmt::TypoExprClass, "");
713static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSPropertyRefExprClass == clang::Stmt::MSPropertyRefExprClass, "");
714static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSPropertySubscriptExprClass == clang::Stmt::MSPropertySubscriptExprClass, "");
715static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXUuidofExprClass == clang::Stmt::CXXUuidofExprClass, "");
716static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHTryStmtClass == clang::Stmt::SEHTryStmtClass, "");
717static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHExceptStmtClass == clang::Stmt::SEHExceptStmtClass, "");
718static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHFinallyStmtClass == clang::Stmt::SEHFinallyStmtClass, "");
719static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHLeaveStmtClass == clang::Stmt::SEHLeaveStmtClass, "");
720static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSDependentExistsStmtClass == clang::Stmt::MSDependentExistsStmtClass, "");
721static_assert((clang::Stmt::StmtClass)ZigClangStmt_AsTypeExprClass == clang::Stmt::AsTypeExprClass, "");
722static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelDirectiveClass == clang::Stmt::OMPParallelDirectiveClass, "");
723static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSimdDirectiveClass == clang::Stmt::OMPSimdDirectiveClass, "");
724static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPForDirectiveClass == clang::Stmt::OMPForDirectiveClass, "");
725static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPForSimdDirectiveClass == clang::Stmt::OMPForSimdDirectiveClass, "");
726static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSectionsDirectiveClass == clang::Stmt::OMPSectionsDirectiveClass, "");
727static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSectionDirectiveClass == clang::Stmt::OMPSectionDirectiveClass, "");
728static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSingleDirectiveClass == clang::Stmt::OMPSingleDirectiveClass, "");
729static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMasterDirectiveClass == clang::Stmt::OMPMasterDirectiveClass, "");
730static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPCriticalDirectiveClass == clang::Stmt::OMPCriticalDirectiveClass, "");
731static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelForDirectiveClass == clang::Stmt::OMPParallelForDirectiveClass, "");
732static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelForSimdDirectiveClass == clang::Stmt::OMPParallelForSimdDirectiveClass, "");
733static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelSectionsDirectiveClass == clang::Stmt::OMPParallelSectionsDirectiveClass, "");
734static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskDirectiveClass == clang::Stmt::OMPTaskDirectiveClass, "");
735static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskyieldDirectiveClass == clang::Stmt::OMPTaskyieldDirectiveClass, "");
736static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPBarrierDirectiveClass == clang::Stmt::OMPBarrierDirectiveClass, "");
737static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskwaitDirectiveClass == clang::Stmt::OMPTaskwaitDirectiveClass, "");
738static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskgroupDirectiveClass == clang::Stmt::OMPTaskgroupDirectiveClass, "");
739static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPFlushDirectiveClass == clang::Stmt::OMPFlushDirectiveClass, "");
740static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPOrderedDirectiveClass == clang::Stmt::OMPOrderedDirectiveClass, "");
741static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPAtomicDirectiveClass == clang::Stmt::OMPAtomicDirectiveClass, "");
742static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetDirectiveClass == clang::Stmt::OMPTargetDirectiveClass, "");
743static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetDataDirectiveClass == clang::Stmt::OMPTargetDataDirectiveClass, "");
744static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetEnterDataDirectiveClass == clang::Stmt::OMPTargetEnterDataDirectiveClass, "");
745static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetExitDataDirectiveClass == clang::Stmt::OMPTargetExitDataDirectiveClass, "");
746static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelDirectiveClass == clang::Stmt::OMPTargetParallelDirectiveClass, "");
747static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelForDirectiveClass == clang::Stmt::OMPTargetParallelForDirectiveClass, "");
748static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetUpdateDirectiveClass == clang::Stmt::OMPTargetUpdateDirectiveClass, "");
749static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDirectiveClass == clang::Stmt::OMPTeamsDirectiveClass, "");
750static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPCancellationPointDirectiveClass == clang::Stmt::OMPCancellationPointDirectiveClass, "");
751static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPCancelDirectiveClass == clang::Stmt::OMPCancelDirectiveClass, "");
752static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskLoopDirectiveClass == clang::Stmt::OMPTaskLoopDirectiveClass, "");
753static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskLoopSimdDirectiveClass == clang::Stmt::OMPTaskLoopSimdDirectiveClass, "");
754static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeDirectiveClass == clang::Stmt::OMPDistributeDirectiveClass, "");
755static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeParallelForDirectiveClass == clang::Stmt::OMPDistributeParallelForDirectiveClass, "");
756static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPDistributeParallelForSimdDirectiveClass, "");
757static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeSimdDirectiveClass == clang::Stmt::OMPDistributeSimdDirectiveClass, "");
758static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelForSimdDirectiveClass == clang::Stmt::OMPTargetParallelForSimdDirectiveClass, "");
759static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetSimdDirectiveClass == clang::Stmt::OMPTargetSimdDirectiveClass, "");
760static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeDirectiveClass == clang::Stmt::OMPTeamsDistributeDirectiveClass, "");
761static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass == clang::Stmt::OMPTeamsDistributeSimdDirectiveClass, "");
762static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass, "");
763static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass == clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass, "");
764static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDirectiveClass == clang::Stmt::OMPTargetTeamsDirectiveClass, "");
765static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeDirectiveClass, "");
766static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass, "");
767static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass, "");
768static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass, "");
769
770void ZigClang_detect_enum_APValueKind(clang::APValue::ValueKind x) {
771 switch (x) {
772 case clang::APValue::Uninitialized:
773 case clang::APValue::Int:
774 case clang::APValue::Float:
775 case clang::APValue::ComplexInt:
776 case clang::APValue::ComplexFloat:
777 case clang::APValue::LValue:
778 case clang::APValue::Vector:
779 case clang::APValue::Array:
780 case clang::APValue::Struct:
781 case clang::APValue::Union:
782 case clang::APValue::MemberPointer:
783 case clang::APValue::AddrLabelDiff:
784 break;
785 }
786}
787
788static_assert((clang::APValue::ValueKind)ZigClangAPValueUninitialized == clang::APValue::Uninitialized, "");
789static_assert((clang::APValue::ValueKind)ZigClangAPValueInt == clang::APValue::Int, "");
790static_assert((clang::APValue::ValueKind)ZigClangAPValueFloat == clang::APValue::Float, "");
791static_assert((clang::APValue::ValueKind)ZigClangAPValueComplexInt == clang::APValue::ComplexInt, "");
792static_assert((clang::APValue::ValueKind)ZigClangAPValueComplexFloat == clang::APValue::ComplexFloat, "");
793static_assert((clang::APValue::ValueKind)ZigClangAPValueLValue == clang::APValue::LValue, "");
794static_assert((clang::APValue::ValueKind)ZigClangAPValueVector == clang::APValue::Vector, "");
795static_assert((clang::APValue::ValueKind)ZigClangAPValueArray == clang::APValue::Array, "");
796static_assert((clang::APValue::ValueKind)ZigClangAPValueStruct == clang::APValue::Struct, "");
797static_assert((clang::APValue::ValueKind)ZigClangAPValueUnion == clang::APValue::Union, "");
798static_assert((clang::APValue::ValueKind)ZigClangAPValueMemberPointer == clang::APValue::MemberPointer, "");
799static_assert((clang::APValue::ValueKind)ZigClangAPValueAddrLabelDiff == clang::APValue::AddrLabelDiff, "");
800
801
802void ZigClang_detect_enum_DeclKind(clang::Decl::Kind x) {
803 switch (x) {
804 case clang::Decl::AccessSpec:
805 case clang::Decl::Block:
806 case clang::Decl::Captured:
807 case clang::Decl::ClassScopeFunctionSpecialization:
808 case clang::Decl::Empty:
809 case clang::Decl::Export:
810 case clang::Decl::ExternCContext:
811 case clang::Decl::FileScopeAsm:
812 case clang::Decl::Friend:
813 case clang::Decl::FriendTemplate:
814 case clang::Decl::Import:
815 case clang::Decl::LinkageSpec:
816 case clang::Decl::Label:
817 case clang::Decl::Namespace:
818 case clang::Decl::NamespaceAlias:
819 case clang::Decl::ObjCCompatibleAlias:
820 case clang::Decl::ObjCCategory:
821 case clang::Decl::ObjCCategoryImpl:
822 case clang::Decl::ObjCImplementation:
823 case clang::Decl::ObjCInterface:
824 case clang::Decl::ObjCProtocol:
825 case clang::Decl::ObjCMethod:
826 case clang::Decl::ObjCProperty:
827 case clang::Decl::BuiltinTemplate:
828 case clang::Decl::ClassTemplate:
829 case clang::Decl::FunctionTemplate:
830 case clang::Decl::TypeAliasTemplate:
831 case clang::Decl::VarTemplate:
832 case clang::Decl::TemplateTemplateParm:
833 case clang::Decl::Enum:
834 case clang::Decl::Record:
835 case clang::Decl::CXXRecord:
836 case clang::Decl::ClassTemplateSpecialization:
837 case clang::Decl::ClassTemplatePartialSpecialization:
838 case clang::Decl::TemplateTypeParm:
839 case clang::Decl::ObjCTypeParam:
840 case clang::Decl::TypeAlias:
841 case clang::Decl::Typedef:
842 case clang::Decl::UnresolvedUsingTypename:
843 case clang::Decl::Using:
844 case clang::Decl::UsingDirective:
845 case clang::Decl::UsingPack:
846 case clang::Decl::UsingShadow:
847 case clang::Decl::ConstructorUsingShadow:
848 case clang::Decl::Binding:
849 case clang::Decl::Field:
850 case clang::Decl::ObjCAtDefsField:
851 case clang::Decl::ObjCIvar:
852 case clang::Decl::Function:
853 case clang::Decl::CXXDeductionGuide:
854 case clang::Decl::CXXMethod:
855 case clang::Decl::CXXConstructor:
856 case clang::Decl::CXXConversion:
857 case clang::Decl::CXXDestructor:
858 case clang::Decl::MSProperty:
859 case clang::Decl::NonTypeTemplateParm:
860 case clang::Decl::Var:
861 case clang::Decl::Decomposition:
862 case clang::Decl::ImplicitParam:
863 case clang::Decl::OMPCapturedExpr:
864 case clang::Decl::ParmVar:
865 case clang::Decl::VarTemplateSpecialization:
866 case clang::Decl::VarTemplatePartialSpecialization:
867 case clang::Decl::EnumConstant:
868 case clang::Decl::IndirectField:
869 case clang::Decl::OMPDeclareReduction:
870 case clang::Decl::UnresolvedUsingValue:
871 case clang::Decl::OMPRequires:
872 case clang::Decl::OMPThreadPrivate:
873 case clang::Decl::ObjCPropertyImpl:
874 case clang::Decl::PragmaComment:
875 case clang::Decl::PragmaDetectMismatch:
876 case clang::Decl::StaticAssert:
877 case clang::Decl::TranslationUnit:
878 break;
879 }
880}
881
882static_assert((clang::Decl::Kind)ZigClangDeclAccessSpec == clang::Decl::AccessSpec, "");
883static_assert((clang::Decl::Kind)ZigClangDeclBlock == clang::Decl::Block, "");
884static_assert((clang::Decl::Kind)ZigClangDeclCaptured == clang::Decl::Captured, "");
885static_assert((clang::Decl::Kind)ZigClangDeclClassScopeFunctionSpecialization == clang::Decl::ClassScopeFunctionSpecialization, "");
886static_assert((clang::Decl::Kind)ZigClangDeclEmpty == clang::Decl::Empty, "");
887static_assert((clang::Decl::Kind)ZigClangDeclExport == clang::Decl::Export, "");
888static_assert((clang::Decl::Kind)ZigClangDeclExternCContext == clang::Decl::ExternCContext, "");
889static_assert((clang::Decl::Kind)ZigClangDeclFileScopeAsm == clang::Decl::FileScopeAsm, "");
890static_assert((clang::Decl::Kind)ZigClangDeclFriend == clang::Decl::Friend, "");
891static_assert((clang::Decl::Kind)ZigClangDeclFriendTemplate == clang::Decl::FriendTemplate, "");
892static_assert((clang::Decl::Kind)ZigClangDeclImport == clang::Decl::Import, "");
893static_assert((clang::Decl::Kind)ZigClangDeclLinkageSpec == clang::Decl::LinkageSpec, "");
894static_assert((clang::Decl::Kind)ZigClangDeclLabel == clang::Decl::Label, "");
895static_assert((clang::Decl::Kind)ZigClangDeclNamespace == clang::Decl::Namespace, "");
896static_assert((clang::Decl::Kind)ZigClangDeclNamespaceAlias == clang::Decl::NamespaceAlias, "");
897static_assert((clang::Decl::Kind)ZigClangDeclObjCCompatibleAlias == clang::Decl::ObjCCompatibleAlias, "");
898static_assert((clang::Decl::Kind)ZigClangDeclObjCCategory == clang::Decl::ObjCCategory, "");
899static_assert((clang::Decl::Kind)ZigClangDeclObjCCategoryImpl == clang::Decl::ObjCCategoryImpl, "");
900static_assert((clang::Decl::Kind)ZigClangDeclObjCImplementation == clang::Decl::ObjCImplementation, "");
901static_assert((clang::Decl::Kind)ZigClangDeclObjCInterface == clang::Decl::ObjCInterface, "");
902static_assert((clang::Decl::Kind)ZigClangDeclObjCProtocol == clang::Decl::ObjCProtocol, "");
903static_assert((clang::Decl::Kind)ZigClangDeclObjCMethod == clang::Decl::ObjCMethod, "");
904static_assert((clang::Decl::Kind)ZigClangDeclObjCProperty == clang::Decl::ObjCProperty, "");
905static_assert((clang::Decl::Kind)ZigClangDeclBuiltinTemplate == clang::Decl::BuiltinTemplate, "");
906static_assert((clang::Decl::Kind)ZigClangDeclClassTemplate == clang::Decl::ClassTemplate, "");
907static_assert((clang::Decl::Kind)ZigClangDeclFunctionTemplate == clang::Decl::FunctionTemplate, "");
908static_assert((clang::Decl::Kind)ZigClangDeclTypeAliasTemplate == clang::Decl::TypeAliasTemplate, "");
909static_assert((clang::Decl::Kind)ZigClangDeclVarTemplate == clang::Decl::VarTemplate, "");
910static_assert((clang::Decl::Kind)ZigClangDeclTemplateTemplateParm == clang::Decl::TemplateTemplateParm, "");
911static_assert((clang::Decl::Kind)ZigClangDeclEnum == clang::Decl::Enum, "");
912static_assert((clang::Decl::Kind)ZigClangDeclRecord == clang::Decl::Record, "");
913static_assert((clang::Decl::Kind)ZigClangDeclCXXRecord == clang::Decl::CXXRecord, "");
914static_assert((clang::Decl::Kind)ZigClangDeclClassTemplateSpecialization == clang::Decl::ClassTemplateSpecialization, "");
915static_assert((clang::Decl::Kind)ZigClangDeclClassTemplatePartialSpecialization == clang::Decl::ClassTemplatePartialSpecialization, "");
916static_assert((clang::Decl::Kind)ZigClangDeclTemplateTypeParm == clang::Decl::TemplateTypeParm, "");
917static_assert((clang::Decl::Kind)ZigClangDeclObjCTypeParam == clang::Decl::ObjCTypeParam, "");
918static_assert((clang::Decl::Kind)ZigClangDeclTypeAlias == clang::Decl::TypeAlias, "");
919static_assert((clang::Decl::Kind)ZigClangDeclTypedef == clang::Decl::Typedef, "");
920static_assert((clang::Decl::Kind)ZigClangDeclUnresolvedUsingTypename == clang::Decl::UnresolvedUsingTypename, "");
921static_assert((clang::Decl::Kind)ZigClangDeclUsing == clang::Decl::Using, "");
922static_assert((clang::Decl::Kind)ZigClangDeclUsingDirective == clang::Decl::UsingDirective, "");
923static_assert((clang::Decl::Kind)ZigClangDeclUsingPack == clang::Decl::UsingPack, "");
924static_assert((clang::Decl::Kind)ZigClangDeclUsingShadow == clang::Decl::UsingShadow, "");
925static_assert((clang::Decl::Kind)ZigClangDeclConstructorUsingShadow == clang::Decl::ConstructorUsingShadow, "");
926static_assert((clang::Decl::Kind)ZigClangDeclBinding == clang::Decl::Binding, "");
927static_assert((clang::Decl::Kind)ZigClangDeclField == clang::Decl::Field, "");
928static_assert((clang::Decl::Kind)ZigClangDeclObjCAtDefsField == clang::Decl::ObjCAtDefsField, "");
929static_assert((clang::Decl::Kind)ZigClangDeclObjCIvar == clang::Decl::ObjCIvar, "");
930static_assert((clang::Decl::Kind)ZigClangDeclFunction == clang::Decl::Function, "");
931static_assert((clang::Decl::Kind)ZigClangDeclCXXDeductionGuide == clang::Decl::CXXDeductionGuide, "");
932static_assert((clang::Decl::Kind)ZigClangDeclCXXMethod == clang::Decl::CXXMethod, "");
933static_assert((clang::Decl::Kind)ZigClangDeclCXXConstructor == clang::Decl::CXXConstructor, "");
934static_assert((clang::Decl::Kind)ZigClangDeclCXXConversion == clang::Decl::CXXConversion, "");
935static_assert((clang::Decl::Kind)ZigClangDeclCXXDestructor == clang::Decl::CXXDestructor, "");
936static_assert((clang::Decl::Kind)ZigClangDeclMSProperty == clang::Decl::MSProperty, "");
937static_assert((clang::Decl::Kind)ZigClangDeclNonTypeTemplateParm == clang::Decl::NonTypeTemplateParm, "");
938static_assert((clang::Decl::Kind)ZigClangDeclVar == clang::Decl::Var, "");
939static_assert((clang::Decl::Kind)ZigClangDeclDecomposition == clang::Decl::Decomposition, "");
940static_assert((clang::Decl::Kind)ZigClangDeclImplicitParam == clang::Decl::ImplicitParam, "");
941static_assert((clang::Decl::Kind)ZigClangDeclOMPCapturedExpr == clang::Decl::OMPCapturedExpr, "");
942static_assert((clang::Decl::Kind)ZigClangDeclParmVar == clang::Decl::ParmVar, "");
943static_assert((clang::Decl::Kind)ZigClangDeclVarTemplateSpecialization == clang::Decl::VarTemplateSpecialization, "");
944static_assert((clang::Decl::Kind)ZigClangDeclVarTemplatePartialSpecialization == clang::Decl::VarTemplatePartialSpecialization, "");
945static_assert((clang::Decl::Kind)ZigClangDeclEnumConstant == clang::Decl::EnumConstant, "");
946static_assert((clang::Decl::Kind)ZigClangDeclIndirectField == clang::Decl::IndirectField, "");
947static_assert((clang::Decl::Kind)ZigClangDeclOMPDeclareReduction == clang::Decl::OMPDeclareReduction, "");
948static_assert((clang::Decl::Kind)ZigClangDeclUnresolvedUsingValue == clang::Decl::UnresolvedUsingValue, "");
949static_assert((clang::Decl::Kind)ZigClangDeclOMPRequires == clang::Decl::OMPRequires, "");
950static_assert((clang::Decl::Kind)ZigClangDeclOMPThreadPrivate == clang::Decl::OMPThreadPrivate, "");
951static_assert((clang::Decl::Kind)ZigClangDeclObjCPropertyImpl == clang::Decl::ObjCPropertyImpl, "");
952static_assert((clang::Decl::Kind)ZigClangDeclPragmaComment == clang::Decl::PragmaComment, "");
953static_assert((clang::Decl::Kind)ZigClangDeclPragmaDetectMismatch == clang::Decl::PragmaDetectMismatch, "");
954static_assert((clang::Decl::Kind)ZigClangDeclStaticAssert == clang::Decl::StaticAssert, "");
955static_assert((clang::Decl::Kind)ZigClangDeclTranslationUnit == clang::Decl::TranslationUnit, "");
956
957void ZigClang_detect_enum_BuiltinTypeKind(clang::BuiltinType::Kind x) {
958 switch (x) {
959 case clang::BuiltinType::OCLImage1dRO:
960 case clang::BuiltinType::OCLImage1dArrayRO:
961 case clang::BuiltinType::OCLImage1dBufferRO:
962 case clang::BuiltinType::OCLImage2dRO:
963 case clang::BuiltinType::OCLImage2dArrayRO:
964 case clang::BuiltinType::OCLImage2dDepthRO:
965 case clang::BuiltinType::OCLImage2dArrayDepthRO:
966 case clang::BuiltinType::OCLImage2dMSAARO:
967 case clang::BuiltinType::OCLImage2dArrayMSAARO:
968 case clang::BuiltinType::OCLImage2dMSAADepthRO:
969 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
970 case clang::BuiltinType::OCLImage3dRO:
971 case clang::BuiltinType::OCLImage1dWO:
972 case clang::BuiltinType::OCLImage1dArrayWO:
973 case clang::BuiltinType::OCLImage1dBufferWO:
974 case clang::BuiltinType::OCLImage2dWO:
975 case clang::BuiltinType::OCLImage2dArrayWO:
976 case clang::BuiltinType::OCLImage2dDepthWO:
977 case clang::BuiltinType::OCLImage2dArrayDepthWO:
978 case clang::BuiltinType::OCLImage2dMSAAWO:
979 case clang::BuiltinType::OCLImage2dArrayMSAAWO:
980 case clang::BuiltinType::OCLImage2dMSAADepthWO:
981 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
982 case clang::BuiltinType::OCLImage3dWO:
983 case clang::BuiltinType::OCLImage1dRW:
984 case clang::BuiltinType::OCLImage1dArrayRW:
985 case clang::BuiltinType::OCLImage1dBufferRW:
986 case clang::BuiltinType::OCLImage2dRW:
987 case clang::BuiltinType::OCLImage2dArrayRW:
988 case clang::BuiltinType::OCLImage2dDepthRW:
989 case clang::BuiltinType::OCLImage2dArrayDepthRW:
990 case clang::BuiltinType::OCLImage2dMSAARW:
991 case clang::BuiltinType::OCLImage2dArrayMSAARW:
992 case clang::BuiltinType::OCLImage2dMSAADepthRW:
993 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
994 case clang::BuiltinType::OCLImage3dRW:
995 case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
996 case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
997 case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
998 case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
999 case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
1000 case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
1001 case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
1002 case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
1003 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
1004 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
1005 case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
1006 case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
1007 case clang::BuiltinType::Void:
1008 case clang::BuiltinType::Bool:
1009 case clang::BuiltinType::Char_U:
1010 case clang::BuiltinType::UChar:
1011 case clang::BuiltinType::WChar_U:
1012 case clang::BuiltinType::Char8:
1013 case clang::BuiltinType::Char16:
1014 case clang::BuiltinType::Char32:
1015 case clang::BuiltinType::UShort:
1016 case clang::BuiltinType::UInt:
1017 case clang::BuiltinType::ULong:
1018 case clang::BuiltinType::ULongLong:
1019 case clang::BuiltinType::UInt128:
1020 case clang::BuiltinType::Char_S:
1021 case clang::BuiltinType::SChar:
1022 case clang::BuiltinType::WChar_S:
1023 case clang::BuiltinType::Short:
1024 case clang::BuiltinType::Int:
1025 case clang::BuiltinType::Long:
1026 case clang::BuiltinType::LongLong:
1027 case clang::BuiltinType::Int128:
1028 case clang::BuiltinType::ShortAccum:
1029 case clang::BuiltinType::Accum:
1030 case clang::BuiltinType::LongAccum:
1031 case clang::BuiltinType::UShortAccum:
1032 case clang::BuiltinType::UAccum:
1033 case clang::BuiltinType::ULongAccum:
1034 case clang::BuiltinType::ShortFract:
1035 case clang::BuiltinType::Fract:
1036 case clang::BuiltinType::LongFract:
1037 case clang::BuiltinType::UShortFract:
1038 case clang::BuiltinType::UFract:
1039 case clang::BuiltinType::ULongFract:
1040 case clang::BuiltinType::SatShortAccum:
1041 case clang::BuiltinType::SatAccum:
1042 case clang::BuiltinType::SatLongAccum:
1043 case clang::BuiltinType::SatUShortAccum:
1044 case clang::BuiltinType::SatUAccum:
1045 case clang::BuiltinType::SatULongAccum:
1046 case clang::BuiltinType::SatShortFract:
1047 case clang::BuiltinType::SatFract:
1048 case clang::BuiltinType::SatLongFract:
1049 case clang::BuiltinType::SatUShortFract:
1050 case clang::BuiltinType::SatUFract:
1051 case clang::BuiltinType::SatULongFract:
1052 case clang::BuiltinType::Half:
1053 case clang::BuiltinType::Float:
1054 case clang::BuiltinType::Double:
1055 case clang::BuiltinType::LongDouble:
1056 case clang::BuiltinType::Float16:
1057 case clang::BuiltinType::Float128:
1058 case clang::BuiltinType::NullPtr:
1059 case clang::BuiltinType::ObjCId:
1060 case clang::BuiltinType::ObjCClass:
1061 case clang::BuiltinType::ObjCSel:
1062 case clang::BuiltinType::OCLSampler:
1063 case clang::BuiltinType::OCLEvent:
1064 case clang::BuiltinType::OCLClkEvent:
1065 case clang::BuiltinType::OCLQueue:
1066 case clang::BuiltinType::OCLReserveID:
1067 case clang::BuiltinType::Dependent:
1068 case clang::BuiltinType::Overload:
1069 case clang::BuiltinType::BoundMember:
1070 case clang::BuiltinType::PseudoObject:
1071 case clang::BuiltinType::UnknownAny:
1072 case clang::BuiltinType::BuiltinFn:
1073 case clang::BuiltinType::ARCUnbridgedCast:
1074 case clang::BuiltinType::OMPArraySection:
1075 break;
1076 }
1077}
1078
1079static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dRO == clang::BuiltinType::OCLImage1dRO, "");
1080static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dArrayRO == clang::BuiltinType::OCLImage1dArrayRO, "");
1081static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dBufferRO == clang::BuiltinType::OCLImage1dBufferRO, "");
1082static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dRO == clang::BuiltinType::OCLImage2dRO, "");
1083static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayRO == clang::BuiltinType::OCLImage2dArrayRO, "");
1084static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dDepthRO == clang::BuiltinType::OCLImage2dDepthRO, "");
1085static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayDepthRO == clang::BuiltinType::OCLImage2dArrayDepthRO, "");
1086static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAARO == clang::BuiltinType::OCLImage2dMSAARO, "");
1087static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAARO == clang::BuiltinType::OCLImage2dArrayMSAARO, "");
1088static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAADepthRO == clang::BuiltinType::OCLImage2dMSAADepthRO, "");
1089static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO == clang::BuiltinType::OCLImage2dArrayMSAADepthRO, "");
1090static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage3dRO == clang::BuiltinType::OCLImage3dRO, "");
1091static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dWO == clang::BuiltinType::OCLImage1dWO, "");
1092static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dArrayWO == clang::BuiltinType::OCLImage1dArrayWO, "");
1093static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dBufferWO == clang::BuiltinType::OCLImage1dBufferWO, "");
1094static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dWO == clang::BuiltinType::OCLImage2dWO, "");
1095static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayWO == clang::BuiltinType::OCLImage2dArrayWO, "");
1096static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dDepthWO == clang::BuiltinType::OCLImage2dDepthWO, "");
1097static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayDepthWO == clang::BuiltinType::OCLImage2dArrayDepthWO, "");
1098static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAAWO == clang::BuiltinType::OCLImage2dMSAAWO, "");
1099static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAAWO == clang::BuiltinType::OCLImage2dArrayMSAAWO, "");
1100static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAADepthWO == clang::BuiltinType::OCLImage2dMSAADepthWO, "");
1101static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO == clang::BuiltinType::OCLImage2dArrayMSAADepthWO, "");
1102static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage3dWO == clang::BuiltinType::OCLImage3dWO, "");
1103static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dRW == clang::BuiltinType::OCLImage1dRW, "");
1104static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dArrayRW == clang::BuiltinType::OCLImage1dArrayRW, "");
1105static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dBufferRW == clang::BuiltinType::OCLImage1dBufferRW, "");
1106static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dRW == clang::BuiltinType::OCLImage2dRW, "");
1107static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayRW == clang::BuiltinType::OCLImage2dArrayRW, "");
1108static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dDepthRW == clang::BuiltinType::OCLImage2dDepthRW, "");
1109static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayDepthRW == clang::BuiltinType::OCLImage2dArrayDepthRW, "");
1110static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAARW == clang::BuiltinType::OCLImage2dMSAARW, "");
1111static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAARW == clang::BuiltinType::OCLImage2dArrayMSAARW, "");
1112static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAADepthRW == clang::BuiltinType::OCLImage2dMSAADepthRW, "");
1113static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW == clang::BuiltinType::OCLImage2dArrayMSAADepthRW, "");
1114static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage3dRW == clang::BuiltinType::OCLImage3dRW, "");
1115static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload == clang::BuiltinType::OCLIntelSubgroupAVCMcePayload, "");
1116static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload == clang::BuiltinType::OCLIntelSubgroupAVCImePayload, "");
1117static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload == clang::BuiltinType::OCLIntelSubgroupAVCRefPayload, "");
1118static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload == clang::BuiltinType::OCLIntelSubgroupAVCSicPayload, "");
1119static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult == clang::BuiltinType::OCLIntelSubgroupAVCMceResult, "");
1120static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult == clang::BuiltinType::OCLIntelSubgroupAVCImeResult, "");
1121static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult == clang::BuiltinType::OCLIntelSubgroupAVCRefResult, "");
1122static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult == clang::BuiltinType::OCLIntelSubgroupAVCSicResult, "");
1123static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout == clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout, "");
1124static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout == clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout, "");
1125static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin == clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin, "");
1126static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin == clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin, "");
1127static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeVoid == clang::BuiltinType::Void, "");
1128static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeBool == clang::BuiltinType::Bool, "");
1129static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar_U == clang::BuiltinType::Char_U, "");
1130static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUChar == clang::BuiltinType::UChar, "");
1131static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeWChar_U == clang::BuiltinType::WChar_U, "");
1132static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar8 == clang::BuiltinType::Char8, "");
1133static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar16 == clang::BuiltinType::Char16, "");
1134static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar32 == clang::BuiltinType::Char32, "");
1135static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUShort == clang::BuiltinType::UShort, "");
1136static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUInt == clang::BuiltinType::UInt, "");
1137static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULong == clang::BuiltinType::ULong, "");
1138static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULongLong == clang::BuiltinType::ULongLong, "");
1139static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUInt128 == clang::BuiltinType::UInt128, "");
1140static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar_S == clang::BuiltinType::Char_S, "");
1141static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSChar == clang::BuiltinType::SChar, "");
1142static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeWChar_S == clang::BuiltinType::WChar_S, "");
1143static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeShort == clang::BuiltinType::Short, "");
1144static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeInt == clang::BuiltinType::Int, "");
1145static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLong == clang::BuiltinType::Long, "");
1146static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongLong == clang::BuiltinType::LongLong, "");
1147static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeInt128 == clang::BuiltinType::Int128, "");
1148static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeShortAccum == clang::BuiltinType::ShortAccum, "");
1149static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeAccum == clang::BuiltinType::Accum, "");
1150static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongAccum == clang::BuiltinType::LongAccum, "");
1151static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUShortAccum == clang::BuiltinType::UShortAccum, "");
1152static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUAccum == clang::BuiltinType::UAccum, "");
1153static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULongAccum == clang::BuiltinType::ULongAccum, "");
1154static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeShortFract == clang::BuiltinType::ShortFract, "");
1155static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFract == clang::BuiltinType::Fract, "");
1156static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongFract == clang::BuiltinType::LongFract, "");
1157static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUShortFract == clang::BuiltinType::UShortFract, "");
1158static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUFract == clang::BuiltinType::UFract, "");
1159static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULongFract == clang::BuiltinType::ULongFract, "");
1160static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatShortAccum == clang::BuiltinType::SatShortAccum, "");
1161static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatAccum == clang::BuiltinType::SatAccum, "");
1162static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatLongAccum == clang::BuiltinType::SatLongAccum, "");
1163static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUShortAccum == clang::BuiltinType::SatUShortAccum, "");
1164static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUAccum == clang::BuiltinType::SatUAccum, "");
1165static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatULongAccum == clang::BuiltinType::SatULongAccum, "");
1166static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatShortFract == clang::BuiltinType::SatShortFract, "");
1167static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatFract == clang::BuiltinType::SatFract, "");
1168static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatLongFract == clang::BuiltinType::SatLongFract, "");
1169static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUShortFract == clang::BuiltinType::SatUShortFract, "");
1170static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUFract == clang::BuiltinType::SatUFract, "");
1171static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatULongFract == clang::BuiltinType::SatULongFract, "");
1172static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeHalf == clang::BuiltinType::Half, "");
1173static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFloat == clang::BuiltinType::Float, "");
1174static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeDouble == clang::BuiltinType::Double, "");
1175static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongDouble == clang::BuiltinType::LongDouble, "");
1176static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFloat16 == clang::BuiltinType::Float16, "");
1177static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFloat128 == clang::BuiltinType::Float128, "");
1178static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeNullPtr == clang::BuiltinType::NullPtr, "");
1179static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeObjCId == clang::BuiltinType::ObjCId, "");
1180static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeObjCClass == clang::BuiltinType::ObjCClass, "");
1181static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeObjCSel == clang::BuiltinType::ObjCSel, "");
1182static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLSampler == clang::BuiltinType::OCLSampler, "");
1183static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLEvent == clang::BuiltinType::OCLEvent, "");
1184static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLClkEvent == clang::BuiltinType::OCLClkEvent, "");
1185static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLQueue == clang::BuiltinType::OCLQueue, "");
1186static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLReserveID == clang::BuiltinType::OCLReserveID, "");
1187static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeDependent == clang::BuiltinType::Dependent, "");
1188static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOverload == clang::BuiltinType::Overload, "");
1189static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeBoundMember == clang::BuiltinType::BoundMember, "");
1190static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypePseudoObject == clang::BuiltinType::PseudoObject, "");
1191static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUnknownAny == clang::BuiltinType::UnknownAny, "");
1192static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeBuiltinFn == clang::BuiltinType::BuiltinFn, "");
1193static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeARCUnbridgedCast == clang::BuiltinType::ARCUnbridgedCast, "");
1194static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOMPArraySection == clang::BuiltinType::OMPArraySection, "");
1195
1196void ZigClang_detect_enum_CallingConv(clang::CallingConv x) {
1197 switch (x) {
1198 case clang::CC_C:
1199 case clang::CC_X86StdCall:
1200 case clang::CC_X86FastCall:
1201 case clang::CC_X86ThisCall:
1202 case clang::CC_X86VectorCall:
1203 case clang::CC_X86Pascal:
1204 case clang::CC_Win64:
1205 case clang::CC_X86_64SysV:
1206 case clang::CC_X86RegCall:
1207 case clang::CC_AAPCS:
1208 case clang::CC_AAPCS_VFP:
1209 case clang::CC_IntelOclBicc:
1210 case clang::CC_SpirFunction:
1211 case clang::CC_OpenCLKernel:
1212 case clang::CC_Swift:
1213 case clang::CC_PreserveMost:
1214 case clang::CC_PreserveAll:
1215 case clang::CC_AArch64VectorCall:
1216 break;
1217 }
1218}
1219
1220static_assert((clang::CallingConv)ZigClangCallingConv_C == clang::CC_C, "");
1221static_assert((clang::CallingConv)ZigClangCallingConv_X86StdCall == clang::CC_X86StdCall, "");
1222static_assert((clang::CallingConv)ZigClangCallingConv_X86FastCall == clang::CC_X86FastCall, "");
1223static_assert((clang::CallingConv)ZigClangCallingConv_X86ThisCall == clang::CC_X86ThisCall, "");
1224static_assert((clang::CallingConv)ZigClangCallingConv_X86VectorCall == clang::CC_X86VectorCall, "");
1225static_assert((clang::CallingConv)ZigClangCallingConv_X86Pascal == clang::CC_X86Pascal, "");
1226static_assert((clang::CallingConv)ZigClangCallingConv_Win64 == clang::CC_Win64, "");
1227static_assert((clang::CallingConv)ZigClangCallingConv_X86_64SysV == clang::CC_X86_64SysV, "");
1228static_assert((clang::CallingConv)ZigClangCallingConv_X86RegCall == clang::CC_X86RegCall, "");
1229static_assert((clang::CallingConv)ZigClangCallingConv_AAPCS == clang::CC_AAPCS, "");
1230static_assert((clang::CallingConv)ZigClangCallingConv_AAPCS_VFP == clang::CC_AAPCS_VFP, "");
1231static_assert((clang::CallingConv)ZigClangCallingConv_IntelOclBicc == clang::CC_IntelOclBicc, "");
1232static_assert((clang::CallingConv)ZigClangCallingConv_SpirFunction == clang::CC_SpirFunction, "");
1233static_assert((clang::CallingConv)ZigClangCallingConv_OpenCLKernel == clang::CC_OpenCLKernel, "");
1234static_assert((clang::CallingConv)ZigClangCallingConv_Swift == clang::CC_Swift, "");
1235static_assert((clang::CallingConv)ZigClangCallingConv_PreserveMost == clang::CC_PreserveMost, "");
1236static_assert((clang::CallingConv)ZigClangCallingConv_PreserveAll == clang::CC_PreserveAll, "");
1237static_assert((clang::CallingConv)ZigClangCallingConv_AArch64VectorCall == clang::CC_AArch64VectorCall, "");
1238
1239void ZigClang_detect_enum_StorageClass(clang::StorageClass x) {
1240 switch (x) {
1241 case clang::SC_None:
1242 case clang::SC_Extern:
1243 case clang::SC_Static:
1244 case clang::SC_PrivateExtern:
1245 case clang::SC_Auto:
1246 case clang::SC_Register:
1247 break;
1248 }
1249}
1250
1251static_assert((clang::StorageClass)ZigClangStorageClass_None == clang::SC_None, "");
1252static_assert((clang::StorageClass)ZigClangStorageClass_Extern == clang::SC_Extern, "");
1253static_assert((clang::StorageClass)ZigClangStorageClass_Static == clang::SC_Static, "");
1254static_assert((clang::StorageClass)ZigClangStorageClass_PrivateExtern == clang::SC_PrivateExtern, "");
1255static_assert((clang::StorageClass)ZigClangStorageClass_Auto == clang::SC_Auto, "");
1256static_assert((clang::StorageClass)ZigClangStorageClass_Register == clang::SC_Register, "");
1257
1258
140static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");1259static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
141static ZigClangSourceLocation bitcast(clang::SourceLocation src) {1260static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
142 ZigClangSourceLocation dest;1261 ZigClangSourceLocation dest;
...@@ -161,6 +1280,26 @@ static clang::QualType bitcast(ZigClangQualType src) {...@@ -161,6 +1280,26 @@ static clang::QualType bitcast(ZigClangQualType src) {
161 return dest;1280 return dest;
162}1281}
1631282
1283static_assert(sizeof(ZigClangAPValueLValueBase) == sizeof(clang::APValue::LValueBase), "");
1284static ZigClangAPValueLValueBase bitcast(clang::APValue::LValueBase src) {
1285 ZigClangAPValueLValueBase dest;
1286 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangAPValueLValueBase));
1287 return dest;
1288}
1289static clang::APValue::LValueBase bitcast(ZigClangAPValueLValueBase src) {
1290 clang::APValue::LValueBase dest;
1291 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangAPValueLValueBase));
1292 return dest;
1293}
1294
1295static_assert(sizeof(ZigClangCompoundStmt_const_body_iterator) == sizeof(clang::CompoundStmt::const_body_iterator), "");
1296static ZigClangCompoundStmt_const_body_iterator bitcast(clang::CompoundStmt::const_body_iterator src) {
1297 ZigClangCompoundStmt_const_body_iterator dest;
1298 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangCompoundStmt_const_body_iterator));
1299 return dest;
1300}
1301
1302
164ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,1303ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
165 ZigClangSourceLocation Loc)1304 ZigClangSourceLocation Loc)
166{1305{
...@@ -196,6 +1335,10 @@ ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* sel...@@ -196,6 +1335,10 @@ ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* sel
196 return bitcast(reinterpret_cast<const clang::ASTContext *>(self)->getPointerType(bitcast(T)));1335 return bitcast(reinterpret_cast<const clang::ASTContext *>(self)->getPointerType(bitcast(T)));
197}1336}
1981337
1338unsigned ZigClangASTContext_getTypeAlign(const ZigClangASTContext* self, ZigClangQualType T) {
1339 return reinterpret_cast<const clang::ASTContext *>(self)->getTypeAlign(bitcast(T));
1340}
1341
199ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) {1342ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) {
200 clang::ASTContext *result = &reinterpret_cast<clang::ASTUnit *>(self)->getASTContext();1343 clang::ASTContext *result = &reinterpret_cast<clang::ASTUnit *>(self)->getASTContext();
201 return reinterpret_cast<ZigClangASTContext *>(result);1344 return reinterpret_cast<ZigClangASTContext *>(result);
...@@ -212,3 +1355,477 @@ bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *contex...@@ -212,3 +1355,477 @@ bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *contex
212 return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context,1355 return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context,
213 reinterpret_cast<bool (*)(void *, const clang::Decl *)>(Fn));1356 reinterpret_cast<bool (*)(void *, const clang::Decl *)>(Fn));
214}1357}
1358
1359const ZigClangRecordDecl *ZigClangRecordType_getDecl(const ZigClangRecordType *record_ty) {
1360 const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordType *>(record_ty)->getDecl();
1361 return reinterpret_cast<const ZigClangRecordDecl *>(record_decl);
1362}
1363
1364const ZigClangEnumDecl *ZigClangEnumType_getDecl(const ZigClangEnumType *enum_ty) {
1365 const clang::EnumDecl *enum_decl = reinterpret_cast<const clang::EnumType *>(enum_ty)->getDecl();
1366 return reinterpret_cast<const ZigClangEnumDecl *>(enum_decl);
1367}
1368
1369const ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const ZigClangRecordDecl *record_decl) {
1370 const clang::TagDecl *tag_decl = reinterpret_cast<const clang::RecordDecl*>(record_decl)->getCanonicalDecl();
1371 return reinterpret_cast<const ZigClangTagDecl *>(tag_decl);
1372}
1373
1374const ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const ZigClangEnumDecl *enum_decl) {
1375 const clang::TagDecl *tag_decl = reinterpret_cast<const clang::EnumDecl*>(enum_decl)->getCanonicalDecl();
1376 return reinterpret_cast<const ZigClangTagDecl *>(tag_decl);
1377}
1378
1379const ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCanonicalDecl(const ZigClangTypedefNameDecl *self) {
1380 const clang::TypedefNameDecl *decl = reinterpret_cast<const clang::TypedefNameDecl*>(self)->getCanonicalDecl();
1381 return reinterpret_cast<const ZigClangTypedefNameDecl *>(decl);
1382}
1383
1384const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) {
1385 const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl);
1386 const clang::RecordDecl *definition = record_decl->getDefinition();
1387 return reinterpret_cast<const ZigClangRecordDecl *>(definition);
1388}
1389
1390const ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const ZigClangEnumDecl *zig_enum_decl) {
1391 const clang::EnumDecl *enum_decl = reinterpret_cast<const clang::EnumDecl *>(zig_enum_decl);
1392 const clang::EnumDecl *definition = enum_decl->getDefinition();
1393 return reinterpret_cast<const ZigClangEnumDecl *>(definition);
1394}
1395
1396bool ZigClangRecordDecl_isUnion(const ZigClangRecordDecl *record_decl) {
1397 return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isUnion();
1398}
1399
1400bool ZigClangRecordDecl_isStruct(const ZigClangRecordDecl *record_decl) {
1401 return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isStruct();
1402}
1403
1404bool ZigClangRecordDecl_isAnonymousStructOrUnion(const ZigClangRecordDecl *record_decl) {
1405 return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isAnonymousStructOrUnion();
1406}
1407
1408const char *ZigClangDecl_getName_bytes_begin(const ZigClangDecl *zig_decl) {
1409 const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zig_decl);
1410 const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl);
1411 return (const char *)named_decl->getName().bytes_begin();
1412}
1413
1414ZigClangDeclKind ZigClangDecl_getKind(const struct ZigClangDecl *self) {
1415 auto casted = reinterpret_cast<const clang::Decl *>(self);
1416 return (ZigClangDeclKind)casted->getKind();
1417}
1418
1419const char *ZigClangDecl_getDeclKindName(const struct ZigClangDecl *self) {
1420 auto casted = reinterpret_cast<const clang::Decl *>(self);
1421 return casted->getDeclKindName();
1422}
1423
1424ZigClangSourceLocation ZigClangRecordDecl_getLocation(const ZigClangRecordDecl *zig_record_decl) {
1425 const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl);
1426 return bitcast(record_decl->getLocation());
1427}
1428
1429ZigClangSourceLocation ZigClangEnumDecl_getLocation(const ZigClangEnumDecl *self) {
1430 auto casted = reinterpret_cast<const clang::EnumDecl *>(self);
1431 return bitcast(casted->getLocation());
1432}
1433
1434ZigClangSourceLocation ZigClangTypedefNameDecl_getLocation(const ZigClangTypedefNameDecl *self) {
1435 auto casted = reinterpret_cast<const clang::TypedefNameDecl *>(self);
1436 return bitcast(casted->getLocation());
1437}
1438
1439ZigClangSourceLocation ZigClangDecl_getLocation(const ZigClangDecl *self) {
1440 auto casted = reinterpret_cast<const clang::Decl *>(self);
1441 return bitcast(casted->getLocation());
1442}
1443
1444bool ZigClangSourceLocation_eq(ZigClangSourceLocation zig_a, ZigClangSourceLocation zig_b) {
1445 clang::SourceLocation a = bitcast(zig_a);
1446 clang::SourceLocation b = bitcast(zig_b);
1447 return a == b;
1448}
1449
1450ZigClangQualType ZigClangEnumDecl_getIntegerType(const ZigClangEnumDecl *self) {
1451 return bitcast(reinterpret_cast<const clang::EnumDecl *>(self)->getIntegerType());
1452}
1453
1454struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *self) {
1455 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1456 return bitcast(casted->getType());
1457}
1458
1459struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *self) {
1460 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1461 return bitcast(casted->getLocation());
1462}
1463
1464bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *self) {
1465 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1466 return casted->hasBody();
1467}
1468
1469enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *self) {
1470 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1471 return (ZigClangStorageClass)casted->getStorageClass();
1472}
1473
1474const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *self,
1475 unsigned i)
1476{
1477 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1478 const clang::ParmVarDecl *parm_var_decl = casted->getParamDecl(i);
1479 return reinterpret_cast<const ZigClangParmVarDecl *>(parm_var_decl);
1480}
1481
1482const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *self) {
1483 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1484 const clang::Stmt *stmt = casted->getBody();
1485 return reinterpret_cast<const ZigClangStmt *>(stmt);
1486}
1487
1488const ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const ZigClangTypedefType *self) {
1489 auto casted = reinterpret_cast<const clang::TypedefType *>(self);
1490 const clang::TypedefNameDecl *name_decl = casted->getDecl();
1491 return reinterpret_cast<const ZigClangTypedefNameDecl *>(name_decl);
1492}
1493
1494ZigClangQualType ZigClangTypedefNameDecl_getUnderlyingType(const ZigClangTypedefNameDecl *self) {
1495 auto casted = reinterpret_cast<const clang::TypedefNameDecl *>(self);
1496 clang::QualType ty = casted->getUnderlyingType();
1497 return bitcast(ty);
1498}
1499
1500ZigClangQualType ZigClangQualType_getCanonicalType(ZigClangQualType self) {
1501 clang::QualType qt = bitcast(self);
1502 return bitcast(qt.getCanonicalType());
1503}
1504
1505const ZigClangType *ZigClangQualType_getTypePtr(ZigClangQualType self) {
1506 clang::QualType qt = bitcast(self);
1507 const clang::Type *ty = qt.getTypePtr();
1508 return reinterpret_cast<const ZigClangType *>(ty);
1509}
1510
1511void ZigClangQualType_addConst(ZigClangQualType *self) {
1512 reinterpret_cast<clang::QualType *>(self)->addConst();
1513}
1514
1515bool ZigClangQualType_eq(ZigClangQualType zig_t1, ZigClangQualType zig_t2) {
1516 clang::QualType t1 = bitcast(zig_t1);
1517 clang::QualType t2 = bitcast(zig_t2);
1518 if (t1.isConstQualified() != t2.isConstQualified()) {
1519 return false;
1520 }
1521 if (t1.isVolatileQualified() != t2.isVolatileQualified()) {
1522 return false;
1523 }
1524 if (t1.isRestrictQualified() != t2.isRestrictQualified()) {
1525 return false;
1526 }
1527 return t1.getTypePtr() == t2.getTypePtr();
1528}
1529
1530bool ZigClangQualType_isConstQualified(ZigClangQualType self) {
1531 clang::QualType qt = bitcast(self);
1532 return qt.isConstQualified();
1533}
1534
1535bool ZigClangQualType_isVolatileQualified(ZigClangQualType self) {
1536 clang::QualType qt = bitcast(self);
1537 return qt.isVolatileQualified();
1538}
1539
1540bool ZigClangQualType_isRestrictQualified(ZigClangQualType self) {
1541 clang::QualType qt = bitcast(self);
1542 return qt.isRestrictQualified();
1543}
1544
1545ZigClangTypeClass ZigClangType_getTypeClass(const ZigClangType *self) {
1546 auto casted = reinterpret_cast<const clang::Type *>(self);
1547 clang::Type::TypeClass tc = casted->getTypeClass();
1548 return (ZigClangTypeClass)tc;
1549}
1550
1551ZigClangQualType ZigClangType_getPointeeType(const ZigClangType *self) {
1552 auto casted = reinterpret_cast<const clang::Type *>(self);
1553 return bitcast(casted->getPointeeType());
1554}
1555
1556bool ZigClangType_isVoidType(const ZigClangType *self) {
1557 auto casted = reinterpret_cast<const clang::Type *>(self);
1558 return casted->isVoidType();
1559}
1560
1561const char *ZigClangType_getTypeClassName(const ZigClangType *self) {
1562 auto casted = reinterpret_cast<const clang::Type *>(self);
1563 return casted->getTypeClassName();
1564}
1565
1566ZigClangSourceLocation ZigClangStmt_getBeginLoc(const ZigClangStmt *self) {
1567 auto casted = reinterpret_cast<const clang::Stmt *>(self);
1568 return bitcast(casted->getBeginLoc());
1569}
1570
1571bool ZigClangStmt_classof_Expr(const ZigClangStmt *self) {
1572 auto casted = reinterpret_cast<const clang::Stmt *>(self);
1573 return clang::Expr::classof(casted);
1574}
1575
1576ZigClangStmtClass ZigClangStmt_getStmtClass(const ZigClangStmt *self) {
1577 auto casted = reinterpret_cast<const clang::Stmt *>(self);
1578 return (ZigClangStmtClass)casted->getStmtClass();
1579}
1580
1581ZigClangStmtClass ZigClangExpr_getStmtClass(const ZigClangExpr *self) {
1582 auto casted = reinterpret_cast<const clang::Expr *>(self);
1583 return (ZigClangStmtClass)casted->getStmtClass();
1584}
1585
1586ZigClangQualType ZigClangExpr_getType(const ZigClangExpr *self) {
1587 auto casted = reinterpret_cast<const clang::Expr *>(self);
1588 return bitcast(casted->getType());
1589}
1590
1591ZigClangSourceLocation ZigClangExpr_getBeginLoc(const ZigClangExpr *self) {
1592 auto casted = reinterpret_cast<const clang::Expr *>(self);
1593 return bitcast(casted->getBeginLoc());
1594}
1595
1596ZigClangAPValueKind ZigClangAPValue_getKind(const ZigClangAPValue *self) {
1597 auto casted = reinterpret_cast<const clang::APValue *>(self);
1598 return (ZigClangAPValueKind)casted->getKind();
1599}
1600
1601const ZigClangAPSInt *ZigClangAPValue_getInt(const ZigClangAPValue *self) {
1602 auto casted = reinterpret_cast<const clang::APValue *>(self);
1603 const llvm::APSInt *result = &casted->getInt();
1604 return reinterpret_cast<const ZigClangAPSInt *>(result);
1605}
1606
1607unsigned ZigClangAPValue_getArrayInitializedElts(const ZigClangAPValue *self) {
1608 auto casted = reinterpret_cast<const clang::APValue *>(self);
1609 return casted->getArrayInitializedElts();
1610}
1611
1612const ZigClangAPValue *ZigClangAPValue_getArrayInitializedElt(const ZigClangAPValue *self, unsigned i) {
1613 auto casted = reinterpret_cast<const clang::APValue *>(self);
1614 const clang::APValue *result = &casted->getArrayInitializedElt(i);
1615 return reinterpret_cast<const ZigClangAPValue *>(result);
1616}
1617
1618const ZigClangAPValue *ZigClangAPValue_getArrayFiller(const ZigClangAPValue *self) {
1619 auto casted = reinterpret_cast<const clang::APValue *>(self);
1620 const clang::APValue *result = &casted->getArrayFiller();
1621 return reinterpret_cast<const ZigClangAPValue *>(result);
1622}
1623
1624unsigned ZigClangAPValue_getArraySize(const ZigClangAPValue *self) {
1625 auto casted = reinterpret_cast<const clang::APValue *>(self);
1626 return casted->getArraySize();
1627}
1628
1629const ZigClangAPSInt *ZigClangAPSInt_negate(const ZigClangAPSInt *self) {
1630 auto casted = reinterpret_cast<const llvm::APSInt *>(self);
1631 llvm::APSInt *result = new llvm::APSInt();
1632 *result = *casted;
1633 *result = -*result;
1634 return reinterpret_cast<const ZigClangAPSInt *>(result);
1635}
1636
1637void ZigClangAPSInt_free(const ZigClangAPSInt *self) {
1638 auto casted = reinterpret_cast<const llvm::APSInt *>(self);
1639 delete casted;
1640}
1641
1642bool ZigClangAPSInt_isSigned(const ZigClangAPSInt *self) {
1643 auto casted = reinterpret_cast<const llvm::APSInt *>(self);
1644 return casted->isSigned();
1645}
1646
1647bool ZigClangAPSInt_isNegative(const ZigClangAPSInt *self) {
1648 auto casted = reinterpret_cast<const llvm::APSInt *>(self);
1649 return casted->isNegative();
1650}
1651
1652const uint64_t *ZigClangAPSInt_getRawData(const ZigClangAPSInt *self) {
1653 auto casted = reinterpret_cast<const llvm::APSInt *>(self);
1654 return casted->getRawData();
1655}
1656
1657unsigned ZigClangAPSInt_getNumWords(const ZigClangAPSInt *self) {
1658 auto casted = reinterpret_cast<const llvm::APSInt *>(self);
1659 return casted->getNumWords();
1660}
1661
1662const ZigClangExpr *ZigClangAPValueLValueBase_dyn_cast_Expr(ZigClangAPValueLValueBase self) {
1663 clang::APValue::LValueBase casted = bitcast(self);
1664 const clang::Expr *expr = casted.dyn_cast<const clang::Expr *>();
1665 return reinterpret_cast<const ZigClangExpr *>(expr);
1666}
1667
1668ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const ZigClangAPValue *self) {
1669 auto casted = reinterpret_cast<const clang::APValue *>(self);
1670 clang::APValue::LValueBase lval_base = casted->getLValueBase();
1671 return bitcast(lval_base);
1672}
1673
1674ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end,
1675 struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path)
1676{
1677 clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
1678
1679 std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();
1680
1681 bool only_local_decls = true;
1682 bool capture_diagnostics = true;
1683 bool user_files_are_volatile = true;
1684 bool allow_pch_with_compiler_errors = false;
1685 bool single_file_parse = false;
1686 bool for_serialization = false;
1687 std::unique_ptr<clang::ASTUnit> *err_unit = new std::unique_ptr<clang::ASTUnit>();
1688 clang::ASTUnit *ast_unit = clang::ASTUnit::LoadFromCommandLine(
1689 args_begin, args_end,
1690 pch_container_ops, diags, resources_path,
1691 only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
1692 false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
1693 single_file_parse, user_files_are_volatile, for_serialization, clang::None, err_unit,
1694 nullptr);
1695
1696 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
1697 if (!ast_unit && !err_unit) {
1698 return nullptr;
1699 }
1700
1701 if (diags->getClient()->getNumErrors() > 0) {
1702 if (ast_unit) {
1703 *err_unit = std::unique_ptr<clang::ASTUnit>(ast_unit);
1704 }
1705
1706 size_t cap = 4;
1707 *errors_len = 0;
1708 *errors_ptr = reinterpret_cast<Stage2ErrorMsg*>(malloc(cap * sizeof(Stage2ErrorMsg)));
1709 if (*errors_ptr == nullptr) {
1710 return nullptr;
1711 }
1712
1713 for (clang::ASTUnit::stored_diag_iterator it = (*err_unit)->stored_diag_begin(),
1714 it_end = (*err_unit)->stored_diag_end();
1715 it != it_end; ++it)
1716 {
1717 switch (it->getLevel()) {
1718 case clang::DiagnosticsEngine::Ignored:
1719 case clang::DiagnosticsEngine::Note:
1720 case clang::DiagnosticsEngine::Remark:
1721 case clang::DiagnosticsEngine::Warning:
1722 continue;
1723 case clang::DiagnosticsEngine::Error:
1724 case clang::DiagnosticsEngine::Fatal:
1725 break;
1726 }
1727 llvm::StringRef msg_str_ref = it->getMessage();
1728 if (*errors_len >= cap) {
1729 cap *= 2;
1730 Stage2ErrorMsg *new_errors = reinterpret_cast<Stage2ErrorMsg *>(
1731 realloc(*errors_ptr, cap * sizeof(Stage2ErrorMsg)));
1732 if (new_errors == nullptr) {
1733 free(*errors_ptr);
1734 *errors_ptr = nullptr;
1735 *errors_len = 0;
1736 return nullptr;
1737 }
1738 *errors_ptr = new_errors;
1739 }
1740 Stage2ErrorMsg *msg = *errors_ptr + *errors_len;
1741 *errors_len += 1;
1742 msg->msg_ptr = (const char *)msg_str_ref.bytes_begin();
1743 msg->msg_len = msg_str_ref.size();
1744
1745 clang::FullSourceLoc fsl = it->getLocation();
1746 if (fsl.hasManager()) {
1747 clang::FileID file_id = fsl.getFileID();
1748 clang::StringRef filename = fsl.getManager().getFilename(fsl);
1749 if (filename.empty()) {
1750 msg->filename_ptr = nullptr;
1751 } else {
1752 msg->filename_ptr = (const char *)filename.bytes_begin();
1753 msg->filename_len = filename.size();
1754 }
1755 msg->source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
1756 msg->line = fsl.getSpellingLineNumber() - 1;
1757 msg->column = fsl.getSpellingColumnNumber() - 1;
1758 msg->offset = fsl.getManager().getFileOffset(fsl);
1759 } else {
1760 // The only known way this gets triggered right now is if you have a lot of errors
1761 // clang emits "too many errors emitted, stopping now"
1762 msg->filename_ptr = nullptr;
1763 msg->source = nullptr;
1764 }
1765 }
1766
1767 if (*errors_len == 0) {
1768 free(*errors_ptr);
1769 *errors_ptr = nullptr;
1770 }
1771
1772 return nullptr;
1773 }
1774
1775 return reinterpret_cast<ZigClangASTUnit *>(ast_unit);
1776}
1777
1778void ZigClangErrorMsg_delete(Stage2ErrorMsg *ptr, size_t len) {
1779 free(ptr);
1780}
1781
1782void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) {
1783 delete reinterpret_cast<clang::ASTUnit *>(self);
1784}
1785
1786enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self) {
1787 auto casted = reinterpret_cast<const clang::BuiltinType *>(self);
1788 return (ZigClangBuiltinTypeKind)casted->getKind();
1789}
1790
1791bool ZigClangFunctionType_getNoReturnAttr(const struct ZigClangFunctionType *self) {
1792 auto casted = reinterpret_cast<const clang::FunctionType *>(self);
1793 return casted->getNoReturnAttr();
1794}
1795
1796enum ZigClangCallingConv ZigClangFunctionType_getCallConv(const struct ZigClangFunctionType *self) {
1797 auto casted = reinterpret_cast<const clang::FunctionType *>(self);
1798 return (ZigClangCallingConv)casted->getCallConv();
1799}
1800
1801struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClangFunctionType *self) {
1802 auto casted = reinterpret_cast<const clang::FunctionType *>(self);
1803 return bitcast(casted->getReturnType());
1804}
1805
1806bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self) {
1807 auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);
1808 return casted->isVariadic();
1809}
1810
1811unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self) {
1812 auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);
1813 return casted->getNumParams();
1814}
1815
1816struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self,
1817 unsigned index)
1818{
1819 auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);
1820 return bitcast(casted->getParamType(index));
1821}
1822
1823ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self) {
1824 auto casted = reinterpret_cast<const clang::CompoundStmt *>(self);
1825 return bitcast(casted->body_begin());
1826}
1827
1828ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self) {
1829 auto casted = reinterpret_cast<const clang::CompoundStmt *>(self);
1830 return bitcast(casted->body_end());
1831}
src/zig_clang.h+686-115
...@@ -8,14 +8,13 @@...@@ -8,14 +8,13 @@
8#ifndef ZIG_ZIG_CLANG_H8#ifndef ZIG_ZIG_CLANG_H
9#define ZIG_ZIG_CLANG_H9#define ZIG_ZIG_CLANG_H
1010
11#ifdef __cplusplus11#include "userland.h"
12#define ZIG_EXTERN_C extern "C"12#include <inttypes.h>
13#else13#include <stdbool.h>
14#define ZIG_EXTERN_C
15#endif
1614
17// ATTENTION: If you modify this file, be sure to update the corresponding15// ATTENTION: If you modify this file, be sure to update the corresponding
18// extern function declarations in the self-hosted compiler.16// extern function declarations in the self-hosted compiler file
17// src-self-hosted/clang.zig.
1918
20struct ZigClangSourceLocation {19struct ZigClangSourceLocation {
21 unsigned ID;20 unsigned ID;
...@@ -25,7 +24,14 @@ struct ZigClangQualType {...@@ -25,7 +24,14 @@ struct ZigClangQualType {
25 void *ptr;24 void *ptr;
26};25};
2726
27struct ZigClangAPValueLValueBase {
28 void *Ptr;
29 unsigned CallIndex;
30 unsigned Version;
31};
32
28struct ZigClangAPValue;33struct ZigClangAPValue;
34struct ZigClangAPSInt;
29struct ZigClangASTContext;35struct ZigClangASTContext;
30struct ZigClangASTUnit;36struct ZigClangASTUnit;
31struct ZigClangArraySubscriptExpr;37struct ZigClangArraySubscriptExpr;
...@@ -82,10 +88,10 @@ struct ZigClangSkipFunctionBodiesScope;...@@ -82,10 +88,10 @@ struct ZigClangSkipFunctionBodiesScope;
82struct ZigClangSourceManager;88struct ZigClangSourceManager;
83struct ZigClangSourceRange;89struct ZigClangSourceRange;
84struct ZigClangStmt;90struct ZigClangStmt;
85struct ZigClangStorageClass;
86struct ZigClangStringLiteral;91struct ZigClangStringLiteral;
87struct ZigClangStringRef;92struct ZigClangStringRef;
88struct ZigClangSwitchStmt;93struct ZigClangSwitchStmt;
94struct ZigClangTagDecl;
89struct ZigClangType;95struct ZigClangType;
90struct ZigClangTypedefNameDecl;96struct ZigClangTypedefNameDecl;
91struct ZigClangTypedefType;97struct ZigClangTypedefType;
...@@ -94,6 +100,9 @@ struct ZigClangUnaryOperator;...@@ -94,6 +100,9 @@ struct ZigClangUnaryOperator;
94struct ZigClangValueDecl;100struct ZigClangValueDecl;
95struct ZigClangVarDecl;101struct ZigClangVarDecl;
96struct ZigClangWhileStmt;102struct ZigClangWhileStmt;
103struct ZigClangFunctionType;
104
105typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator;
97106
98enum ZigClangBO {107enum ZigClangBO {
99 ZigClangBO_PtrMemD,108 ZigClangBO_PtrMemD,
...@@ -148,112 +157,674 @@ enum ZigClangUO {...@@ -148,112 +157,674 @@ enum ZigClangUO {
148 ZigClangUO_Coawait,157 ZigClangUO_Coawait,
149};158};
150159
151//struct ZigClangCC_AAPCS;160enum ZigClangTypeClass {
152//struct ZigClangCC_AAPCS_VFP;161 ZigClangType_Builtin,
153//struct ZigClangCC_C;162 ZigClangType_Complex,
154//struct ZigClangCC_IntelOclBicc;163 ZigClangType_Pointer,
155//struct ZigClangCC_OpenCLKernel;164 ZigClangType_BlockPointer,
156//struct ZigClangCC_PreserveAll;165 ZigClangType_LValueReference,
157//struct ZigClangCC_PreserveMost;166 ZigClangType_RValueReference,
158//struct ZigClangCC_SpirFunction;167 ZigClangType_MemberPointer,
159//struct ZigClangCC_Swift;168 ZigClangType_ConstantArray,
160//struct ZigClangCC_Win64;169 ZigClangType_IncompleteArray,
161//struct ZigClangCC_X86FastCall;170 ZigClangType_VariableArray,
162//struct ZigClangCC_X86Pascal;171 ZigClangType_DependentSizedArray,
163//struct ZigClangCC_X86RegCall;172 ZigClangType_DependentSizedExtVector,
164//struct ZigClangCC_X86StdCall;173 ZigClangType_DependentAddressSpace,
165//struct ZigClangCC_X86ThisCall;174 ZigClangType_Vector,
166//struct ZigClangCC_X86VectorCall;175 ZigClangType_DependentVector,
167//struct ZigClangCC_X86_64SysV;176 ZigClangType_ExtVector,
168177 ZigClangType_FunctionProto,
169//struct ZigClangCK_ARCConsumeObject;178 ZigClangType_FunctionNoProto,
170//struct ZigClangCK_ARCExtendBlockObject;179 ZigClangType_UnresolvedUsing,
171//struct ZigClangCK_ARCProduceObject;180 ZigClangType_Paren,
172//struct ZigClangCK_ARCReclaimReturnedObject;181 ZigClangType_Typedef,
173//struct ZigClangCK_AddressSpaceConversion;182 ZigClangType_Adjusted,
174//struct ZigClangCK_AnyPointerToBlockPointerCast;183 ZigClangType_Decayed,
175//struct ZigClangCK_ArrayToPointerDecay;184 ZigClangType_TypeOfExpr,
176//struct ZigClangCK_AtomicToNonAtomic;185 ZigClangType_TypeOf,
177//struct ZigClangCK_BaseToDerived;186 ZigClangType_Decltype,
178//struct ZigClangCK_BaseToDerivedMemberPointer;187 ZigClangType_UnaryTransform,
179//struct ZigClangCK_BitCast;188 ZigClangType_Record,
180//struct ZigClangCK_BlockPointerToObjCPointerCast;189 ZigClangType_Enum,
181//struct ZigClangCK_BooleanToSignedIntegral;190 ZigClangType_Elaborated,
182//struct ZigClangCK_BuiltinFnToFnPtr;191 ZigClangType_Attributed,
183//struct ZigClangCK_CPointerToObjCPointerCast;192 ZigClangType_TemplateTypeParm,
184//struct ZigClangCK_ConstructorConversion;193 ZigClangType_SubstTemplateTypeParm,
185//struct ZigClangCK_CopyAndAutoreleaseBlockObject;194 ZigClangType_SubstTemplateTypeParmPack,
186//struct ZigClangCK_Dependent;195 ZigClangType_TemplateSpecialization,
187//struct ZigClangCK_DerivedToBase;196 ZigClangType_Auto,
188//struct ZigClangCK_DerivedToBaseMemberPointer;197 ZigClangType_DeducedTemplateSpecialization,
189//struct ZigClangCK_Dynamic;198 ZigClangType_InjectedClassName,
190//struct ZigClangCK_FloatingCast;199 ZigClangType_DependentName,
191//struct ZigClangCK_FloatingComplexCast;200 ZigClangType_DependentTemplateSpecialization,
192//struct ZigClangCK_FloatingComplexToBoolean;201 ZigClangType_PackExpansion,
193//struct ZigClangCK_FloatingComplexToIntegralComplex;202 ZigClangType_ObjCTypeParam,
194//struct ZigClangCK_FloatingComplexToReal;203 ZigClangType_ObjCObject,
195//struct ZigClangCK_FloatingRealToComplex;204 ZigClangType_ObjCInterface,
196//struct ZigClangCK_FloatingToBoolean;205 ZigClangType_ObjCObjectPointer,
197//struct ZigClangCK_FloatingToIntegral;206 ZigClangType_Pipe,
198//struct ZigClangCK_FunctionToPointerDecay;207 ZigClangType_Atomic,
199//struct ZigClangCK_IntToOCLSampler;208};
200//struct ZigClangCK_IntegralCast;209
201//struct ZigClangCK_IntegralComplexCast;210enum ZigClangStmtClass {
202//struct ZigClangCK_IntegralComplexToBoolean;211 ZigClangStmt_NoStmtClass = 0,
203//struct ZigClangCK_IntegralComplexToFloatingComplex;212 ZigClangStmt_GCCAsmStmtClass,
204//struct ZigClangCK_IntegralComplexToReal;213 ZigClangStmt_MSAsmStmtClass,
205//struct ZigClangCK_IntegralRealToComplex;214 ZigClangStmt_AttributedStmtClass,
206//struct ZigClangCK_IntegralToBoolean;215 ZigClangStmt_BreakStmtClass,
207//struct ZigClangCK_IntegralToFloating;216 ZigClangStmt_CXXCatchStmtClass,
208//struct ZigClangCK_IntegralToPointer;217 ZigClangStmt_CXXForRangeStmtClass,
209//struct ZigClangCK_LValueBitCast;218 ZigClangStmt_CXXTryStmtClass,
210//struct ZigClangCK_LValueToRValue;219 ZigClangStmt_CapturedStmtClass,
211//struct ZigClangCK_MemberPointerToBoolean;220 ZigClangStmt_CompoundStmtClass,
212//struct ZigClangCK_NoOp;221 ZigClangStmt_ContinueStmtClass,
213//struct ZigClangCK_NonAtomicToAtomic;222 ZigClangStmt_CoreturnStmtClass,
214//struct ZigClangCK_NullToMemberPointer;223 ZigClangStmt_CoroutineBodyStmtClass,
215//struct ZigClangCK_NullToPointer;224 ZigClangStmt_DeclStmtClass,
216//struct ZigClangCK_ObjCObjectLValueCast;225 ZigClangStmt_DoStmtClass,
217//struct ZigClangCK_PointerToBoolean;226 ZigClangStmt_BinaryConditionalOperatorClass,
218//struct ZigClangCK_PointerToIntegral;227 ZigClangStmt_ConditionalOperatorClass,
219//struct ZigClangCK_ReinterpretMemberPointer;228 ZigClangStmt_AddrLabelExprClass,
220//struct ZigClangCK_ToUnion;229 ZigClangStmt_ArrayInitIndexExprClass,
221//struct ZigClangCK_ToVoid;230 ZigClangStmt_ArrayInitLoopExprClass,
222//struct ZigClangCK_UncheckedDerivedToBase;231 ZigClangStmt_ArraySubscriptExprClass,
223//struct ZigClangCK_UserDefinedConversion;232 ZigClangStmt_ArrayTypeTraitExprClass,
224//struct ZigClangCK_VectorSplat;233 ZigClangStmt_AsTypeExprClass,
225//struct ZigClangCK_ZeroToOCLEvent;234 ZigClangStmt_AtomicExprClass,
226//struct ZigClangCK_ZeroToOCLQueue;235 ZigClangStmt_BinaryOperatorClass,
227236 ZigClangStmt_CompoundAssignOperatorClass,
228//struct ZigClangETK_Class;237 ZigClangStmt_BlockExprClass,
229//struct ZigClangETK_Enum;238 ZigClangStmt_CXXBindTemporaryExprClass,
230//struct ZigClangETK_Interface;239 ZigClangStmt_CXXBoolLiteralExprClass,
231//struct ZigClangETK_None;240 ZigClangStmt_CXXConstructExprClass,
232//struct ZigClangETK_Struct;241 ZigClangStmt_CXXTemporaryObjectExprClass,
233//struct ZigClangETK_Typename;242 ZigClangStmt_CXXDefaultArgExprClass,
234//struct ZigClangETK_Union;243 ZigClangStmt_CXXDefaultInitExprClass,
235244 ZigClangStmt_CXXDeleteExprClass,
236//struct ZigClangSC_None;245 ZigClangStmt_CXXDependentScopeMemberExprClass,
237//struct ZigClangSC_PrivateExtern;246 ZigClangStmt_CXXFoldExprClass,
238//struct ZigClangSC_Static;247 ZigClangStmt_CXXInheritedCtorInitExprClass,
239248 ZigClangStmt_CXXNewExprClass,
240//struct ZigClangTU_Complete;249 ZigClangStmt_CXXNoexceptExprClass,
241250 ZigClangStmt_CXXNullPtrLiteralExprClass,
242ZIG_EXTERN_C ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *,251 ZigClangStmt_CXXPseudoDestructorExprClass,
243 ZigClangSourceLocation Loc);252 ZigClangStmt_CXXScalarValueInitExprClass,
244ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *,253 ZigClangStmt_CXXStdInitializerListExprClass,
245 ZigClangSourceLocation SpellingLoc);254 ZigClangStmt_CXXThisExprClass,
246ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *,255 ZigClangStmt_CXXThrowExprClass,
247 ZigClangSourceLocation Loc);256 ZigClangStmt_CXXTypeidExprClass,
248ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *,257 ZigClangStmt_CXXUnresolvedConstructExprClass,
249 ZigClangSourceLocation Loc);258 ZigClangStmt_CXXUuidofExprClass,
250ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *,259 ZigClangStmt_CallExprClass,
251 ZigClangSourceLocation SL);260 ZigClangStmt_CUDAKernelCallExprClass,
252261 ZigClangStmt_CXXMemberCallExprClass,
253ZIG_EXTERN_C ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext*, ZigClangQualType T);262 ZigClangStmt_CXXOperatorCallExprClass,
254263 ZigClangStmt_UserDefinedLiteralClass,
255ZIG_EXTERN_C ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *);264 ZigClangStmt_CStyleCastExprClass,
256ZIG_EXTERN_C ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *);265 ZigClangStmt_CXXFunctionalCastExprClass,
257ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *, void *context, 266 ZigClangStmt_CXXConstCastExprClass,
258 bool (*Fn)(void *context, const ZigClangDecl *decl));267 ZigClangStmt_CXXDynamicCastExprClass,
268 ZigClangStmt_CXXReinterpretCastExprClass,
269 ZigClangStmt_CXXStaticCastExprClass,
270 ZigClangStmt_ObjCBridgedCastExprClass,
271 ZigClangStmt_ImplicitCastExprClass,
272 ZigClangStmt_CharacterLiteralClass,
273 ZigClangStmt_ChooseExprClass,
274 ZigClangStmt_CompoundLiteralExprClass,
275 ZigClangStmt_ConvertVectorExprClass,
276 ZigClangStmt_CoawaitExprClass,
277 ZigClangStmt_CoyieldExprClass,
278 ZigClangStmt_DeclRefExprClass,
279 ZigClangStmt_DependentCoawaitExprClass,
280 ZigClangStmt_DependentScopeDeclRefExprClass,
281 ZigClangStmt_DesignatedInitExprClass,
282 ZigClangStmt_DesignatedInitUpdateExprClass,
283 ZigClangStmt_ExpressionTraitExprClass,
284 ZigClangStmt_ExtVectorElementExprClass,
285 ZigClangStmt_FixedPointLiteralClass,
286 ZigClangStmt_FloatingLiteralClass,
287 ZigClangStmt_ConstantExprClass,
288 ZigClangStmt_ExprWithCleanupsClass,
289 ZigClangStmt_FunctionParmPackExprClass,
290 ZigClangStmt_GNUNullExprClass,
291 ZigClangStmt_GenericSelectionExprClass,
292 ZigClangStmt_ImaginaryLiteralClass,
293 ZigClangStmt_ImplicitValueInitExprClass,
294 ZigClangStmt_InitListExprClass,
295 ZigClangStmt_IntegerLiteralClass,
296 ZigClangStmt_LambdaExprClass,
297 ZigClangStmt_MSPropertyRefExprClass,
298 ZigClangStmt_MSPropertySubscriptExprClass,
299 ZigClangStmt_MaterializeTemporaryExprClass,
300 ZigClangStmt_MemberExprClass,
301 ZigClangStmt_NoInitExprClass,
302 ZigClangStmt_OMPArraySectionExprClass,
303 ZigClangStmt_ObjCArrayLiteralClass,
304 ZigClangStmt_ObjCAvailabilityCheckExprClass,
305 ZigClangStmt_ObjCBoolLiteralExprClass,
306 ZigClangStmt_ObjCBoxedExprClass,
307 ZigClangStmt_ObjCDictionaryLiteralClass,
308 ZigClangStmt_ObjCEncodeExprClass,
309 ZigClangStmt_ObjCIndirectCopyRestoreExprClass,
310 ZigClangStmt_ObjCIsaExprClass,
311 ZigClangStmt_ObjCIvarRefExprClass,
312 ZigClangStmt_ObjCMessageExprClass,
313 ZigClangStmt_ObjCPropertyRefExprClass,
314 ZigClangStmt_ObjCProtocolExprClass,
315 ZigClangStmt_ObjCSelectorExprClass,
316 ZigClangStmt_ObjCStringLiteralClass,
317 ZigClangStmt_ObjCSubscriptRefExprClass,
318 ZigClangStmt_OffsetOfExprClass,
319 ZigClangStmt_OpaqueValueExprClass,
320 ZigClangStmt_UnresolvedLookupExprClass,
321 ZigClangStmt_UnresolvedMemberExprClass,
322 ZigClangStmt_PackExpansionExprClass,
323 ZigClangStmt_ParenExprClass,
324 ZigClangStmt_ParenListExprClass,
325 ZigClangStmt_PredefinedExprClass,
326 ZigClangStmt_PseudoObjectExprClass,
327 ZigClangStmt_ShuffleVectorExprClass,
328 ZigClangStmt_SizeOfPackExprClass,
329 ZigClangStmt_StmtExprClass,
330 ZigClangStmt_StringLiteralClass,
331 ZigClangStmt_SubstNonTypeTemplateParmExprClass,
332 ZigClangStmt_SubstNonTypeTemplateParmPackExprClass,
333 ZigClangStmt_TypeTraitExprClass,
334 ZigClangStmt_TypoExprClass,
335 ZigClangStmt_UnaryExprOrTypeTraitExprClass,
336 ZigClangStmt_UnaryOperatorClass,
337 ZigClangStmt_VAArgExprClass,
338 ZigClangStmt_ForStmtClass,
339 ZigClangStmt_GotoStmtClass,
340 ZigClangStmt_IfStmtClass,
341 ZigClangStmt_IndirectGotoStmtClass,
342 ZigClangStmt_LabelStmtClass,
343 ZigClangStmt_MSDependentExistsStmtClass,
344 ZigClangStmt_NullStmtClass,
345 ZigClangStmt_OMPAtomicDirectiveClass,
346 ZigClangStmt_OMPBarrierDirectiveClass,
347 ZigClangStmt_OMPCancelDirectiveClass,
348 ZigClangStmt_OMPCancellationPointDirectiveClass,
349 ZigClangStmt_OMPCriticalDirectiveClass,
350 ZigClangStmt_OMPFlushDirectiveClass,
351 ZigClangStmt_OMPDistributeDirectiveClass,
352 ZigClangStmt_OMPDistributeParallelForDirectiveClass,
353 ZigClangStmt_OMPDistributeParallelForSimdDirectiveClass,
354 ZigClangStmt_OMPDistributeSimdDirectiveClass,
355 ZigClangStmt_OMPForDirectiveClass,
356 ZigClangStmt_OMPForSimdDirectiveClass,
357 ZigClangStmt_OMPParallelForDirectiveClass,
358 ZigClangStmt_OMPParallelForSimdDirectiveClass,
359 ZigClangStmt_OMPSimdDirectiveClass,
360 ZigClangStmt_OMPTargetParallelForSimdDirectiveClass,
361 ZigClangStmt_OMPTargetSimdDirectiveClass,
362 ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass,
363 ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass,
364 ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
365 ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass,
366 ZigClangStmt_OMPTaskLoopDirectiveClass,
367 ZigClangStmt_OMPTaskLoopSimdDirectiveClass,
368 ZigClangStmt_OMPTeamsDistributeDirectiveClass,
369 ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass,
370 ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass,
371 ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass,
372 ZigClangStmt_OMPMasterDirectiveClass,
373 ZigClangStmt_OMPOrderedDirectiveClass,
374 ZigClangStmt_OMPParallelDirectiveClass,
375 ZigClangStmt_OMPParallelSectionsDirectiveClass,
376 ZigClangStmt_OMPSectionDirectiveClass,
377 ZigClangStmt_OMPSectionsDirectiveClass,
378 ZigClangStmt_OMPSingleDirectiveClass,
379 ZigClangStmt_OMPTargetDataDirectiveClass,
380 ZigClangStmt_OMPTargetDirectiveClass,
381 ZigClangStmt_OMPTargetEnterDataDirectiveClass,
382 ZigClangStmt_OMPTargetExitDataDirectiveClass,
383 ZigClangStmt_OMPTargetParallelDirectiveClass,
384 ZigClangStmt_OMPTargetParallelForDirectiveClass,
385 ZigClangStmt_OMPTargetTeamsDirectiveClass,
386 ZigClangStmt_OMPTargetUpdateDirectiveClass,
387 ZigClangStmt_OMPTaskDirectiveClass,
388 ZigClangStmt_OMPTaskgroupDirectiveClass,
389 ZigClangStmt_OMPTaskwaitDirectiveClass,
390 ZigClangStmt_OMPTaskyieldDirectiveClass,
391 ZigClangStmt_OMPTeamsDirectiveClass,
392 ZigClangStmt_ObjCAtCatchStmtClass,
393 ZigClangStmt_ObjCAtFinallyStmtClass,
394 ZigClangStmt_ObjCAtSynchronizedStmtClass,
395 ZigClangStmt_ObjCAtThrowStmtClass,
396 ZigClangStmt_ObjCAtTryStmtClass,
397 ZigClangStmt_ObjCAutoreleasePoolStmtClass,
398 ZigClangStmt_ObjCForCollectionStmtClass,
399 ZigClangStmt_ReturnStmtClass,
400 ZigClangStmt_SEHExceptStmtClass,
401 ZigClangStmt_SEHFinallyStmtClass,
402 ZigClangStmt_SEHLeaveStmtClass,
403 ZigClangStmt_SEHTryStmtClass,
404 ZigClangStmt_CaseStmtClass,
405 ZigClangStmt_DefaultStmtClass,
406 ZigClangStmt_SwitchStmtClass,
407 ZigClangStmt_WhileStmtClass,
408};
409
410enum ZigClangCK {
411 ZigClangCK_Dependent,
412 ZigClangCK_BitCast,
413 ZigClangCK_LValueBitCast,
414 ZigClangCK_LValueToRValue,
415 ZigClangCK_NoOp,
416 ZigClangCK_BaseToDerived,
417 ZigClangCK_DerivedToBase,
418 ZigClangCK_UncheckedDerivedToBase,
419 ZigClangCK_Dynamic,
420 ZigClangCK_ToUnion,
421 ZigClangCK_ArrayToPointerDecay,
422 ZigClangCK_FunctionToPointerDecay,
423 ZigClangCK_NullToPointer,
424 ZigClangCK_NullToMemberPointer,
425 ZigClangCK_BaseToDerivedMemberPointer,
426 ZigClangCK_DerivedToBaseMemberPointer,
427 ZigClangCK_MemberPointerToBoolean,
428 ZigClangCK_ReinterpretMemberPointer,
429 ZigClangCK_UserDefinedConversion,
430 ZigClangCK_ConstructorConversion,
431 ZigClangCK_IntegralToPointer,
432 ZigClangCK_PointerToIntegral,
433 ZigClangCK_PointerToBoolean,
434 ZigClangCK_ToVoid,
435 ZigClangCK_VectorSplat,
436 ZigClangCK_IntegralCast,
437 ZigClangCK_IntegralToBoolean,
438 ZigClangCK_IntegralToFloating,
439 ZigClangCK_FixedPointCast,
440 ZigClangCK_FixedPointToBoolean,
441 ZigClangCK_FloatingToIntegral,
442 ZigClangCK_FloatingToBoolean,
443 ZigClangCK_BooleanToSignedIntegral,
444 ZigClangCK_FloatingCast,
445 ZigClangCK_CPointerToObjCPointerCast,
446 ZigClangCK_BlockPointerToObjCPointerCast,
447 ZigClangCK_AnyPointerToBlockPointerCast,
448 ZigClangCK_ObjCObjectLValueCast,
449 ZigClangCK_FloatingRealToComplex,
450 ZigClangCK_FloatingComplexToReal,
451 ZigClangCK_FloatingComplexToBoolean,
452 ZigClangCK_FloatingComplexCast,
453 ZigClangCK_FloatingComplexToIntegralComplex,
454 ZigClangCK_IntegralRealToComplex,
455 ZigClangCK_IntegralComplexToReal,
456 ZigClangCK_IntegralComplexToBoolean,
457 ZigClangCK_IntegralComplexCast,
458 ZigClangCK_IntegralComplexToFloatingComplex,
459 ZigClangCK_ARCProduceObject,
460 ZigClangCK_ARCConsumeObject,
461 ZigClangCK_ARCReclaimReturnedObject,
462 ZigClangCK_ARCExtendBlockObject,
463 ZigClangCK_AtomicToNonAtomic,
464 ZigClangCK_NonAtomicToAtomic,
465 ZigClangCK_CopyAndAutoreleaseBlockObject,
466 ZigClangCK_BuiltinFnToFnPtr,
467 ZigClangCK_ZeroToOCLOpaqueType,
468 ZigClangCK_AddressSpaceConversion,
469 ZigClangCK_IntToOCLSampler,
470};
471
472enum ZigClangAPValueKind {
473 ZigClangAPValueUninitialized,
474 ZigClangAPValueInt,
475 ZigClangAPValueFloat,
476 ZigClangAPValueComplexInt,
477 ZigClangAPValueComplexFloat,
478 ZigClangAPValueLValue,
479 ZigClangAPValueVector,
480 ZigClangAPValueArray,
481 ZigClangAPValueStruct,
482 ZigClangAPValueUnion,
483 ZigClangAPValueMemberPointer,
484 ZigClangAPValueAddrLabelDiff,
485};
486
487enum ZigClangDeclKind {
488 ZigClangDeclAccessSpec,
489 ZigClangDeclBlock,
490 ZigClangDeclCaptured,
491 ZigClangDeclClassScopeFunctionSpecialization,
492 ZigClangDeclEmpty,
493 ZigClangDeclExport,
494 ZigClangDeclExternCContext,
495 ZigClangDeclFileScopeAsm,
496 ZigClangDeclFriend,
497 ZigClangDeclFriendTemplate,
498 ZigClangDeclImport,
499 ZigClangDeclLinkageSpec,
500 ZigClangDeclLabel,
501 ZigClangDeclNamespace,
502 ZigClangDeclNamespaceAlias,
503 ZigClangDeclObjCCompatibleAlias,
504 ZigClangDeclObjCCategory,
505 ZigClangDeclObjCCategoryImpl,
506 ZigClangDeclObjCImplementation,
507 ZigClangDeclObjCInterface,
508 ZigClangDeclObjCProtocol,
509 ZigClangDeclObjCMethod,
510 ZigClangDeclObjCProperty,
511 ZigClangDeclBuiltinTemplate,
512 ZigClangDeclClassTemplate,
513 ZigClangDeclFunctionTemplate,
514 ZigClangDeclTypeAliasTemplate,
515 ZigClangDeclVarTemplate,
516 ZigClangDeclTemplateTemplateParm,
517 ZigClangDeclEnum,
518 ZigClangDeclRecord,
519 ZigClangDeclCXXRecord,
520 ZigClangDeclClassTemplateSpecialization,
521 ZigClangDeclClassTemplatePartialSpecialization,
522 ZigClangDeclTemplateTypeParm,
523 ZigClangDeclObjCTypeParam,
524 ZigClangDeclTypeAlias,
525 ZigClangDeclTypedef,
526 ZigClangDeclUnresolvedUsingTypename,
527 ZigClangDeclUsing,
528 ZigClangDeclUsingDirective,
529 ZigClangDeclUsingPack,
530 ZigClangDeclUsingShadow,
531 ZigClangDeclConstructorUsingShadow,
532 ZigClangDeclBinding,
533 ZigClangDeclField,
534 ZigClangDeclObjCAtDefsField,
535 ZigClangDeclObjCIvar,
536 ZigClangDeclFunction,
537 ZigClangDeclCXXDeductionGuide,
538 ZigClangDeclCXXMethod,
539 ZigClangDeclCXXConstructor,
540 ZigClangDeclCXXConversion,
541 ZigClangDeclCXXDestructor,
542 ZigClangDeclMSProperty,
543 ZigClangDeclNonTypeTemplateParm,
544 ZigClangDeclVar,
545 ZigClangDeclDecomposition,
546 ZigClangDeclImplicitParam,
547 ZigClangDeclOMPCapturedExpr,
548 ZigClangDeclParmVar,
549 ZigClangDeclVarTemplateSpecialization,
550 ZigClangDeclVarTemplatePartialSpecialization,
551 ZigClangDeclEnumConstant,
552 ZigClangDeclIndirectField,
553 ZigClangDeclOMPDeclareReduction,
554 ZigClangDeclUnresolvedUsingValue,
555 ZigClangDeclOMPRequires,
556 ZigClangDeclOMPThreadPrivate,
557 ZigClangDeclObjCPropertyImpl,
558 ZigClangDeclPragmaComment,
559 ZigClangDeclPragmaDetectMismatch,
560 ZigClangDeclStaticAssert,
561 ZigClangDeclTranslationUnit,
562};
563
564enum ZigClangBuiltinTypeKind {
565 ZigClangBuiltinTypeOCLImage1dRO,
566 ZigClangBuiltinTypeOCLImage1dArrayRO,
567 ZigClangBuiltinTypeOCLImage1dBufferRO,
568 ZigClangBuiltinTypeOCLImage2dRO,
569 ZigClangBuiltinTypeOCLImage2dArrayRO,
570 ZigClangBuiltinTypeOCLImage2dDepthRO,
571 ZigClangBuiltinTypeOCLImage2dArrayDepthRO,
572 ZigClangBuiltinTypeOCLImage2dMSAARO,
573 ZigClangBuiltinTypeOCLImage2dArrayMSAARO,
574 ZigClangBuiltinTypeOCLImage2dMSAADepthRO,
575 ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO,
576 ZigClangBuiltinTypeOCLImage3dRO,
577 ZigClangBuiltinTypeOCLImage1dWO,
578 ZigClangBuiltinTypeOCLImage1dArrayWO,
579 ZigClangBuiltinTypeOCLImage1dBufferWO,
580 ZigClangBuiltinTypeOCLImage2dWO,
581 ZigClangBuiltinTypeOCLImage2dArrayWO,
582 ZigClangBuiltinTypeOCLImage2dDepthWO,
583 ZigClangBuiltinTypeOCLImage2dArrayDepthWO,
584 ZigClangBuiltinTypeOCLImage2dMSAAWO,
585 ZigClangBuiltinTypeOCLImage2dArrayMSAAWO,
586 ZigClangBuiltinTypeOCLImage2dMSAADepthWO,
587 ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO,
588 ZigClangBuiltinTypeOCLImage3dWO,
589 ZigClangBuiltinTypeOCLImage1dRW,
590 ZigClangBuiltinTypeOCLImage1dArrayRW,
591 ZigClangBuiltinTypeOCLImage1dBufferRW,
592 ZigClangBuiltinTypeOCLImage2dRW,
593 ZigClangBuiltinTypeOCLImage2dArrayRW,
594 ZigClangBuiltinTypeOCLImage2dDepthRW,
595 ZigClangBuiltinTypeOCLImage2dArrayDepthRW,
596 ZigClangBuiltinTypeOCLImage2dMSAARW,
597 ZigClangBuiltinTypeOCLImage2dArrayMSAARW,
598 ZigClangBuiltinTypeOCLImage2dMSAADepthRW,
599 ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW,
600 ZigClangBuiltinTypeOCLImage3dRW,
601 ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload,
602 ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload,
603 ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload,
604 ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload,
605 ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult,
606 ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult,
607 ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult,
608 ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult,
609 ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout,
610 ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout,
611 ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin,
612 ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin,
613 ZigClangBuiltinTypeVoid,
614 ZigClangBuiltinTypeBool,
615 ZigClangBuiltinTypeChar_U,
616 ZigClangBuiltinTypeUChar,
617 ZigClangBuiltinTypeWChar_U,
618 ZigClangBuiltinTypeChar8,
619 ZigClangBuiltinTypeChar16,
620 ZigClangBuiltinTypeChar32,
621 ZigClangBuiltinTypeUShort,
622 ZigClangBuiltinTypeUInt,
623 ZigClangBuiltinTypeULong,
624 ZigClangBuiltinTypeULongLong,
625 ZigClangBuiltinTypeUInt128,
626 ZigClangBuiltinTypeChar_S,
627 ZigClangBuiltinTypeSChar,
628 ZigClangBuiltinTypeWChar_S,
629 ZigClangBuiltinTypeShort,
630 ZigClangBuiltinTypeInt,
631 ZigClangBuiltinTypeLong,
632 ZigClangBuiltinTypeLongLong,
633 ZigClangBuiltinTypeInt128,
634 ZigClangBuiltinTypeShortAccum,
635 ZigClangBuiltinTypeAccum,
636 ZigClangBuiltinTypeLongAccum,
637 ZigClangBuiltinTypeUShortAccum,
638 ZigClangBuiltinTypeUAccum,
639 ZigClangBuiltinTypeULongAccum,
640 ZigClangBuiltinTypeShortFract,
641 ZigClangBuiltinTypeFract,
642 ZigClangBuiltinTypeLongFract,
643 ZigClangBuiltinTypeUShortFract,
644 ZigClangBuiltinTypeUFract,
645 ZigClangBuiltinTypeULongFract,
646 ZigClangBuiltinTypeSatShortAccum,
647 ZigClangBuiltinTypeSatAccum,
648 ZigClangBuiltinTypeSatLongAccum,
649 ZigClangBuiltinTypeSatUShortAccum,
650 ZigClangBuiltinTypeSatUAccum,
651 ZigClangBuiltinTypeSatULongAccum,
652 ZigClangBuiltinTypeSatShortFract,
653 ZigClangBuiltinTypeSatFract,
654 ZigClangBuiltinTypeSatLongFract,
655 ZigClangBuiltinTypeSatUShortFract,
656 ZigClangBuiltinTypeSatUFract,
657 ZigClangBuiltinTypeSatULongFract,
658 ZigClangBuiltinTypeHalf,
659 ZigClangBuiltinTypeFloat,
660 ZigClangBuiltinTypeDouble,
661 ZigClangBuiltinTypeLongDouble,
662 ZigClangBuiltinTypeFloat16,
663 ZigClangBuiltinTypeFloat128,
664 ZigClangBuiltinTypeNullPtr,
665 ZigClangBuiltinTypeObjCId,
666 ZigClangBuiltinTypeObjCClass,
667 ZigClangBuiltinTypeObjCSel,
668 ZigClangBuiltinTypeOCLSampler,
669 ZigClangBuiltinTypeOCLEvent,
670 ZigClangBuiltinTypeOCLClkEvent,
671 ZigClangBuiltinTypeOCLQueue,
672 ZigClangBuiltinTypeOCLReserveID,
673 ZigClangBuiltinTypeDependent,
674 ZigClangBuiltinTypeOverload,
675 ZigClangBuiltinTypeBoundMember,
676 ZigClangBuiltinTypePseudoObject,
677 ZigClangBuiltinTypeUnknownAny,
678 ZigClangBuiltinTypeBuiltinFn,
679 ZigClangBuiltinTypeARCUnbridgedCast,
680 ZigClangBuiltinTypeOMPArraySection,
681};
682
683enum ZigClangCallingConv {
684 ZigClangCallingConv_C, // __attribute__((cdecl))
685 ZigClangCallingConv_X86StdCall, // __attribute__((stdcall))
686 ZigClangCallingConv_X86FastCall, // __attribute__((fastcall))
687 ZigClangCallingConv_X86ThisCall, // __attribute__((thiscall))
688 ZigClangCallingConv_X86VectorCall, // __attribute__((vectorcall))
689 ZigClangCallingConv_X86Pascal, // __attribute__((pascal))
690 ZigClangCallingConv_Win64, // __attribute__((ms_abi))
691 ZigClangCallingConv_X86_64SysV, // __attribute__((sysv_abi))
692 ZigClangCallingConv_X86RegCall, // __attribute__((regcall))
693 ZigClangCallingConv_AAPCS, // __attribute__((pcs("aapcs")))
694 ZigClangCallingConv_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
695 ZigClangCallingConv_IntelOclBicc, // __attribute__((intel_ocl_bicc))
696 ZigClangCallingConv_SpirFunction, // default for OpenCL functions on SPIR target
697 ZigClangCallingConv_OpenCLKernel, // inferred for OpenCL kernels
698 ZigClangCallingConv_Swift, // __attribute__((swiftcall))
699 ZigClangCallingConv_PreserveMost, // __attribute__((preserve_most))
700 ZigClangCallingConv_PreserveAll, // __attribute__((preserve_all))
701 ZigClangCallingConv_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
702};
703
704enum ZigClangStorageClass {
705 // These are legal on both functions and variables.
706 ZigClangStorageClass_None,
707 ZigClangStorageClass_Extern,
708 ZigClangStorageClass_Static,
709 ZigClangStorageClass_PrivateExtern,
710
711 // These are only legal on variables.
712 ZigClangStorageClass_Auto,
713 ZigClangStorageClass_Register,
714};
715
716ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *,
717 struct ZigClangSourceLocation Loc);
718ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *,
719 struct ZigClangSourceLocation SpellingLoc);
720ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const struct ZigClangSourceManager *,
721 struct ZigClangSourceLocation Loc);
722ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const struct ZigClangSourceManager *,
723 struct ZigClangSourceLocation Loc);
724ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const struct ZigClangSourceManager *,
725 struct ZigClangSourceLocation SL);
726
727ZIG_EXTERN_C struct ZigClangQualType ZigClangASTContext_getPointerType(const struct ZigClangASTContext*, struct ZigClangQualType T);
728
729
730// Can return null.
731ZIG_EXTERN_C struct ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end,
732 struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path);
733ZIG_EXTERN_C void ZigClangASTUnit_delete(struct ZigClangASTUnit *);
734ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len);
735
736ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *);
737ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *);
738ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,
739 bool (*Fn)(void *context, const struct ZigClangDecl *decl));
740
741ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordType_getDecl(const struct ZigClangRecordType *record_ty);
742ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumType_getDecl(const struct ZigClangEnumType *record_ty);
743
744ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const struct ZigClangRecordDecl *record_decl);
745ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const struct ZigClangEnumDecl *);
746ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCanonicalDecl(const struct ZigClangTypedefNameDecl *);
747
748ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *);
749ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *);
750
751ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangRecordDecl_getLocation(const struct ZigClangRecordDecl *);
752ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangEnumDecl_getLocation(const struct ZigClangEnumDecl *);
753ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangTypedefNameDecl_getLocation(const struct ZigClangTypedefNameDecl *);
754ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDecl_getLocation(const struct ZigClangDecl *);
755
756ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *);
757ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *);
758ZIG_EXTERN_C bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *);
759ZIG_EXTERN_C enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *);
760ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *, unsigned i);
761ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *);
762
763ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl);
764ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const struct ZigClangRecordDecl *record_decl);
765ZIG_EXTERN_C bool ZigClangRecordDecl_isAnonymousStructOrUnion(const struct ZigClangRecordDecl *record_decl);
766
767ZIG_EXTERN_C struct ZigClangQualType ZigClangEnumDecl_getIntegerType(const struct ZigClangEnumDecl *);
768
769ZIG_EXTERN_C const char *ZigClangDecl_getName_bytes_begin(const struct ZigClangDecl *decl);
770ZIG_EXTERN_C enum ZigClangDeclKind ZigClangDecl_getKind(const struct ZigClangDecl *decl);
771ZIG_EXTERN_C const char *ZigClangDecl_getDeclKindName(const struct ZigClangDecl *decl);
772
773ZIG_EXTERN_C bool ZigClangSourceLocation_eq(struct ZigClangSourceLocation a, struct ZigClangSourceLocation b);
774
775ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const struct ZigClangTypedefType *);
776ZIG_EXTERN_C struct ZigClangQualType ZigClangTypedefNameDecl_getUnderlyingType(const struct ZigClangTypedefNameDecl *);
777
778ZIG_EXTERN_C struct ZigClangQualType ZigClangQualType_getCanonicalType(struct ZigClangQualType);
779ZIG_EXTERN_C const struct ZigClangType *ZigClangQualType_getTypePtr(struct ZigClangQualType);
780ZIG_EXTERN_C void ZigClangQualType_addConst(struct ZigClangQualType *);
781ZIG_EXTERN_C bool ZigClangQualType_eq(struct ZigClangQualType, struct ZigClangQualType);
782ZIG_EXTERN_C bool ZigClangQualType_isConstQualified(struct ZigClangQualType);
783ZIG_EXTERN_C bool ZigClangQualType_isVolatileQualified(struct ZigClangQualType);
784ZIG_EXTERN_C bool ZigClangQualType_isRestrictQualified(struct ZigClangQualType);
785
786ZIG_EXTERN_C enum ZigClangTypeClass ZigClangType_getTypeClass(const struct ZigClangType *self);
787ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct ZigClangType *self);
788ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
789ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);
790
791ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangStmt_getBeginLoc(const struct ZigClangStmt *self);
792ZIG_EXTERN_C enum ZigClangStmtClass ZigClangStmt_getStmtClass(const struct ZigClangStmt *self);
793ZIG_EXTERN_C bool ZigClangStmt_classof_Expr(const struct ZigClangStmt *self);
794
795ZIG_EXTERN_C enum ZigClangStmtClass ZigClangExpr_getStmtClass(const struct ZigClangExpr *self);
796ZIG_EXTERN_C struct ZigClangQualType ZigClangExpr_getType(const struct ZigClangExpr *self);
797ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangExpr_getBeginLoc(const struct ZigClangExpr *self);
798
799ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self);
800ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPValue_getInt(const struct ZigClangAPValue *self);
801ZIG_EXTERN_C unsigned ZigClangAPValue_getArrayInitializedElts(const struct ZigClangAPValue *self);
802ZIG_EXTERN_C const struct ZigClangAPValue *ZigClangAPValue_getArrayInitializedElt(const struct ZigClangAPValue *self, unsigned i);
803ZIG_EXTERN_C const struct ZigClangAPValue *ZigClangAPValue_getArrayFiller(const struct ZigClangAPValue *self);
804ZIG_EXTERN_C unsigned ZigClangAPValue_getArraySize(const struct ZigClangAPValue *self);
805ZIG_EXTERN_C struct ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const struct ZigClangAPValue *self);
806
807ZIG_EXTERN_C bool ZigClangAPSInt_isSigned(const struct ZigClangAPSInt *self);
808ZIG_EXTERN_C bool ZigClangAPSInt_isNegative(const struct ZigClangAPSInt *self);
809ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPSInt_negate(const struct ZigClangAPSInt *self);
810ZIG_EXTERN_C void ZigClangAPSInt_free(const struct ZigClangAPSInt *self);
811ZIG_EXTERN_C const uint64_t *ZigClangAPSInt_getRawData(const struct ZigClangAPSInt *self);
812ZIG_EXTERN_C unsigned ZigClangAPSInt_getNumWords(const struct ZigClangAPSInt *self);
813
814ZIG_EXTERN_C const struct ZigClangExpr *ZigClangAPValueLValueBase_dyn_cast_Expr(struct ZigClangAPValueLValueBase self);
815
816ZIG_EXTERN_C enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self);
817
818ZIG_EXTERN_C bool ZigClangFunctionType_getNoReturnAttr(const struct ZigClangFunctionType *self);
819ZIG_EXTERN_C enum ZigClangCallingConv ZigClangFunctionType_getCallConv(const struct ZigClangFunctionType *self);
820ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClangFunctionType *self);
821
822ZIG_EXTERN_C bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self);
823ZIG_EXTERN_C unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self);
824ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self, unsigned i);
825
826
827ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self);
828ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self);
829
259#endif830#endif
std/array_list.zig+38
...@@ -111,6 +111,17 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {...@@ -111,6 +111,17 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
111 new_item_ptr.* = item;111 new_item_ptr.* = item;
112 }112 }
113113
114 pub fn orderedRemove(self: *Self, i: usize) T {
115 const newlen = self.len - 1;
116 if (newlen == i) return self.pop();
117
118 const old_item = self.at(i);
119 for (self.items[i..newlen]) |*b, j| b.* = self.items[i + 1 + j];
120 self.items[newlen] = undefined;
121 self.len = newlen;
122 return old_item;
123 }
124
114 /// Removes the element at the specified index and returns it.125 /// Removes the element at the specified index and returns it.
115 /// The empty slot is filled from the end of the list.126 /// The empty slot is filled from the end of the list.
116 pub fn swapRemove(self: *Self, i: usize) T {127 pub fn swapRemove(self: *Self, i: usize) T {
...@@ -279,6 +290,33 @@ test "std.ArrayList.basic" {...@@ -279,6 +290,33 @@ test "std.ArrayList.basic" {
279 testing.expect(list.pop() == 33);290 testing.expect(list.pop() == 33);
280}291}
281292
293test "std.ArrayList.orderedRemove" {
294 var list = ArrayList(i32).init(debug.global_allocator);
295 defer list.deinit();
296
297 try list.append(1);
298 try list.append(2);
299 try list.append(3);
300 try list.append(4);
301 try list.append(5);
302 try list.append(6);
303 try list.append(7);
304
305 //remove from middle
306 testing.expectEqual(i32(4), list.orderedRemove(3));
307 testing.expectEqual(i32(5), list.at(3));
308 testing.expectEqual(usize(6), list.len);
309
310 //remove from end
311 testing.expectEqual(i32(7), list.orderedRemove(5));
312 testing.expectEqual(usize(5), list.len);
313
314 //remove from front
315 testing.expectEqual(i32(1), list.orderedRemove(0));
316 testing.expectEqual(i32(2), list.at(0));
317 testing.expectEqual(usize(4), list.len);
318}
319
282test "std.ArrayList.swapRemove" {320test "std.ArrayList.swapRemove" {
283 var list = ArrayList(i32).init(debug.global_allocator);321 var list = ArrayList(i32).init(debug.global_allocator);
284 defer list.deinit();322 defer list.deinit();
std/build.zig+27
...@@ -50,6 +50,8 @@ pub const Builder = struct {...@@ -50,6 +50,8 @@ pub const Builder = struct {
50 build_root: []const u8,50 build_root: []const u8,
51 cache_root: []const u8,51 cache_root: []const u8,
52 release_mode: ?builtin.Mode,52 release_mode: ?builtin.Mode,
53 override_std_dir: ?[]const u8,
54 override_lib_dir: ?[]const u8,
5355
54 pub const CStd = enum {56 pub const CStd = enum {
55 C89,57 C89,
...@@ -133,6 +135,8 @@ pub const Builder = struct {...@@ -133,6 +135,8 @@ pub const Builder = struct {
133 },135 },
134 .have_install_step = false,136 .have_install_step = false,
135 .release_mode = null,137 .release_mode = null,
138 .override_std_dir = null,
139 .override_lib_dir = null,
136 };140 };
137 self.detectNativeSystemPaths();141 self.detectNativeSystemPaths();
138 self.default_step = self.step("default", "Build the project");142 self.default_step = self.step("default", "Build the project");
...@@ -937,8 +941,11 @@ pub const LibExeObjStep = struct {...@@ -937,8 +941,11 @@ pub const LibExeObjStep = struct {
937 verbose_link: bool,941 verbose_link: bool,
938 verbose_cc: bool,942 verbose_cc: bool,
939 disable_gen_h: bool,943 disable_gen_h: bool,
944 bundle_compiler_rt: bool,
945 disable_stack_probing: bool,
940 c_std: Builder.CStd,946 c_std: Builder.CStd,
941 override_std_dir: ?[]const u8,947 override_std_dir: ?[]const u8,
948 override_lib_dir: ?[]const u8,
942 main_pkg_path: ?[]const u8,949 main_pkg_path: ?[]const u8,
943 exec_cmd_args: ?[]const ?[]const u8,950 exec_cmd_args: ?[]const ?[]const u8,
944 name_prefix: []const u8,951 name_prefix: []const u8,
...@@ -1039,11 +1046,14 @@ pub const LibExeObjStep = struct {...@@ -1039,11 +1046,14 @@ pub const LibExeObjStep = struct {
1039 .c_std = Builder.CStd.C99,1046 .c_std = Builder.CStd.C99,
1040 .system_linker_hack = false,1047 .system_linker_hack = false,
1041 .override_std_dir = null,1048 .override_std_dir = null,
1049 .override_lib_dir = null,
1042 .main_pkg_path = null,1050 .main_pkg_path = null,
1043 .exec_cmd_args = null,1051 .exec_cmd_args = null,
1044 .name_prefix = "",1052 .name_prefix = "",
1045 .filter = null,1053 .filter = null,
1046 .disable_gen_h = false,1054 .disable_gen_h = false,
1055 .bundle_compiler_rt = false,
1056 .disable_stack_probing = false,
1047 .output_dir = null,1057 .output_dir = null,
1048 .need_system_paths = false,1058 .need_system_paths = false,
1049 .single_threaded = false,1059 .single_threaded = false,
...@@ -1446,6 +1456,12 @@ pub const LibExeObjStep = struct {...@@ -1446,6 +1456,12 @@ pub const LibExeObjStep = struct {
1446 if (self.disable_gen_h) {1456 if (self.disable_gen_h) {
1447 try zig_args.append("--disable-gen-h");1457 try zig_args.append("--disable-gen-h");
1448 }1458 }
1459 if (self.bundle_compiler_rt) {
1460 try zig_args.append("--bundle-compiler-rt");
1461 }
1462 if (self.disable_stack_probing) {
1463 try zig_args.append("--disable-stack-probing");
1464 }
14491465
1450 switch (self.target) {1466 switch (self.target) {
1451 Target.Native => {},1467 Target.Native => {},
...@@ -1528,6 +1544,17 @@ pub const LibExeObjStep = struct {...@@ -1528,6 +1544,17 @@ pub const LibExeObjStep = struct {
1528 if (self.override_std_dir) |dir| {1544 if (self.override_std_dir) |dir| {
1529 try zig_args.append("--override-std-dir");1545 try zig_args.append("--override-std-dir");
1530 try zig_args.append(builder.pathFromRoot(dir));1546 try zig_args.append(builder.pathFromRoot(dir));
1547 } else if (self.builder.override_std_dir) |dir| {
1548 try zig_args.append("--override-std-dir");
1549 try zig_args.append(builder.pathFromRoot(dir));
1550 }
1551
1552 if (self.override_lib_dir) |dir| {
1553 try zig_args.append("--override-lib-dir");
1554 try zig_args.append(builder.pathFromRoot(dir));
1555 } else if (self.builder.override_lib_dir) |dir| {
1556 try zig_args.append("--override-lib-dir");
1557 try zig_args.append(builder.pathFromRoot(dir));
1531 }1558 }
15321559
1533 if (self.main_pkg_path) |dir| {1560 if (self.main_pkg_path) |dir| {
std/c.zig+6
...@@ -12,6 +12,12 @@ pub use switch (builtin.os) {...@@ -12,6 +12,12 @@ pub use switch (builtin.os) {
1212
13// TODO https://github.com/ziglang/zig/issues/265 on this whole file13// TODO https://github.com/ziglang/zig/issues/265 on this whole file
1414
15pub const FILE = @OpaqueType();
16pub extern "c" fn fopen(filename: [*]const u8, modes: [*]const u8) ?*FILE;
17pub extern "c" fn fclose(stream: *FILE) c_int;
18pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
19pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
20
15pub extern "c" fn abort() noreturn;21pub extern "c" fn abort() noreturn;
16pub extern "c" fn exit(code: c_int) noreturn;22pub extern "c" fn exit(code: c_int) noreturn;
17pub extern "c" fn isatty(fd: c_int) c_int;23pub extern "c" fn isatty(fd: c_int) c_int;
std/c/freebsd.zig+27-5
...@@ -42,14 +42,36 @@ pub const pthread_attr_t = extern struct {...@@ -42,14 +42,36 @@ pub const pthread_attr_t = extern struct {
42};42};
4343
44pub const msghdr = extern struct {44pub const msghdr = extern struct {
45 msg_name: *u8,45 /// optional address
46 msg_name: ?*sockaddr,
47 /// size of address
46 msg_namelen: socklen_t,48 msg_namelen: socklen_t,
47 msg_iov: *iovec,49 /// scatter/gather array
50 msg_iov: [*]iovec,
51 /// # elements in msg_iov
48 msg_iovlen: i32,52 msg_iovlen: i32,
49 __pad1: i32,53 /// ancillary data
50 msg_control: *u8,54 msg_control: ?*c_void,
55 /// ancillary data buffer len
51 msg_controllen: socklen_t,56 msg_controllen: socklen_t,
52 __pad2: socklen_t,57 /// flags on received message
58 msg_flags: i32,
59};
60
61pub const msghdr_const = extern struct {
62 /// optional address
63 msg_name: ?*const sockaddr,
64 /// size of address
65 msg_namelen: socklen_t,
66 /// scatter/gather array
67 msg_iov: [*]iovec_const,
68 /// # elements in msg_iov
69 msg_iovlen: i32,
70 /// ancillary data
71 msg_control: ?*c_void,
72 /// ancillary data buffer len
73 msg_controllen: socklen_t,
74 /// flags on received message
53 msg_flags: i32,75 msg_flags: i32,
54};76};
5577
std/c/linux.zig+4
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1const linux = @import("../os/linux.zig");
1pub use @import("../os/linux/errno.zig");2pub use @import("../os/linux/errno.zig");
23
3pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;4pub 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 {...@@ -11,3 +12,6 @@ pub const pthread_attr_t = extern struct {
1112
12/// See std.elf for constants for this13/// See std.elf for constants for this
13pub extern fn getauxval(__type: c_ulong) c_ulong;14pub extern fn getauxval(__type: c_ulong) c_ulong;
15
16pub const dl_iterate_phdr_callback = extern fn (info: *linux.dl_phdr_info, size: usize, data: ?*c_void) c_int;
17pub extern fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
std/c/netbsd.zig+27-5
...@@ -42,14 +42,36 @@ pub const pthread_attr_t = extern struct {...@@ -42,14 +42,36 @@ pub const pthread_attr_t = extern struct {
42};42};
4343
44pub const msghdr = extern struct {44pub const msghdr = extern struct {
45 msg_name: *u8,45 /// optional address
46 msg_name: ?*sockaddr,
47 /// size of address
46 msg_namelen: socklen_t,48 msg_namelen: socklen_t,
47 msg_iov: *iovec,49 /// scatter/gather array
50 msg_iov: [*]iovec,
51 /// # elements in msg_iov
48 msg_iovlen: i32,52 msg_iovlen: i32,
49 __pad1: i32,53 /// ancillary data
50 msg_control: *u8,54 msg_control: ?*c_void,
55 /// ancillary data buffer len
51 msg_controllen: socklen_t,56 msg_controllen: socklen_t,
52 __pad2: socklen_t,57 /// flags on received message
58 msg_flags: i32,
59};
60
61pub const msghdr_const = extern struct {
62 /// optional address
63 msg_name: ?*const sockaddr,
64 /// size of address
65 msg_namelen: socklen_t,
66 /// scatter/gather array
67 msg_iov: [*]iovec_const,
68 /// # elements in msg_iov
69 msg_iovlen: i32,
70 /// ancillary data
71 msg_control: ?*c_void,
72 /// ancillary data buffer len
73 msg_controllen: socklen_t,
74 /// flags on received message
53 msg_flags: i32,75 msg_flags: i32,
54};76};
5577
std/crypto/chacha20.zig+3-2
...@@ -142,7 +142,7 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]...@@ -142,7 +142,7 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
142 assert(in.len >= out.len);142 assert(in.len >= out.len);
143 assert(counter +% (in.len >> 6) >= counter);143 assert(counter +% (in.len >> 6) >= counter);
144144
145 var cursor: u64 = 0;145 var cursor: usize = 0;
146 var k: [8]u32 = undefined;146 var k: [8]u32 = undefined;
147 var c: [4]u32 = undefined;147 var c: [4]u32 = undefined;
148148
...@@ -161,7 +161,8 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]...@@ -161,7 +161,8 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
161 c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);161 c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
162162
163 const block_size = (1 << 6);163 const block_size = (1 << 6);
164 const big_block = (block_size << 32);164 // The full block size is greater than the address space on a 32bit machine
165 const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize);
165166
166 // first partial big block167 // first partial big block
167 if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) {168 if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) {
std/debug.zig+344-286
...@@ -13,6 +13,8 @@ const ArrayList = std.ArrayList;...@@ -13,6 +13,8 @@ const ArrayList = std.ArrayList;
13const builtin = @import("builtin");13const builtin = @import("builtin");
14const maxInt = std.math.maxInt;14const maxInt = std.math.maxInt;
1515
16const leb = @import("debug/leb128.zig");
17
16pub const FailingAllocator = @import("debug/failing_allocator.zig").FailingAllocator;18pub const FailingAllocator = @import("debug/failing_allocator.zig").FailingAllocator;
17pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator;19pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator;
1820
...@@ -214,14 +216,14 @@ pub fn writeStackTrace(...@@ -214,14 +216,14 @@ pub fn writeStackTrace(
214 tty_color: bool,216 tty_color: bool,
215) !void {217) !void {
216 var frame_index: usize = 0;218 var frame_index: usize = 0;
217 var frames_left: usize = stack_trace.index;219 var frames_left: usize = std.math.min(stack_trace.index, stack_trace.instruction_addresses.len);
218220
219 while (frames_left != 0) : ({221 while (frames_left != 0) : ({
220 frames_left -= 1;222 frames_left -= 1;
221 frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;223 frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
222 }) {224 }) {
223 const return_address = stack_trace.instruction_addresses[frame_index];225 const return_address = stack_trace.instruction_addresses[frame_index];
224 try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);226 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color);
225 }227 }
226}228}
227229
...@@ -263,7 +265,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color...@@ -263,7 +265,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color
263 }265 }
264 var it = StackIterator.init(start_addr);266 var it = StackIterator.init(start_addr);
265 while (it.next()) |return_address| {267 while (it.next()) |return_address| {
266 try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);268 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color);
267 }269 }
268}270}
269271
...@@ -376,7 +378,6 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -376,7 +378,6 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
376 // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records)378 // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records)
377 // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in,379 // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in,
378 // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection.380 // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection.
379
380 const subsection_end_index = sect_offset + subsect_hdr.Length;381 const subsection_end_index = sect_offset + subsect_hdr.Length;
381382
382 while (line_index < subsection_end_index) {383 while (line_index < subsection_end_index) {
...@@ -690,9 +691,9 @@ pub fn printSourceAtAddressDwarf(...@@ -690,9 +691,9 @@ pub fn printSourceAtAddressDwarf(
690 return;691 return;
691 };692 };
692 const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);693 const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
693 if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| {694 if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address)) |line_info| {
694 defer line_info.deinit();695 defer line_info.deinit();
695 const symbol_name = "???";696 const symbol_name = getSymbolNameDwarf(debug_info, address) orelse "???";
696 try printLineInfo(697 try printLineInfo(
697 out_stream,698 out_stream,
698 line_info,699 line_info,
...@@ -969,6 +970,8 @@ fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Sec...@@ -969,6 +970,8 @@ fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Sec
969pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void {970pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void {
970 di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator);971 di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator);
971 di.compile_unit_list = ArrayList(CompileUnit).init(allocator);972 di.compile_unit_list = ArrayList(CompileUnit).init(allocator);
973 di.func_list = ArrayList(Func).init(allocator);
974 try scanAllFunctions(di);
972 try scanAllCompileUnits(di);975 try scanAllCompileUnits(di);
973}976}
974977
...@@ -992,6 +995,7 @@ pub fn openElfDebugInfo(...@@ -992,6 +995,7 @@ pub fn openElfDebugInfo(
992 .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")),995 .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")),
993 .abbrev_table_list = undefined,996 .abbrev_table_list = undefined,
994 .compile_unit_list = undefined,997 .compile_unit_list = undefined,
998 .func_list = undefined,
995 };999 };
996 try openDwarfDebugInfo(&di, allocator);1000 try openDwarfDebugInfo(&di, allocator);
997 return di;1001 return di;
...@@ -1162,6 +1166,7 @@ pub const DwarfInfo = struct {...@@ -1162,6 +1166,7 @@ pub const DwarfInfo = struct {
1162 debug_ranges: ?Section,1166 debug_ranges: ?Section,
1163 abbrev_table_list: ArrayList(AbbrevTableHeader),1167 abbrev_table_list: ArrayList(AbbrevTableHeader),
1164 compile_unit_list: ArrayList(CompileUnit),1168 compile_unit_list: ArrayList(CompileUnit),
1169 func_list: ArrayList(Func),
11651170
1166 pub const Section = struct {1171 pub const Section = struct {
1167 offset: usize,1172 offset: usize,
...@@ -1178,7 +1183,7 @@ pub const DwarfInfo = struct {...@@ -1178,7 +1183,7 @@ pub const DwarfInfo = struct {
1178};1183};
11791184
1180pub const DebugInfo = switch (builtin.os) {1185pub const DebugInfo = switch (builtin.os) {
1181 builtin.Os.macosx => struct {1186 builtin.Os.macosx, builtin.Os.ios => struct {
1182 symbols: []const MachoSymbol,1187 symbols: []const MachoSymbol,
1183 strings: []const u8,1188 strings: []const u8,
1184 ofiles: OFileTable,1189 ofiles: OFileTable,
...@@ -1213,7 +1218,6 @@ const CompileUnit = struct {...@@ -1213,7 +1218,6 @@ const CompileUnit = struct {
1213 version: u16,1218 version: u16,
1214 is_64: bool,1219 is_64: bool,
1215 die: *Die,1220 die: *Die,
1216 index: usize,
1217 pc_range: ?PcRange,1221 pc_range: ?PcRange,
1218};1222};
12191223
...@@ -1244,21 +1248,19 @@ const FormValue = union(enum) {...@@ -1244,21 +1248,19 @@ const FormValue = union(enum) {
1244 ExprLoc: []u8,1248 ExprLoc: []u8,
1245 Flag: bool,1249 Flag: bool,
1246 SecOffset: u64,1250 SecOffset: u64,
1247 Ref: []u8,1251 Ref: u64,
1248 RefAddr: u64,1252 RefAddr: u64,
1249 RefSig8: u64,
1250 String: []u8,1253 String: []u8,
1251 StrPtr: u64,1254 StrPtr: u64,
1252};1255};
12531256
1254const Constant = struct {1257const Constant = struct {
1255 payload: []u8,1258 payload: u64,
1256 signed: bool,1259 signed: bool,
12571260
1258 fn asUnsignedLe(self: *const Constant) !u64 {1261 fn asUnsignedLe(self: *const Constant) !u64 {
1259 if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
1260 if (self.signed) return error.InvalidDebugInfo;1262 if (self.signed) return error.InvalidDebugInfo;
1261 return mem.readVarInt(u64, self.payload, builtin.Endian.Little);1263 return self.payload;
1262 }1264 }
1263};1265};
12641266
...@@ -1304,6 +1306,14 @@ const Die = struct {...@@ -1304,6 +1306,14 @@ const Die = struct {
1304 };1306 };
1305 }1307 }
13061308
1309 fn getAttrRef(self: *const Die, id: u64) !u64 {
1310 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
1311 return switch (form_value.*) {
1312 FormValue.Ref => |value| value,
1313 else => error.InvalidDebugInfo,
1314 };
1315 }
1316
1307 fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 {1317 fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 {
1308 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;1318 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
1309 return switch (form_value.*) {1319 return switch (form_value.*) {
...@@ -1443,11 +1453,18 @@ fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !...@@ -1443,11 +1453,18 @@ fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !
1443 return parseFormValueBlockLen(allocator, in_stream, block_len);1453 return parseFormValueBlockLen(allocator, in_stream, block_len);
1444}1454}
14451455
1446fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue {1456fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, comptime size: i32) !FormValue {
1447 return FormValue{1457 return FormValue{
1448 .Const = Constant{1458 .Const = Constant{
1449 .signed = signed,1459 .signed = signed,
1450 .payload = try readAllocBytes(allocator, in_stream, size),1460 .payload = switch (size) {
1461 1 => try in_stream.readIntLittle(u8),
1462 2 => try in_stream.readIntLittle(u16),
1463 4 => try in_stream.readIntLittle(u32),
1464 8 => try in_stream.readIntLittle(u64),
1465 -1 => if (signed) @bitCast(u64, try leb.readILEB128(i64, in_stream)) else try leb.readULEB128(u64, in_stream),
1466 else => @compileError("Invalid size"),
1467 },
1451 },1468 },
1452 };1469 };
1453}1470}
...@@ -1460,14 +1477,17 @@ fn parseFormValueTargetAddrSize(in_stream: var) !u64 {...@@ -1460,14 +1477,17 @@ fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
1460 return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable;1477 return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable;
1461}1478}
14621479
1463fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {1480fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue {
1464 const buf = try readAllocBytes(allocator, in_stream, size);1481 return FormValue{
1465 return FormValue{ .Ref = buf };1482 .Ref = switch (size) {
1466}1483 1 => try in_stream.readIntLittle(u8),
14671484 2 => try in_stream.readIntLittle(u16),
1468fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {1485 4 => try in_stream.readIntLittle(u32),
1469 const block_len = try in_stream.readIntLittle(T);1486 8 => try in_stream.readIntLittle(u64),
1470 return parseFormValueRefLen(allocator, in_stream, block_len);1487 -1 => try leb.readULEB128(u64, in_stream),
1488 else => unreachable,
1489 },
1490 };
1471}1491}
14721492
1473fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {1493fn 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...@@ -1477,7 +1497,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
1477 DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),1497 DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
1478 DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),1498 DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
1479 DW.FORM_block => x: {1499 DW.FORM_block => x: {
1480 const block_len = try readULeb128(in_stream);1500 const block_len = try leb.readULEB128(usize, in_stream);
1481 return parseFormValueBlockLen(allocator, in_stream, block_len);1501 return parseFormValueBlockLen(allocator, in_stream, block_len);
1482 },1502 },
1483 DW.FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1),1503 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...@@ -1485,12 +1505,11 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
1485 DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),1505 DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),
1486 DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),1506 DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),
1487 DW.FORM_udata, DW.FORM_sdata => {1507 DW.FORM_udata, DW.FORM_sdata => {
1488 const block_len = try readULeb128(in_stream);
1489 const signed = form_id == DW.FORM_sdata;1508 const signed = form_id == DW.FORM_sdata;
1490 return parseFormValueConstant(allocator, in_stream, signed, block_len);1509 return parseFormValueConstant(allocator, in_stream, signed, -1);
1491 },1510 },
1492 DW.FORM_exprloc => {1511 DW.FORM_exprloc => {
1493 const size = try readULeb128(in_stream);1512 const size = try leb.readULEB128(usize, in_stream);
1494 const buf = try readAllocBytes(allocator, in_stream, size);1513 const buf = try readAllocBytes(allocator, in_stream, size);
1495 return FormValue{ .ExprLoc = buf };1514 return FormValue{ .ExprLoc = buf };
1496 },1515 },
...@@ -1498,22 +1517,19 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64...@@ -1498,22 +1517,19 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
1498 DW.FORM_flag_present => FormValue{ .Flag = true },1517 DW.FORM_flag_present => FormValue{ .Flag = true },
1499 DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },1518 DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
15001519
1501 DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),1520 DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, 1),
1502 DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),1521 DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, 2),
1503 DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, u32),1522 DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, 4),
1504 DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, u64),1523 DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, 8),
1505 DW.FORM_ref_udata => {1524 DW.FORM_ref_udata => parseFormValueRef(allocator, in_stream, -1),
1506 const ref_len = try readULeb128(in_stream);
1507 return parseFormValueRefLen(allocator, in_stream, ref_len);
1508 },
15091525
1510 DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },1526 DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
1511 DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) },1527 DW.FORM_ref_sig8 => FormValue{ .Ref = try in_stream.readIntLittle(u64) },
15121528
1513 DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },1529 DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
1514 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },1530 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
1515 DW.FORM_indirect => {1531 DW.FORM_indirect => {
1516 const child_form_id = try readULeb128(in_stream);1532 const child_form_id = try leb.readULEB128(u64, in_stream);
1517 return parseFormValue(allocator, in_stream, child_form_id, is_64);1533 return parseFormValue(allocator, in_stream, child_form_id, is_64);
1518 },1534 },
1519 else => error.InvalidDebugInfo,1535 else => error.InvalidDebugInfo,
...@@ -1523,19 +1539,19 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64...@@ -1523,19 +1539,19 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
1523fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {1539fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {
1524 var result = AbbrevTable.init(di.allocator());1540 var result = AbbrevTable.init(di.allocator());
1525 while (true) {1541 while (true) {
1526 const abbrev_code = try readULeb128(di.dwarf_in_stream);1542 const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
1527 if (abbrev_code == 0) return result;1543 if (abbrev_code == 0) return result;
1528 try result.append(AbbrevTableEntry{1544 try result.append(AbbrevTableEntry{
1529 .abbrev_code = abbrev_code,1545 .abbrev_code = abbrev_code,
1530 .tag_id = try readULeb128(di.dwarf_in_stream),1546 .tag_id = try leb.readULEB128(u64, di.dwarf_in_stream),
1531 .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes,1547 .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes,
1532 .attrs = ArrayList(AbbrevAttr).init(di.allocator()),1548 .attrs = ArrayList(AbbrevAttr).init(di.allocator()),
1533 });1549 });
1534 const attrs = &result.items[result.len - 1].attrs;1550 const attrs = &result.items[result.len - 1].attrs;
15351551
1536 while (true) {1552 while (true) {
1537 const attr_id = try readULeb128(di.dwarf_in_stream);1553 const attr_id = try leb.readULEB128(u64, di.dwarf_in_stream);
1538 const form_id = try readULeb128(di.dwarf_in_stream);1554 const form_id = try leb.readULEB128(u64, di.dwarf_in_stream);
1539 if (attr_id == 0 and form_id == 0) break;1555 if (attr_id == 0 and form_id == 0) break;
1540 try attrs.append(AbbrevAttr{1556 try attrs.append(AbbrevAttr{
1541 .attr_id = attr_id,1557 .attr_id = attr_id,
...@@ -1568,8 +1584,28 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con...@@ -1568,8 +1584,28 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
1568 return null;1584 return null;
1569}1585}
15701586
1587fn parseDie1(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Die {
1588 const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
1589 if (abbrev_code == 0) return null;
1590 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
1591
1592 var result = Die{
1593 .tag_id = table_entry.tag_id,
1594 .has_children = table_entry.has_children,
1595 .attrs = ArrayList(Die.Attr).init(di.allocator()),
1596 };
1597 try result.attrs.resize(table_entry.attrs.len);
1598 for (table_entry.attrs.toSliceConst()) |attr, i| {
1599 result.attrs.items[i] = Die.Attr{
1600 .id = attr.attr_id,
1601 .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64),
1602 };
1603 }
1604 return result;
1605}
1606
1571fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {1607fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
1572 const abbrev_code = try readULeb128(di.dwarf_in_stream);1608 const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
1573 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;1609 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
15741610
1575 var result = Die{1611 var result = Die{
...@@ -1682,9 +1718,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u...@@ -1682,9 +1718,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
1682 while (true) {1718 while (true) {
1683 const file_name = readStringMem(&ptr);1719 const file_name = readStringMem(&ptr);
1684 if (file_name.len == 0) break;1720 if (file_name.len == 0) break;
1685 const dir_index = try readULeb128Mem(&ptr);1721 const dir_index = try leb.readULEB128Mem(usize, &ptr);
1686 const mtime = try readULeb128Mem(&ptr);1722 const mtime = try leb.readULEB128Mem(usize, &ptr);
1687 const len_bytes = try readULeb128Mem(&ptr);1723 const len_bytes = try leb.readULEB128Mem(usize, &ptr);
1688 try file_entries.append(FileEntry{1724 try file_entries.append(FileEntry{
1689 .file_name = file_name,1725 .file_name = file_name,
1690 .dir_index = dir_index,1726 .dir_index = dir_index,
...@@ -1698,7 +1734,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u...@@ -1698,7 +1734,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
1698 const opcode = readByteMem(&ptr);1734 const opcode = readByteMem(&ptr);
16991735
1700 if (opcode == DW.LNS_extended_op) {1736 if (opcode == DW.LNS_extended_op) {
1701 const op_size = try readULeb128Mem(&ptr);1737 const op_size = try leb.readULEB128Mem(u64, &ptr);
1702 if (op_size < 1) return error.InvalidDebugInfo;1738 if (op_size < 1) return error.InvalidDebugInfo;
1703 var sub_op = readByteMem(&ptr);1739 var sub_op = readByteMem(&ptr);
1704 switch (sub_op) {1740 switch (sub_op) {
...@@ -1713,9 +1749,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u...@@ -1713,9 +1749,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
1713 },1749 },
1714 DW.LNE_define_file => {1750 DW.LNE_define_file => {
1715 const file_name = readStringMem(&ptr);1751 const file_name = readStringMem(&ptr);
1716 const dir_index = try readULeb128Mem(&ptr);1752 const dir_index = try leb.readULEB128Mem(usize, &ptr);
1717 const mtime = try readULeb128Mem(&ptr);1753 const mtime = try leb.readULEB128Mem(usize, &ptr);
1718 const len_bytes = try readULeb128Mem(&ptr);1754 const len_bytes = try leb.readULEB128Mem(usize, &ptr);
1719 try file_entries.append(FileEntry{1755 try file_entries.append(FileEntry{
1720 .file_name = file_name,1756 .file_name = file_name,
1721 .dir_index = dir_index,1757 .dir_index = dir_index,
...@@ -1743,19 +1779,19 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u...@@ -1743,19 +1779,19 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
1743 prog.basic_block = false;1779 prog.basic_block = false;
1744 },1780 },
1745 DW.LNS_advance_pc => {1781 DW.LNS_advance_pc => {
1746 const arg = try readULeb128Mem(&ptr);1782 const arg = try leb.readULEB128Mem(u64, &ptr);
1747 prog.address += arg * minimum_instruction_length;1783 prog.address += arg * minimum_instruction_length;
1748 },1784 },
1749 DW.LNS_advance_line => {1785 DW.LNS_advance_line => {
1750 const arg = try readILeb128Mem(&ptr);1786 const arg = try leb.readILEB128Mem(i64, &ptr);
1751 prog.line += arg;1787 prog.line += arg;
1752 },1788 },
1753 DW.LNS_set_file => {1789 DW.LNS_set_file => {
1754 const arg = try readULeb128Mem(&ptr);1790 const arg = try leb.readULEB128Mem(u64, &ptr);
1755 prog.file = arg;1791 prog.file = arg;
1756 },1792 },
1757 DW.LNS_set_column => {1793 DW.LNS_set_column => {
1758 const arg = try readULeb128Mem(&ptr);1794 const arg = try leb.readULEB128Mem(u64, &ptr);
1759 prog.column = arg;1795 prog.column = arg;
1760 },1796 },
1761 DW.LNS_negate_stmt => {1797 DW.LNS_negate_stmt => {
...@@ -1787,182 +1823,292 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u...@@ -1787,182 +1823,292 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
17871823
1788fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {1824fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
1789 const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);1825 const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);
1826 const line_info_offset = try compile_unit.die.getAttrSecOffset(DW.AT_stmt_list);
17901827
1791 const debug_line_end = di.debug_line.offset + di.debug_line.size;1828 assert(line_info_offset < di.debug_line.size);
1792 var this_offset = di.debug_line.offset;
1793 var this_index: usize = 0;
17941829
1795 while (this_offset < debug_line_end) : (this_index += 1) {1830 try di.dwarf_seekable_stream.seekTo(di.debug_line.offset + line_info_offset);
1796 try di.dwarf_seekable_stream.seekTo(this_offset);
17971831
1798 var is_64: bool = undefined;1832 var is_64: bool = undefined;
1799 const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);1833 const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
1800 if (unit_length == 0) return error.MissingDebugInfo;1834 if (unit_length == 0) {
1801 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));1835 return error.MissingDebugInfo;
1836 }
1837 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
18021838
1803 if (compile_unit.index != this_index) {1839 const version = try di.dwarf_in_stream.readInt(u16, di.endian);
1804 this_offset += next_offset;1840 // TODO support 3 and 5
1805 continue;1841 if (version != 2 and version != 4) return error.InvalidDebugInfo;
1806 }
18071842
1808 const version = try di.dwarf_in_stream.readInt(u16, di.endian);1843 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);
1809 // TODO support 3 and 51844 const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
1810 if (version != 2 and version != 4) return error.InvalidDebugInfo;1845
1846 const minimum_instruction_length = try di.dwarf_in_stream.readByte();
1847 if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
1848
1849 if (version >= 4) {
1850 // maximum_operations_per_instruction
1851 _ = try di.dwarf_in_stream.readByte();
1852 }
1853
1854 const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0;
1855 const line_base = try di.dwarf_in_stream.readByteSigned();
1856
1857 const line_range = try di.dwarf_in_stream.readByte();
1858 if (line_range == 0) return error.InvalidDebugInfo;
18111859
1812 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);1860 const opcode_base = try di.dwarf_in_stream.readByte();
1813 const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
18141861
1815 const minimum_instruction_length = try di.dwarf_in_stream.readByte();1862 const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);
1816 if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
18171863
1818 if (version >= 4) {1864 {
1819 // maximum_operations_per_instruction1865 var i: usize = 0;
1820 _ = try di.dwarf_in_stream.readByte();1866 while (i < opcode_base - 1) : (i += 1) {
1867 standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte();
1821 }1868 }
1869 }
18221870
1823 const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0;1871 var include_directories = ArrayList([]u8).init(di.allocator());
1824 const line_base = try di.dwarf_in_stream.readByteSigned();1872 try include_directories.append(compile_unit_cwd);
1873 while (true) {
1874 const dir = try di.readString();
1875 if (dir.len == 0) break;
1876 try include_directories.append(dir);
1877 }
1878
1879 var file_entries = ArrayList(FileEntry).init(di.allocator());
1880 var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address);
18251881
1826 const line_range = try di.dwarf_in_stream.readByte();1882 while (true) {
1827 if (line_range == 0) return error.InvalidDebugInfo;1883 const file_name = try di.readString();
1884 if (file_name.len == 0) break;
1885 const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream);
1886 const mtime = try leb.readULEB128(usize, di.dwarf_in_stream);
1887 const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream);
1888 try file_entries.append(FileEntry{
1889 .file_name = file_name,
1890 .dir_index = dir_index,
1891 .mtime = mtime,
1892 .len_bytes = len_bytes,
1893 });
1894 }
18281895
1829 const opcode_base = try di.dwarf_in_stream.readByte();1896 try di.dwarf_seekable_stream.seekTo(prog_start_offset);
18301897
1831 const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);1898 while (true) {
1899 const opcode = try di.dwarf_in_stream.readByte();
18321900
1833 {1901 if (opcode == DW.LNS_extended_op) {
1834 var i: usize = 0;1902 const op_size = try leb.readULEB128(u64, di.dwarf_in_stream);
1835 while (i < opcode_base - 1) : (i += 1) {1903 if (op_size < 1) return error.InvalidDebugInfo;
1836 standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte();1904 var sub_op = try di.dwarf_in_stream.readByte();
1905 switch (sub_op) {
1906 DW.LNE_end_sequence => {
1907 prog.end_sequence = true;
1908 if (try prog.checkLineMatch()) |info| return info;
1909 return error.MissingDebugInfo;
1910 },
1911 DW.LNE_set_address => {
1912 const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
1913 prog.address = addr;
1914 },
1915 DW.LNE_define_file => {
1916 const file_name = try di.readString();
1917 const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream);
1918 const mtime = try leb.readULEB128(usize, di.dwarf_in_stream);
1919 const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream);
1920 try file_entries.append(FileEntry{
1921 .file_name = file_name,
1922 .dir_index = dir_index,
1923 .mtime = mtime,
1924 .len_bytes = len_bytes,
1925 });
1926 },
1927 else => {
1928 const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
1929 try di.dwarf_seekable_stream.seekForward(fwd_amt);
1930 },
1931 }
1932 } else if (opcode >= opcode_base) {
1933 // special opcodes
1934 const adjusted_opcode = opcode - opcode_base;
1935 const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range);
1936 const inc_line = i32(line_base) + i32(adjusted_opcode % line_range);
1937 prog.line += inc_line;
1938 prog.address += inc_addr;
1939 if (try prog.checkLineMatch()) |info| return info;
1940 prog.basic_block = false;
1941 } else {
1942 switch (opcode) {
1943 DW.LNS_copy => {
1944 if (try prog.checkLineMatch()) |info| return info;
1945 prog.basic_block = false;
1946 },
1947 DW.LNS_advance_pc => {
1948 const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
1949 prog.address += arg * minimum_instruction_length;
1950 },
1951 DW.LNS_advance_line => {
1952 const arg = try leb.readILEB128(i64, di.dwarf_in_stream);
1953 prog.line += arg;
1954 },
1955 DW.LNS_set_file => {
1956 const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
1957 prog.file = arg;
1958 },
1959 DW.LNS_set_column => {
1960 const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
1961 prog.column = arg;
1962 },
1963 DW.LNS_negate_stmt => {
1964 prog.is_stmt = !prog.is_stmt;
1965 },
1966 DW.LNS_set_basic_block => {
1967 prog.basic_block = true;
1968 },
1969 DW.LNS_const_add_pc => {
1970 const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range);
1971 prog.address += inc_addr;
1972 },
1973 DW.LNS_fixed_advance_pc => {
1974 const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
1975 prog.address += arg;
1976 },
1977 DW.LNS_set_prologue_end => {},
1978 else => {
1979 if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
1980 const len_bytes = standard_opcode_lengths[opcode - 1];
1981 try di.dwarf_seekable_stream.seekForward(len_bytes);
1982 },
1837 }1983 }
1838 }1984 }
1985 }
18391986
1840 var include_directories = ArrayList([]u8).init(di.allocator());1987 return error.MissingDebugInfo;
1841 try include_directories.append(compile_unit_cwd);1988}
1842 while (true) {
1843 const dir = try di.readString();
1844 if (dir.len == 0) break;
1845 try include_directories.append(dir);
1846 }
18471989
1848 var file_entries = ArrayList(FileEntry).init(di.allocator());1990const Func = struct {
1849 var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address);1991 pc_range: ?PcRange,
1992 name: ?[]u8,
1993};
18501994
1851 while (true) {1995fn getSymbolNameDwarf(di: *DwarfInfo, address: u64) ?[]const u8 {
1852 const file_name = try di.readString();1996 for (di.func_list.toSliceConst()) |*func| {
1853 if (file_name.len == 0) break;1997 if (func.pc_range) |range| {
1854 const dir_index = try readULeb128(di.dwarf_in_stream);1998 if (address >= range.start and address < range.end) {
1855 const mtime = try readULeb128(di.dwarf_in_stream);1999 return func.name;
1856 const len_bytes = try readULeb128(di.dwarf_in_stream);2000 }
1857 try file_entries.append(FileEntry{
1858 .file_name = file_name,
1859 .dir_index = dir_index,
1860 .mtime = mtime,
1861 .len_bytes = len_bytes,
1862 });
1863 }2001 }
2002 }
2003
2004 return null;
2005}
18642006
1865 try di.dwarf_seekable_stream.seekTo(prog_start_offset);2007fn scanAllFunctions(di: *DwarfInfo) !void {
2008 const debug_info_end = di.debug_info.offset + di.debug_info.size;
2009 var this_unit_offset = di.debug_info.offset;
18662010
1867 while (true) {2011 while (this_unit_offset < debug_info_end) {
1868 const opcode = try di.dwarf_in_stream.readByte();2012 try di.dwarf_seekable_stream.seekTo(this_unit_offset);
18692013
1870 if (opcode == DW.LNS_extended_op) {2014 var is_64: bool = undefined;
1871 const op_size = try readULeb128(di.dwarf_in_stream);2015 const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
1872 if (op_size < 1) return error.InvalidDebugInfo;2016 if (unit_length == 0) return;
1873 var sub_op = try di.dwarf_in_stream.readByte();2017 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
1874 switch (sub_op) {2018
1875 DW.LNE_end_sequence => {2019 const version = try di.dwarf_in_stream.readInt(u16, di.endian);
1876 prog.end_sequence = true;2020 if (version < 2 or version > 5) return error.InvalidDebugInfo;
1877 if (try prog.checkLineMatch()) |info| return info;2021
1878 return error.MissingDebugInfo;2022 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);
1879 },2023
1880 DW.LNE_set_address => {2024 const address_size = try di.dwarf_in_stream.readByte();
1881 const addr = try di.dwarf_in_stream.readInt(usize, di.endian);2025 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
1882 prog.address = addr;2026
1883 },2027 const compile_unit_pos = try di.dwarf_seekable_stream.getPos();
1884 DW.LNE_define_file => {2028 const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset);
1885 const file_name = try di.readString();2029
1886 const dir_index = try readULeb128(di.dwarf_in_stream);2030 try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
1887 const mtime = try readULeb128(di.dwarf_in_stream);2031
1888 const len_bytes = try readULeb128(di.dwarf_in_stream);2032 const next_unit_pos = this_unit_offset + next_offset;
1889 try file_entries.append(FileEntry{2033
1890 .file_name = file_name,2034 while ((try di.dwarf_seekable_stream.getPos()) < next_unit_pos) {
1891 .dir_index = dir_index,2035 const die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse continue;
1892 .mtime = mtime,2036 const after_die_offset = try di.dwarf_seekable_stream.getPos();
1893 .len_bytes = len_bytes,2037
1894 });2038 switch (die_obj.tag_id) {
1895 },2039 DW.TAG_subprogram, DW.TAG_inlined_subroutine, DW.TAG_subroutine, DW.TAG_entry_point => {
1896 else => {2040 const fn_name = x: {
1897 const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;2041 var depth: i32 = 3;
1898 try di.dwarf_seekable_stream.seekForward(fwd_amt);2042 var this_die_obj = die_obj;
1899 },2043 // Prenvent endless loops
1900 }2044 while (depth > 0) : (depth -= 1) {
1901 } else if (opcode >= opcode_base) {2045 if (this_die_obj.getAttr(DW.AT_name)) |_| {
1902 // special opcodes2046 const name = try this_die_obj.getAttrString(di, DW.AT_name);
1903 const adjusted_opcode = opcode - opcode_base;2047 break :x name;
1904 const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range);2048 } else if (this_die_obj.getAttr(DW.AT_abstract_origin)) |ref| {
1905 const inc_line = i32(line_base) + i32(adjusted_opcode % line_range);2049 // Follow the DIE it points to and repeat
1906 prog.line += inc_line;2050 const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin);
1907 prog.address += inc_addr;2051 if (ref_offset > next_offset) return error.InvalidDebugInfo;
1908 if (try prog.checkLineMatch()) |info| return info;2052 try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset);
1909 prog.basic_block = false;2053 this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
1910 } else {2054 } else if (this_die_obj.getAttr(DW.AT_specification)) |ref| {
1911 switch (opcode) {2055 // Follow the DIE it points to and repeat
1912 DW.LNS_copy => {2056 const ref_offset = try this_die_obj.getAttrRef(DW.AT_specification);
1913 if (try prog.checkLineMatch()) |info| return info;2057 if (ref_offset > next_offset) return error.InvalidDebugInfo;
1914 prog.basic_block = false;2058 try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset);
1915 },2059 this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
1916 DW.LNS_advance_pc => {2060 } else {
1917 const arg = try readULeb128(di.dwarf_in_stream);2061 break :x null;
1918 prog.address += arg * minimum_instruction_length;2062 }
1919 },2063 }
1920 DW.LNS_advance_line => {2064
1921 const arg = try readILeb128(di.dwarf_in_stream);2065 break :x null;
1922 prog.line += arg;2066 };
1923 },2067
1924 DW.LNS_set_file => {2068 const pc_range = x: {
1925 const arg = try readULeb128(di.dwarf_in_stream);2069 if (die_obj.getAttrAddr(DW.AT_low_pc)) |low_pc| {
1926 prog.file = arg;2070 if (die_obj.getAttr(DW.AT_high_pc)) |high_pc_value| {
1927 },2071 const pc_end = switch (high_pc_value.*) {
1928 DW.LNS_set_column => {2072 FormValue.Address => |value| value,
1929 const arg = try readULeb128(di.dwarf_in_stream);2073 FormValue.Const => |value| b: {
1930 prog.column = arg;2074 const offset = try value.asUnsignedLe();
1931 },2075 break :b (low_pc + offset);
1932 DW.LNS_negate_stmt => {2076 },
1933 prog.is_stmt = !prog.is_stmt;2077 else => return error.InvalidDebugInfo,
1934 },2078 };
1935 DW.LNS_set_basic_block => {2079 break :x PcRange{
1936 prog.basic_block = true;2080 .start = low_pc,
1937 },2081 .end = pc_end,
1938 DW.LNS_const_add_pc => {2082 };
1939 const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range);2083 } else {
1940 prog.address += inc_addr;2084 break :x null;
1941 },2085 }
1942 DW.LNS_fixed_advance_pc => {2086 } else |err| {
1943 const arg = try di.dwarf_in_stream.readInt(u16, di.endian);2087 if (err != error.MissingDebugInfo) return err;
1944 prog.address += arg;2088 break :x null;
1945 },2089 }
1946 DW.LNS_set_prologue_end => {},2090 };
1947 else => {2091
1948 if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;2092 try di.func_list.append(Func{
1949 const len_bytes = standard_opcode_lengths[opcode - 1];2093 .name = fn_name,
1950 try di.dwarf_seekable_stream.seekForward(len_bytes);2094 .pc_range = pc_range,
1951 },2095 });
1952 }2096 },
2097 else => {
2098 continue;
2099 },
1953 }2100 }
2101
2102 try di.dwarf_seekable_stream.seekTo(after_die_offset);
1954 }2103 }
19552104
1956 this_offset += next_offset;2105 this_unit_offset += next_offset;
1957 }2106 }
1958
1959 return error.MissingDebugInfo;
1960}2107}
19612108
1962fn scanAllCompileUnits(di: *DwarfInfo) !void {2109fn scanAllCompileUnits(di: *DwarfInfo) !void {
1963 const debug_info_end = di.debug_info.offset + di.debug_info.size;2110 const debug_info_end = di.debug_info.offset + di.debug_info.size;
1964 var this_unit_offset = di.debug_info.offset;2111 var this_unit_offset = di.debug_info.offset;
1965 var cu_index: usize = 0;
19662112
1967 while (this_unit_offset < debug_info_end) {2113 while (this_unit_offset < debug_info_end) {
1968 try di.dwarf_seekable_stream.seekTo(this_unit_offset);2114 try di.dwarf_seekable_stream.seekTo(this_unit_offset);
...@@ -2019,11 +2165,9 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {...@@ -2019,11 +2165,9 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
2019 .is_64 = is_64,2165 .is_64 = is_64,
2020 .pc_range = pc_range,2166 .pc_range = pc_range,
2021 .die = compile_unit_die,2167 .die = compile_unit_die,
2022 .index = cu_index,
2023 });2168 });
20242169
2025 this_unit_offset += next_offset;2170 this_unit_offset += next_offset;
2026 cu_index += 1;
2027 }2171 }
2028}2172}
20292173
...@@ -2098,52 +2242,6 @@ fn readStringMem(ptr: *[*]const u8) []const u8 {...@@ -2098,52 +2242,6 @@ fn readStringMem(ptr: *[*]const u8) []const u8 {
2098 return result;2242 return result;
2099}2243}
21002244
2101fn readULeb128Mem(ptr: *[*]const u8) !u64 {
2102 var result: u64 = 0;
2103 var shift: usize = 0;
2104 var i: usize = 0;
2105
2106 while (true) {
2107 const byte = ptr.*[i];
2108 i += 1;
2109
2110 var operand: u64 = undefined;
2111
2112 if (@shlWithOverflow(u64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
2113
2114 result |= operand;
2115
2116 if ((byte & 0b10000000) == 0) {
2117 ptr.* += i;
2118 return result;
2119 }
2120
2121 shift += 7;
2122 }
2123}
2124fn readILeb128Mem(ptr: *[*]const u8) !i64 {
2125 var result: i64 = 0;
2126 var shift: usize = 0;
2127 var i: usize = 0;
2128
2129 while (true) {
2130 const byte = ptr.*[i];
2131 i += 1;
2132
2133 var operand: i64 = undefined;
2134 if (@shlWithOverflow(i64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
2135
2136 result |= operand;
2137 shift += 7;
2138
2139 if ((byte & 0b10000000) == 0) {
2140 if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) result |= -(i64(1) << @intCast(u6, shift));
2141 ptr.* += i;
2142 return result;
2143 }
2144 }
2145}
2146
2147fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {2245fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
2148 const first_32_bits = try in_stream.readIntLittle(u32);2246 const first_32_bits = try in_stream.readIntLittle(u32);
2149 is_64.* = (first_32_bits == 0xffffffff);2247 is_64.* = (first_32_bits == 0xffffffff);
...@@ -2155,46 +2253,6 @@ fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool)...@@ -2155,46 +2253,6 @@ fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool)
2155 }2253 }
2156}2254}
21572255
2158fn readULeb128(in_stream: var) !u64 {
2159 var result: u64 = 0;
2160 var shift: usize = 0;
2161
2162 while (true) {
2163 const byte = try in_stream.readByte();
2164
2165 var operand: u64 = undefined;
2166
2167 if (@shlWithOverflow(u64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
2168
2169 result |= operand;
2170
2171 if ((byte & 0b10000000) == 0) return result;
2172
2173 shift += 7;
2174 }
2175}
2176
2177fn readILeb128(in_stream: var) !i64 {
2178 var result: i64 = 0;
2179 var shift: usize = 0;
2180
2181 while (true) {
2182 const byte = try in_stream.readByte();
2183
2184 var operand: i64 = undefined;
2185
2186 if (@shlWithOverflow(i64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
2187
2188 result |= operand;
2189 shift += 7;
2190
2191 if ((byte & 0b10000000) == 0) {
2192 if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) result |= -(i64(1) << @intCast(u6, shift));
2193 return result;
2194 }
2195 }
2196}
2197
2198/// This should only be used in temporary test programs.2256/// This should only be used in temporary test programs.
2199pub const global_allocator = &global_fixed_allocator.allocator;2257pub const global_allocator = &global_fixed_allocator.allocator;
2200var global_fixed_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(global_allocator_mem[0..]);2258var global_fixed_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(global_allocator_mem[0..]);
std/debug/failing_allocator.zig+13-5
...@@ -10,6 +10,7 @@ pub const FailingAllocator = struct {...@@ -10,6 +10,7 @@ pub const FailingAllocator = struct {
10 internal_allocator: *mem.Allocator,10 internal_allocator: *mem.Allocator,
11 allocated_bytes: usize,11 allocated_bytes: usize,
12 freed_bytes: usize,12 freed_bytes: usize,
13 allocations: usize,
13 deallocations: usize,14 deallocations: usize,
1415
15 pub fn init(allocator: *mem.Allocator, fail_index: usize) FailingAllocator {16 pub fn init(allocator: *mem.Allocator, fail_index: usize) FailingAllocator {
...@@ -19,6 +20,7 @@ pub const FailingAllocator = struct {...@@ -19,6 +20,7 @@ pub const FailingAllocator = struct {
19 .index = 0,20 .index = 0,
20 .allocated_bytes = 0,21 .allocated_bytes = 0,
21 .freed_bytes = 0,22 .freed_bytes = 0,
23 .allocations = 0,
22 .deallocations = 0,24 .deallocations = 0,
23 .allocator = mem.Allocator{25 .allocator = mem.Allocator{
24 .reallocFn = realloc,26 .reallocFn = realloc,
...@@ -39,19 +41,25 @@ pub const FailingAllocator = struct {...@@ -39,19 +41,25 @@ pub const FailingAllocator = struct {
39 new_size,41 new_size,
40 new_align,42 new_align,
41 );43 );
42 if (new_size <= old_mem.len) {44 if (new_size < old_mem.len) {
43 self.freed_bytes += old_mem.len - new_size;45 self.freed_bytes += old_mem.len - new_size;
44 } else {46 if (new_size == 0)
47 self.deallocations += 1;
48 } else if (new_size > old_mem.len) {
45 self.allocated_bytes += new_size - old_mem.len;49 self.allocated_bytes += new_size - old_mem.len;
50 if (old_mem.len == 0)
51 self.allocations += 1;
46 }52 }
47 self.deallocations += 1;
48 self.index += 1;53 self.index += 1;
49 return result;54 return result;
50 }55 }
5156
52 fn shrink(allocator: *mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {57 fn shrink(allocator: *mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
53 const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);58 const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
54 self.freed_bytes += old_mem.len - new_size;59 const r = self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align);
55 return self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align);60 self.freed_bytes += old_mem.len - r.len;
61 if (new_size == 0)
62 self.deallocations += 1;
63 return r;
56 }64 }
57};65};
std/debug/leb128.zig created+228
...@@ -0,0 +1,228 @@
1const std = @import("std");
2const testing = std.testing;
3
4pub fn readULEB128(comptime T: type, in_stream: var) !T {
5 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
6
7 var result: T = 0;
8 var shift: usize = 0;
9
10 while (true) {
11 const byte = try in_stream.readByte();
12
13 if (shift > T.bit_count)
14 return error.Overflow;
15
16 var operand: T = undefined;
17 if (@shlWithOverflow(T, byte & 0x7f, @intCast(ShiftT, shift), &operand))
18 return error.Overflow;
19
20 result |= operand;
21
22 if ((byte & 0x80) == 0)
23 return result;
24
25 shift += 7;
26 }
27}
28
29pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
30 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
31
32 var result: T = 0;
33 var shift: usize = 0;
34 var i: usize = 0;
35
36 while (true) : (i += 1) {
37 const byte = ptr.*[i];
38
39 if (shift > T.bit_count)
40 return error.Overflow;
41
42 var operand: T = undefined;
43 if (@shlWithOverflow(T, byte & 0x7f, @intCast(ShiftT, shift), &operand))
44 return error.Overflow;
45
46 result |= operand;
47
48 if ((byte & 0x80) == 0) {
49 ptr.* += i;
50 return result;
51 }
52
53 shift += 7;
54 }
55}
56
57pub fn readILEB128(comptime T: type, in_stream: var) !T {
58 const UT = @IntType(false, T.bit_count);
59 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
60
61 var result: UT = 0;
62 var shift: usize = 0;
63
64 while (true) {
65 const byte = u8(try in_stream.readByte());
66
67 if (shift > T.bit_count)
68 return error.Overflow;
69
70 var operand: UT = undefined;
71 if (@shlWithOverflow(UT, UT(byte & 0x7f), @intCast(ShiftT, shift), &operand)) {
72 if (byte != 0x7f)
73 return error.Overflow;
74 }
75
76 result |= operand;
77
78 shift += 7;
79
80 if ((byte & 0x80) == 0) {
81 if (shift < T.bit_count and (byte & 0x40) != 0) {
82 result |= @bitCast(UT, @intCast(T, -1)) << @intCast(ShiftT, shift);
83 }
84 return @bitCast(T, result);
85 }
86 }
87}
88
89pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
90 const UT = @IntType(false, T.bit_count);
91 const ShiftT = @IntType(false, std.math.log2(T.bit_count));
92
93 var result: UT = 0;
94 var shift: usize = 0;
95 var i: usize = 0;
96
97 while (true) : (i += 1) {
98 const byte = ptr.*[i];
99
100 if (shift > T.bit_count)
101 return error.Overflow;
102
103 var operand: UT = undefined;
104 if (@shlWithOverflow(UT, UT(byte & 0x7f), @intCast(ShiftT, shift), &operand)) {
105 if (byte != 0x7f)
106 return error.Overflow;
107 }
108
109 result |= operand;
110
111 shift += 7;
112
113 if ((byte & 0x80) == 0) {
114 if (shift < T.bit_count and (byte & 0x40) != 0) {
115 result |= @bitCast(UT, @intCast(T, -1)) << @intCast(ShiftT, shift);
116 }
117 ptr.* += i;
118 return @bitCast(T, result);
119 }
120 }
121}
122
123fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T {
124 var in_stream = std.io.SliceInStream.init(encoded);
125 return try readILEB128(T, &in_stream.stream);
126}
127
128fn test_read_stream_uleb128(comptime T: type, encoded: []const u8) !T {
129 var in_stream = std.io.SliceInStream.init(encoded);
130 return try readULEB128(T, &in_stream.stream);
131}
132
133fn test_read_ileb128(comptime T: type, encoded: []const u8) !T {
134 var in_stream = std.io.SliceInStream.init(encoded);
135 const v1 = readILEB128(T, &in_stream.stream);
136 var in_ptr = encoded.ptr;
137 const v2 = readILEB128Mem(T, &in_ptr);
138 testing.expectEqual(v1, v2);
139 return v1;
140}
141
142fn test_read_uleb128(comptime T: type, encoded: []const u8) !T {
143 var in_stream = std.io.SliceInStream.init(encoded);
144 const v1 = readULEB128(T, &in_stream.stream);
145 var in_ptr = encoded.ptr;
146 const v2 = readULEB128Mem(T, &in_ptr);
147 testing.expectEqual(v1, v2);
148 return v1;
149}
150
151test "deserialize signed LEB128" {
152 // Truncated
153 testing.expectError(error.EndOfStream, test_read_stream_ileb128(i64, "\x80"));
154
155 // Overflow
156 testing.expectError(error.Overflow, test_read_ileb128(i8, "\x80\x80\x40"));
157 testing.expectError(error.Overflow, test_read_ileb128(i16, "\x80\x80\x80\x40"));
158 testing.expectError(error.Overflow, test_read_ileb128(i32, "\x80\x80\x80\x80\x40"));
159 testing.expectError(error.Overflow, test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40"));
160 testing.expectError(error.Overflow, test_read_ileb128(i8, "\xff\x7e"));
161
162 // Decode SLEB128
163 testing.expect((try test_read_ileb128(i64, "\x00")) == 0);
164 testing.expect((try test_read_ileb128(i64, "\x01")) == 1);
165 testing.expect((try test_read_ileb128(i64, "\x3f")) == 63);
166 testing.expect((try test_read_ileb128(i64, "\x40")) == -64);
167 testing.expect((try test_read_ileb128(i64, "\x41")) == -63);
168 testing.expect((try test_read_ileb128(i64, "\x7f")) == -1);
169 testing.expect((try test_read_ileb128(i64, "\x80\x01")) == 128);
170 testing.expect((try test_read_ileb128(i64, "\x81\x01")) == 129);
171 testing.expect((try test_read_ileb128(i64, "\xff\x7e")) == -129);
172 testing.expect((try test_read_ileb128(i64, "\x80\x7f")) == -128);
173 testing.expect((try test_read_ileb128(i64, "\x81\x7f")) == -127);
174 testing.expect((try test_read_ileb128(i64, "\xc0\x00")) == 64);
175 testing.expect((try test_read_ileb128(i64, "\xc7\x9f\x7f")) == -12345);
176 testing.expect((try test_read_ileb128(i8, "\xff\x7f")) == -1);
177 testing.expect((try test_read_ileb128(i16, "\xff\xff\x7f")) == -1);
178 testing.expect((try test_read_ileb128(i32, "\xff\xff\xff\xff\x7f")) == -1);
179 testing.expect((try test_read_ileb128(i32, "\x80\x80\x80\x80\x08")) == -0x80000000);
180 testing.expect((try test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01")) == @bitCast(i64, @intCast(u64, 0x8000000000000000)));
181 testing.expect((try test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x40")) == -0x4000000000000000);
182 testing.expect((try test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x7f")) == -0x8000000000000000);
183
184 // Decode unnormalized SLEB128 with extra padding bytes.
185 testing.expect((try test_read_ileb128(i64, "\x80\x00")) == 0);
186 testing.expect((try test_read_ileb128(i64, "\x80\x80\x00")) == 0);
187 testing.expect((try test_read_ileb128(i64, "\xff\x00")) == 0x7f);
188 testing.expect((try test_read_ileb128(i64, "\xff\x80\x00")) == 0x7f);
189 testing.expect((try test_read_ileb128(i64, "\x80\x81\x00")) == 0x80);
190 testing.expect((try test_read_ileb128(i64, "\x80\x81\x80\x00")) == 0x80);
191}
192
193test "deserialize unsigned LEB128" {
194 // Truncated
195 testing.expectError(error.EndOfStream, test_read_stream_uleb128(u64, "\x80"));
196
197 // Overflow
198 testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x02"));
199 testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x80\x40"));
200 testing.expectError(error.Overflow, test_read_uleb128(u16, "\x80\x80\x84"));
201 testing.expectError(error.Overflow, test_read_uleb128(u16, "\x80\x80\x80\x40"));
202 testing.expectError(error.Overflow, test_read_uleb128(u32, "\x80\x80\x80\x80\x90"));
203 testing.expectError(error.Overflow, test_read_uleb128(u32, "\x80\x80\x80\x80\x40"));
204 testing.expectError(error.Overflow, test_read_uleb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40"));
205
206 // Decode ULEB128
207 testing.expect((try test_read_uleb128(u64, "\x00")) == 0);
208 testing.expect((try test_read_uleb128(u64, "\x01")) == 1);
209 testing.expect((try test_read_uleb128(u64, "\x3f")) == 63);
210 testing.expect((try test_read_uleb128(u64, "\x40")) == 64);
211 testing.expect((try test_read_uleb128(u64, "\x7f")) == 0x7f);
212 testing.expect((try test_read_uleb128(u64, "\x80\x01")) == 0x80);
213 testing.expect((try test_read_uleb128(u64, "\x81\x01")) == 0x81);
214 testing.expect((try test_read_uleb128(u64, "\x90\x01")) == 0x90);
215 testing.expect((try test_read_uleb128(u64, "\xff\x01")) == 0xff);
216 testing.expect((try test_read_uleb128(u64, "\x80\x02")) == 0x100);
217 testing.expect((try test_read_uleb128(u64, "\x81\x02")) == 0x101);
218 testing.expect((try test_read_uleb128(u64, "\x80\xc1\x80\x80\x10")) == 4294975616);
219 testing.expect((try test_read_uleb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01")) == 0x8000000000000000);
220
221 // Decode ULEB128 with extra padding bytes
222 testing.expect((try test_read_uleb128(u64, "\x80\x00")) == 0);
223 testing.expect((try test_read_uleb128(u64, "\x80\x80\x00")) == 0);
224 testing.expect((try test_read_uleb128(u64, "\xff\x00")) == 0x7f);
225 testing.expect((try test_read_uleb128(u64, "\xff\x80\x00")) == 0x7f);
226 testing.expect((try test_read_uleb128(u64, "\x80\x81\x00")) == 0x80);
227 testing.expect((try test_read_uleb128(u64, "\x80\x81\x80\x00")) == 0x80);
228}
std/dwarf.zig+4
...@@ -13,6 +13,7 @@ pub const TAG_reference_type = 0x10;...@@ -13,6 +13,7 @@ pub const TAG_reference_type = 0x10;
13pub const TAG_compile_unit = 0x11;13pub const TAG_compile_unit = 0x11;
14pub const TAG_string_type = 0x12;14pub const TAG_string_type = 0x12;
15pub const TAG_structure_type = 0x13;15pub const TAG_structure_type = 0x13;
16pub const TAG_subroutine = 0x14;
16pub const TAG_subroutine_type = 0x15;17pub const TAG_subroutine_type = 0x15;
17pub const TAG_typedef = 0x16;18pub const TAG_typedef = 0x16;
18pub const TAG_union_type = 0x17;19pub const TAG_union_type = 0x17;
...@@ -241,6 +242,9 @@ pub const AT_const_expr = 0x6c;...@@ -241,6 +242,9 @@ pub const AT_const_expr = 0x6c;
241pub const AT_enum_class = 0x6d;242pub const AT_enum_class = 0x6d;
242pub const AT_linkage_name = 0x6e;243pub const AT_linkage_name = 0x6e;
243244
245// DWARF 5
246pub const AT_alignment = 0x88;
247
244pub const AT_lo_user = 0x2000; // Implementation-defined range start.248pub const AT_lo_user = 0x2000; // Implementation-defined range start.
245pub const AT_hi_user = 0x3fff; // Implementation-defined range end.249pub const AT_hi_user = 0x3fff; // Implementation-defined range end.
246250
std/dynamic_library.zig+83
...@@ -19,6 +19,89 @@ pub const DynLib = switch (builtin.os) {...@@ -19,6 +19,89 @@ pub const DynLib = switch (builtin.os) {
19 else => void,19 else => void,
20};20};
2121
22// The link_map structure is not completely specified beside the fields
23// reported below, any libc is free to store additional data in the remaining
24// space.
25// An iterator is provided in order to traverse the linked list in a idiomatic
26// fashion.
27const LinkMap = extern struct {
28 l_addr: usize,
29 l_name: [*]const u8,
30 l_ld: ?*elf.Dyn,
31 l_next: ?*LinkMap,
32 l_prev: ?*LinkMap,
33
34 pub const Iterator = struct {
35 current: ?*LinkMap,
36
37 fn end(self: *Iterator) bool {
38 return self.current == null;
39 }
40
41 fn next(self: *Iterator) ?*LinkMap {
42 if (self.current) |it| {
43 self.current = it.l_next;
44 return it;
45 }
46 return null;
47 }
48 };
49};
50
51const RDebug = extern struct {
52 r_version: i32,
53 r_map: ?*LinkMap,
54 r_brk: usize,
55 r_ldbase: usize,
56};
57
58fn elf_get_va_offset(phdrs: []elf.Phdr) !usize {
59 for (phdrs) |*phdr| {
60 if (phdr.p_type == elf.PT_LOAD) {
61 return @ptrToInt(phdr) - phdr.p_vaddr;
62 }
63 }
64 return error.InvalidExe;
65}
66
67pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
68 const va_offset = try elf_get_va_offset(phdrs);
69
70 const dyn_table = init: {
71 for (phdrs) |*phdr| {
72 if (phdr.p_type == elf.PT_DYNAMIC) {
73 const ptr = @intToPtr([*]elf.Dyn, va_offset + phdr.p_vaddr);
74 break :init ptr[0..phdr.p_memsz / @sizeOf(elf.Dyn)];
75 }
76 }
77 // No PT_DYNAMIC means this is either a statically-linked program or a
78 // badly corrupted one
79 return LinkMap.Iterator{.current = null};
80 };
81
82 const link_map_ptr = init: {
83 for (dyn_table) |*dyn| {
84 switch (dyn.d_tag) {
85 elf.DT_DEBUG => {
86 const r_debug = @intToPtr(*RDebug, dyn.d_un.d_ptr);
87 if (r_debug.r_version != 1) return error.InvalidExe;
88 break :init r_debug.r_map;
89 },
90 elf.DT_PLTGOT => {
91 const got_table = @intToPtr([*]usize, dyn.d_un.d_ptr);
92 // The address to the link_map structure is stored in the
93 // second slot
94 break :init @intToPtr(?*LinkMap, got_table[1]);
95 },
96 else => { }
97 }
98 }
99 return error.InvalidExe;
100 };
101
102 return LinkMap.Iterator{.current = link_map_ptr};
103}
104
22pub const LinuxDynLib = struct {105pub const LinuxDynLib = struct {
23 elf_lib: ElfLib,106 elf_lib: ElfLib,
24 fd: i32,107 fd: i32,
std/elf.zig+5
...@@ -877,6 +877,11 @@ pub const Phdr = switch (@sizeOf(usize)) {...@@ -877,6 +877,11 @@ pub const Phdr = switch (@sizeOf(usize)) {
877 8 => Elf64_Phdr,877 8 => Elf64_Phdr,
878 else => @compileError("expected pointer size of 32 or 64"),878 else => @compileError("expected pointer size of 32 or 64"),
879};879};
880pub const Dyn = switch (@sizeOf(usize)) {
881 4 => Elf32_Dyn,
882 8 => Elf64_Dyn,
883 else => @compileError("expected pointer size of 32 or 64"),
884};
880pub const Shdr = switch (@sizeOf(usize)) {885pub const Shdr = switch (@sizeOf(usize)) {
881 4 => Elf32_Shdr,886 4 => Elf32_Shdr,
882 8 => Elf64_Shdr,887 8 => Elf64_Shdr,
std/fmt.zig+96-12
...@@ -8,6 +8,8 @@ const builtin = @import("builtin");...@@ -8,6 +8,8 @@ const builtin = @import("builtin");
8const errol = @import("fmt/errol.zig");8const errol = @import("fmt/errol.zig");
9const lossyCast = std.math.lossyCast;9const lossyCast = std.math.lossyCast;
1010
11pub const default_max_depth = 3;
12
11/// Renders fmt string with args, calling output with slices of bytes.13/// Renders fmt string with args, calling output with slices of bytes.
12/// If `output` returns an error, the error is returned from `format` and14/// If `output` returns an error, the error is returned from `format` and
13/// `output` is not called again.15/// `output` is not called again.
...@@ -49,7 +51,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),...@@ -49,7 +51,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
49 start_index = i;51 start_index = i;
50 },52 },
51 '}' => {53 '}' => {
52 try formatType(args[next_arg], fmt[0..0], context, Errors, output);54 try formatType(args[next_arg], fmt[0..0], context, Errors, output, default_max_depth);
53 next_arg += 1;55 next_arg += 1;
54 state = State.Start;56 state = State.Start;
55 start_index = i + 1;57 start_index = i + 1;
...@@ -69,7 +71,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),...@@ -69,7 +71,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
69 State.FormatString => switch (c) {71 State.FormatString => switch (c) {
70 '}' => {72 '}' => {
71 const s = start_index + 1;73 const s = start_index + 1;
72 try formatType(args[next_arg], fmt[s..i], context, Errors, output);74 try formatType(args[next_arg], fmt[s..i], context, Errors, output, default_max_depth);
73 next_arg += 1;75 next_arg += 1;
74 state = State.Start;76 state = State.Start;
75 start_index = i + 1;77 start_index = i + 1;
...@@ -108,6 +110,7 @@ pub fn formatType(...@@ -108,6 +110,7 @@ pub fn formatType(
108 context: var,110 context: var,
109 comptime Errors: type,111 comptime Errors: type,
110 output: fn (@typeOf(context), []const u8) Errors!void,112 output: fn (@typeOf(context), []const u8) Errors!void,
113 max_depth: usize,
111) Errors!void {114) Errors!void {
112 const T = @typeOf(value);115 const T = @typeOf(value);
113 switch (@typeInfo(T)) {116 switch (@typeInfo(T)) {
...@@ -122,16 +125,16 @@ pub fn formatType(...@@ -122,16 +125,16 @@ pub fn formatType(
122 },125 },
123 builtin.TypeId.Optional => {126 builtin.TypeId.Optional => {
124 if (value) |payload| {127 if (value) |payload| {
125 return formatType(payload, fmt, context, Errors, output);128 return formatType(payload, fmt, context, Errors, output, max_depth);
126 } else {129 } else {
127 return output(context, "null");130 return output(context, "null");
128 }131 }
129 },132 },
130 builtin.TypeId.ErrorUnion => {133 builtin.TypeId.ErrorUnion => {
131 if (value) |payload| {134 if (value) |payload| {
132 return formatType(payload, fmt, context, Errors, output);135 return formatType(payload, fmt, context, Errors, output, max_depth);
133 } else |err| {136 } else |err| {
134 return formatType(err, fmt, context, Errors, output);137 return formatType(err, fmt, context, Errors, output, max_depth);
135 }138 }
136 },139 },
137 builtin.TypeId.ErrorSet => {140 builtin.TypeId.ErrorSet => {
...@@ -164,10 +167,13 @@ pub fn formatType(...@@ -164,10 +167,13 @@ pub fn formatType(
164 switch (comptime @typeId(T)) {167 switch (comptime @typeId(T)) {
165 builtin.TypeId.Enum => {168 builtin.TypeId.Enum => {
166 try output(context, ".");169 try output(context, ".");
167 try formatType(@tagName(value), "", context, Errors, output);170 try formatType(@tagName(value), "", context, Errors, output, max_depth);
168 return;171 return;
169 },172 },
170 builtin.TypeId.Struct => {173 builtin.TypeId.Struct => {
174 if (max_depth == 0) {
175 return output(context, "{ ... }");
176 }
171 comptime var field_i = 0;177 comptime var field_i = 0;
172 inline while (field_i < @memberCount(T)) : (field_i += 1) {178 inline while (field_i < @memberCount(T)) : (field_i += 1) {
173 if (field_i == 0) {179 if (field_i == 0) {
...@@ -177,11 +183,14 @@ pub fn formatType(...@@ -177,11 +183,14 @@ pub fn formatType(
177 }183 }
178 try output(context, @memberName(T, field_i));184 try output(context, @memberName(T, field_i));
179 try output(context, " = ");185 try output(context, " = ");
180 try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output);186 try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output, max_depth-1);
181 }187 }
182 try output(context, " }");188 try output(context, " }");
183 },189 },
184 builtin.TypeId.Union => {190 builtin.TypeId.Union => {
191 if (max_depth == 0) {
192 return output(context, "{ ... }");
193 }
185 const info = @typeInfo(T).Union;194 const info = @typeInfo(T).Union;
186 if (info.tag_type) |UnionTagType| {195 if (info.tag_type) |UnionTagType| {
187 try output(context, "{ .");196 try output(context, "{ .");
...@@ -189,7 +198,7 @@ pub fn formatType(...@@ -189,7 +198,7 @@ pub fn formatType(
189 try output(context, " = ");198 try output(context, " = ");
190 inline for (info.fields) |u_field| {199 inline for (info.fields) |u_field| {
191 if (@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) {200 if (@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) {
192 try formatType(@field(value, u_field.name), "", context, Errors, output);201 try formatType(@field(value, u_field.name), "", context, Errors, output, max_depth-1);
193 }202 }
194 }203 }
195 try output(context, " }");204 try output(context, " }");
...@@ -210,7 +219,7 @@ pub fn formatType(...@@ -210,7 +219,7 @@ pub fn formatType(
210 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));219 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
211 },220 },
212 builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {221 builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
213 return formatType(value.*, fmt, context, Errors, output);222 return formatType(value.*, fmt, context, Errors, output, max_depth);
214 },223 },
215 else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),224 else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),
216 },225 },
...@@ -986,17 +995,17 @@ test "fmt.format" {...@@ -986,17 +995,17 @@ test "fmt.format" {
986 {995 {
987 var buf1: [32]u8 = undefined;996 var buf1: [32]u8 = undefined;
988 var context = BufPrintContext{ .remaining = buf1[0..] };997 var context = BufPrintContext{ .remaining = buf1[0..] };
989 try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite);998 try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
990 var res = buf1[0 .. buf1.len - context.remaining.len];999 var res = buf1[0 .. buf1.len - context.remaining.len];
991 testing.expect(mem.eql(u8, res, "1234"));1000 testing.expect(mem.eql(u8, res, "1234"));
9921001
993 context = BufPrintContext{ .remaining = buf1[0..] };1002 context = BufPrintContext{ .remaining = buf1[0..] };
994 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);1003 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
995 res = buf1[0 .. buf1.len - context.remaining.len];1004 res = buf1[0 .. buf1.len - context.remaining.len];
996 testing.expect(mem.eql(u8, res, "a"));1005 testing.expect(mem.eql(u8, res, "a"));
9971006
998 context = BufPrintContext{ .remaining = buf1[0..] };1007 context = BufPrintContext{ .remaining = buf1[0..] };
999 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);1008 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1000 res = buf1[0 .. buf1.len - context.remaining.len];1009 res = buf1[0 .. buf1.len - context.remaining.len];
1001 testing.expect(mem.eql(u8, res, "1100"));1010 testing.expect(mem.eql(u8, res, "1100"));
1002 }1011 }
...@@ -1364,6 +1373,20 @@ test "fmt.format" {...@@ -1364,6 +1373,20 @@ test "fmt.format" {
13641373
1365 try testFmt("E.Two", "{}", inst);1374 try testFmt("E.Two", "{}", inst);
1366 }1375 }
1376 //self-referential struct format
1377 {
1378 const S = struct {
1379 const SelfType = @This();
1380 a: ?*SelfType,
1381 };
1382
1383 var inst = S{
1384 .a = null,
1385 };
1386 inst.a = &inst;
1387
1388 try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst);
1389 }
1367 //print bytes as hex1390 //print bytes as hex
1368 {1391 {
1369 const some_bytes = "\xCA\xFE\xBA\xBE";1392 const some_bytes = "\xCA\xFE\xBA\xBE";
...@@ -1449,3 +1472,64 @@ test "fmt.formatIntValue with comptime_int" {...@@ -1449,3 +1472,64 @@ test "fmt.formatIntValue with comptime_int" {
1449 try formatIntValue(value, "", &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);1472 try formatIntValue(value, "", &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);
1450 assert(mem.eql(u8, buf.toSlice(), "123456789123456789"));1473 assert(mem.eql(u8, buf.toSlice(), "123456789123456789"));
1451}1474}
1475
1476test "fmt.formatType max_depth" {
1477 const Vec2 = struct {
1478 const SelfType = @This();
1479 x: f32,
1480 y: f32,
1481
1482 pub fn format(
1483 self: SelfType,
1484 comptime fmt: []const u8,
1485 context: var,
1486 comptime Errors: type,
1487 output: fn (@typeOf(context), []const u8) Errors!void,
1488 ) Errors!void {
1489 return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y);
1490 }
1491 };
1492 const E = enum {
1493 One,
1494 Two,
1495 Three,
1496 };
1497 const TU = union(enum) {
1498 const SelfType = @This();
1499 float: f32,
1500 int: u32,
1501 ptr: ?*SelfType,
1502 };
1503 const S = struct {
1504 const SelfType = @This();
1505 a: ?*SelfType,
1506 tu: TU,
1507 e: E,
1508 vec: Vec2,
1509 };
1510
1511 var inst = S{
1512 .a = null,
1513 .tu = TU{ .ptr = null },
1514 .e = E.Two,
1515 .vec = Vec2{ .x = 10.2, .y = 2.22 },
1516 };
1517 inst.a = &inst;
1518 inst.tu.ptr = &inst.tu;
1519
1520 var buf0 = try std.Buffer.init(std.debug.global_allocator, "");
1521 try formatType(inst, "", &buf0, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0);
1522 assert(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
1523
1524 var buf1 = try std.Buffer.init(std.debug.global_allocator, "");
1525 try formatType(inst, "", &buf1, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1);
1526 assert(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
1527
1528 var buf2 = try std.Buffer.init(std.debug.global_allocator, "");
1529 try formatType(inst, "", &buf2, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2);
1530 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) }"));
1531
1532 var buf3 = try std.Buffer.init(std.debug.global_allocator, "");
1533 try formatType(inst, "", &buf3, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3);
1534 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) }"));
1535}
std/hash_map.zig+71-12
...@@ -118,7 +118,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -118,7 +118,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
118 };118 };
119 }119 }
120 self.incrementModificationCount();120 self.incrementModificationCount();
121 try self.ensureCapacity();121 try self.autoCapacity();
122 const put_result = self.internalPut(key);122 const put_result = self.internalPut(key);
123 assert(put_result.old_kv == null);123 assert(put_result.old_kv == null);
124 return GetOrPutResult{124 return GetOrPutResult{
...@@ -135,15 +135,37 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -135,15 +135,37 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
135 return res.kv;135 return res.kv;
136 }136 }
137137
138 fn ensureCapacity(self: *Self) !void {138 fn optimizedCapacity(expected_count: usize) usize {
139 if (self.entries.len == 0) {139 // ensure that the hash map will be at most 60% full if
140 return self.initCapacity(16);140 // expected_count items are put into it
141 var optimized_capacity = expected_count * 5 / 3;
142 // round capacity to the next power of two
143 const pow = math.log2_int_ceil(usize, optimized_capacity);
144 return math.pow(usize, 2, pow);
145 }
146
147 /// Increases capacity so that the hash map will be at most
148 /// 60% full when expected_count items are put into it
149 pub fn ensureCapacity(self: *Self, expected_count: usize) !void {
150 const optimized_capacity = optimizedCapacity(expected_count);
151 return self.ensureCapacityExact(optimized_capacity);
152 }
153
154 /// Sets the capacity to the new capacity if the new
155 /// capacity is greater than the current capacity.
156 /// New capacity must be a power of two.
157 fn ensureCapacityExact(self: *Self, new_capacity: usize) !void {
158 const is_power_of_two = new_capacity & (new_capacity-1) == 0;
159 assert(is_power_of_two);
160
161 if (new_capacity <= self.entries.len) {
162 return;
141 }163 }
142164
143 // if we get too full (60%), double the capacity165 const old_entries = self.entries;
144 if (self.size * 5 >= self.entries.len * 3) {166 try self.initCapacity(new_capacity);
145 const old_entries = self.entries;167 self.incrementModificationCount();
146 try self.initCapacity(self.entries.len * 2);168 if (old_entries.len > 0) {
147 // dump all of the old elements into the new table169 // dump all of the old elements into the new table
148 for (old_entries) |*old_entry| {170 for (old_entries) |*old_entry| {
149 if (old_entry.used) {171 if (old_entry.used) {
...@@ -156,8 +178,13 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -156,8 +178,13 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
156178
157 /// Returns the kv pair that was already there.179 /// Returns the kv pair that was already there.
158 pub fn put(self: *Self, key: K, value: V) !?KV {180 pub fn put(self: *Self, key: K, value: V) !?KV {
181 try self.autoCapacity();
182 return putAssumeCapacity(self, key, value);
183 }
184
185 pub fn putAssumeCapacity(self: *Self, key: K, value: V) ?KV {
186 assert(self.count() < self.entries.len);
159 self.incrementModificationCount();187 self.incrementModificationCount();
160 try self.ensureCapacity();
161188
162 const put_result = self.internalPut(key);189 const put_result = self.internalPut(key);
163 put_result.new_entry.kv.value = value;190 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...@@ -175,7 +202,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
175 return hm.get(key) != null;202 return hm.get(key) != null;
176 }203 }
177204
178 pub fn remove(hm: *Self, key: K) ?*KV {205 pub fn remove(hm: *Self, key: K) ?KV {
179 if (hm.entries.len == 0) return null;206 if (hm.entries.len == 0) return null;
180 hm.incrementModificationCount();207 hm.incrementModificationCount();
181 const start_index = hm.keyToIndex(key);208 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...@@ -189,13 +216,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
189216
190 if (!eql(entry.kv.key, key)) continue;217 if (!eql(entry.kv.key, key)) continue;
191218
219 const removed_kv = entry.kv;
192 while (roll_over < hm.entries.len) : (roll_over += 1) {220 while (roll_over < hm.entries.len) : (roll_over += 1) {
193 const next_index = (start_index + roll_over + 1) % hm.entries.len;221 const next_index = (start_index + roll_over + 1) % hm.entries.len;
194 const next_entry = &hm.entries[next_index];222 const next_entry = &hm.entries[next_index];
195 if (!next_entry.used or next_entry.distance_from_start_index == 0) {223 if (!next_entry.used or next_entry.distance_from_start_index == 0) {
196 entry.used = false;224 entry.used = false;
197 hm.size -= 1;225 hm.size -= 1;
198 return &entry.kv;226 return removed_kv;
199 }227 }
200 entry.* = next_entry.*;228 entry.* = next_entry.*;
201 entry.distance_from_start_index -= 1;229 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...@@ -226,6 +254,16 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
226 return other;254 return other;
227 }255 }
228256
257 fn autoCapacity(self: *Self) !void {
258 if (self.entries.len == 0) {
259 return self.ensureCapacityExact(16);
260 }
261 // if we get too full (60%), double the capacity
262 if (self.size * 5 >= self.entries.len * 3) {
263 return self.ensureCapacityExact(self.entries.len * 2);
264 }
265 }
266
229 fn initCapacity(hm: *Self, capacity: usize) !void {267 fn initCapacity(hm: *Self, capacity: usize) !void {
230 hm.entries = try hm.allocator.alloc(Entry, capacity);268 hm.entries = try hm.allocator.alloc(Entry, capacity);
231 hm.size = 0;269 hm.size = 0;
...@@ -371,7 +409,10 @@ test "basic hash map usage" {...@@ -371,7 +409,10 @@ test "basic hash map usage" {
371409
372 testing.expect(map.contains(2));410 testing.expect(map.contains(2));
373 testing.expect(map.get(2).?.value == 22);411 testing.expect(map.get(2).?.value == 22);
374 _ = map.remove(2);412
413 const rmv1 = map.remove(2);
414 testing.expect(rmv1.?.key == 2);
415 testing.expect(rmv1.?.value == 22);
375 testing.expect(map.remove(2) == null);416 testing.expect(map.remove(2) == null);
376 testing.expect(map.get(2) == null);417 testing.expect(map.get(2) == null);
377}418}
...@@ -423,6 +464,24 @@ test "iterator hash map" {...@@ -423,6 +464,24 @@ test "iterator hash map" {
423 testing.expect(entry.value == values[0]);464 testing.expect(entry.value == values[0]);
424}465}
425466
467test "ensure capacity" {
468 var direct_allocator = std.heap.DirectAllocator.init();
469 defer direct_allocator.deinit();
470
471 var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
472 defer map.deinit();
473
474 try map.ensureCapacity(20);
475 const initialCapacity = map.entries.len;
476 testing.expect(initialCapacity >= 20);
477 var i : i32 = 0;
478 while (i < 20) : (i += 1) {
479 testing.expect(map.putAssumeCapacity(i, i+10) == null);
480 }
481 // shouldn't resize from putAssumeCapacity
482 testing.expect(initialCapacity == map.entries.len);
483}
484
426pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) {485pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) {
427 return struct {486 return struct {
428 fn hash(key: K) u32 {487 fn hash(key: K) u32 {
std/heap.zig+405-73
...@@ -34,9 +34,6 @@ fn cShrink(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new...@@ -34,9 +34,6 @@ fn cShrink(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new
34/// Thread-safe and lock-free.34/// Thread-safe and lock-free.
35pub const DirectAllocator = struct {35pub const DirectAllocator = struct {
36 allocator: Allocator,36 allocator: Allocator,
37 heap_handle: ?HeapHandle,
38
39 const HeapHandle = if (builtin.os == Os.windows) os.windows.HANDLE else void;
4037
41 pub fn init() DirectAllocator {38 pub fn init() DirectAllocator {
42 return DirectAllocator{39 return DirectAllocator{
...@@ -44,21 +41,15 @@ pub const DirectAllocator = struct {...@@ -44,21 +41,15 @@ pub const DirectAllocator = struct {
44 .reallocFn = realloc,41 .reallocFn = realloc,
45 .shrinkFn = shrink,42 .shrinkFn = shrink,
46 },43 },
47 .heap_handle = if (builtin.os == Os.windows) null else {},
48 };44 };
49 }45 }
5046
51 pub fn deinit(self: *DirectAllocator) void {47 pub fn deinit(self: *DirectAllocator) void {}
52 switch (builtin.os) {
53 Os.windows => if (self.heap_handle) |heap_handle| {
54 _ = os.windows.HeapDestroy(heap_handle);
55 },
56 else => {},
57 }
58 }
5948
60 fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {49 fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
61 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);50 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
51 if (n == 0)
52 return (([*]u8)(undefined))[0..0];
6253
63 switch (builtin.os) {54 switch (builtin.os) {
64 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {55 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
...@@ -68,39 +59,76 @@ pub const DirectAllocator = struct {...@@ -68,39 +59,76 @@ pub const DirectAllocator = struct {
68 if (addr == p.MAP_FAILED) return error.OutOfMemory;59 if (addr == p.MAP_FAILED) return error.OutOfMemory;
69 if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];60 if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];
7061
71 const aligned_addr = (addr & ~usize(alignment - 1)) + alignment;62 const aligned_addr = mem.alignForward(addr, alignment);
72
73 // We can unmap the unused portions of our mmap, but we must only
74 // pass munmap bytes that exist outside our allocated pages or it
75 // will happily eat us too.
76
77 // Since alignment > page_size, we are by definition on a page boundary.
78 const unused_start = addr;
79 const unused_len = aligned_addr - 1 - unused_start;
80
81 const err = p.munmap(unused_start, unused_len);
82 assert(p.getErrno(err) == 0);
8363
84 // It is impossible that there is an unoccupied page at the top of our64 // Unmap the extra bytes that were only requested in order to guarantee
85 // mmap.65 // that the range of memory we were provided had a proper alignment in
66 // it somewhere. The extra bytes could be at the beginning, or end, or both.
67 const unused_start_len = aligned_addr - addr;
68 if (unused_start_len != 0) {
69 const err = p.munmap(addr, unused_start_len);
70 assert(p.getErrno(err) == 0);
71 }
72 const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size);
73 const unused_end_len = addr + alloc_size - aligned_end_addr;
74 if (unused_end_len != 0) {
75 const err = p.munmap(aligned_end_addr, unused_end_len);
76 assert(p.getErrno(err) == 0);
77 }
8678
87 return @intToPtr([*]u8, aligned_addr)[0..n];79 return @intToPtr([*]u8, aligned_addr)[0..n];
88 },80 },
89 Os.windows => {81 .windows => {
90 const amt = n + alignment + @sizeOf(usize);82 const w = os.windows;
91 const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, builtin.AtomicOrder.SeqCst);83
92 const heap_handle = optional_heap_handle orelse blk: {84 // Although officially it's at least aligned to page boundary,
93 const hh = os.windows.HeapCreate(0, amt, 0) orelse return error.OutOfMemory;85 // Windows is known to reserve pages on a 64K boundary. It's
94 const other_hh = @cmpxchgStrong(?HeapHandle, &self.heap_handle, null, hh, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse break :blk hh;86 // even more likely that the requested alignment is <= 64K than
95 _ = os.windows.HeapDestroy(hh);87 // 4K, so we're just allocating blindly and hoping for the best.
96 break :blk other_hh.?; // can't be null because of the cmpxchg88 // see https://devblogs.microsoft.com/oldnewthing/?p=42223
97 };89 const addr = w.VirtualAlloc(
98 const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory;90 null,
99 const root_addr = @ptrToInt(ptr);91 n,
100 const adjusted_addr = mem.alignForward(root_addr, alignment);92 w.MEM_COMMIT | w.MEM_RESERVE,
101 const record_addr = adjusted_addr + n;93 w.PAGE_READWRITE,
102 @intToPtr(*align(1) usize, record_addr).* = root_addr;94 ) orelse return error.OutOfMemory;
103 return @intToPtr([*]u8, adjusted_addr)[0..n];95
96 // If the allocation is sufficiently aligned, use it.
97 if (@ptrToInt(addr) & (alignment - 1) == 0) {
98 return @ptrCast([*]u8, addr)[0..n];
99 }
100
101 // If it wasn't, actually do an explicitely aligned allocation.
102 if (w.VirtualFree(addr, 0, w.MEM_RELEASE) == 0) unreachable;
103 const alloc_size = n + alignment;
104
105 const final_addr = while (true) {
106 // Reserve a range of memory large enough to find a sufficiently
107 // aligned address.
108 const reserved_addr = w.VirtualAlloc(
109 null,
110 alloc_size,
111 w.MEM_RESERVE,
112 w.PAGE_NOACCESS,
113 ) orelse return error.OutOfMemory;
114 const aligned_addr = mem.alignForward(@ptrToInt(reserved_addr), alignment);
115
116 // Release the reserved pages (not actually used).
117 if (w.VirtualFree(reserved_addr, 0, w.MEM_RELEASE) == 0) unreachable;
118
119 // At this point, it is possible that another thread has
120 // obtained some memory space that will cause the next
121 // VirtualAlloc call to fail. To handle this, we will retry
122 // until it succeeds.
123 if (w.VirtualAlloc(
124 @intToPtr(*c_void, aligned_addr),
125 n,
126 w.MEM_COMMIT | w.MEM_RESERVE,
127 w.PAGE_READWRITE,
128 )) |ptr| break ptr;
129 } else unreachable; // TODO else unreachable should not be necessary
130
131 return @ptrCast([*]u8, final_addr)[0..n];
104 },132 },
105 else => @compileError("Unsupported OS"),133 else => @compileError("Unsupported OS"),
106 }134 }
...@@ -118,13 +146,31 @@ pub const DirectAllocator = struct {...@@ -118,13 +146,31 @@ pub const DirectAllocator = struct {
118 }146 }
119 return old_mem[0..new_size];147 return old_mem[0..new_size];
120 },148 },
121 Os.windows => return realloc(allocator, old_mem, old_align, new_size, new_align) catch {149 .windows => {
122 const old_adjusted_addr = @ptrToInt(old_mem.ptr);150 const w = os.windows;
123 const old_record_addr = old_adjusted_addr + old_mem.len;151 if (new_size == 0) {
124 const root_addr = @intToPtr(*align(1) usize, old_record_addr).*;152 // From the docs:
125 const old_ptr = @intToPtr(*c_void, root_addr);153 // "If the dwFreeType parameter is MEM_RELEASE, this parameter
126 const new_record_addr = old_record_addr - new_size + old_mem.len;154 // must be 0 (zero). The function frees the entire region that
127 @intToPtr(*align(1) usize, new_record_addr).* = root_addr;155 // is reserved in the initial allocation call to VirtualAlloc."
156 // So we can only use MEM_RELEASE when actually releasing the
157 // whole allocation.
158 if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
159 } else {
160 const base_addr = @ptrToInt(old_mem.ptr);
161 const old_addr_end = base_addr + old_mem.len;
162 const new_addr_end = base_addr + new_size;
163 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
164 if (old_addr_end > new_addr_end_rounded) {
165 // For shrinking that is not releasing, we will only
166 // decommit the pages not needed anymore.
167 if (w.VirtualFree(
168 @intToPtr(*c_void, new_addr_end_rounded),
169 old_addr_end - new_addr_end_rounded,
170 w.MEM_DECOMMIT,
171 ) == 0) unreachable;
172 }
173 }
128 return old_mem[0..new_size];174 return old_mem[0..new_size];
129 },175 },
130 else => @compileError("Unsupported OS"),176 else => @compileError("Unsupported OS"),
...@@ -138,36 +184,168 @@ pub const DirectAllocator = struct {...@@ -138,36 +184,168 @@ pub const DirectAllocator = struct {
138 return shrink(allocator, old_mem, old_align, new_size, new_align);184 return shrink(allocator, old_mem, old_align, new_size, new_align);
139 }185 }
140 const result = try alloc(allocator, new_size, new_align);186 const result = try alloc(allocator, new_size, new_align);
141 mem.copy(u8, result, old_mem);187 if (old_mem.len != 0) {
142 _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len);188 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
189 _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
190 }
143 return result;191 return result;
144 },192 },
145 Os.windows => {193 .windows => {
146 if (old_mem.len == 0) return alloc(allocator, new_size, new_align);194 if (old_mem.len == 0) {
195 return alloc(allocator, new_size, new_align);
196 }
197
198 if (new_size <= old_mem.len and new_align <= old_align) {
199 return shrink(allocator, old_mem, old_align, new_size, new_align);
200 }
201
202 const w = os.windows;
203 const base_addr = @ptrToInt(old_mem.ptr);
204
205 if (new_align > old_align and base_addr & (new_align - 1) != 0) {
206 // Current allocation doesn't satisfy the new alignment.
207 // For now we'll do a new one no matter what, but maybe
208 // there is something smarter to do instead.
209 const result = try alloc(allocator, new_size, new_align);
210 assert(old_mem.len != 0);
211 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
212 if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
147213
148 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);214 return result;
215 }
216
217 const old_addr_end = base_addr + old_mem.len;
218 const old_addr_end_rounded = mem.alignForward(old_addr_end, os.page_size);
219 const new_addr_end = base_addr + new_size;
220 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
221 if (new_addr_end_rounded == old_addr_end_rounded) {
222 // The reallocation fits in the already allocated pages.
223 return @ptrCast([*]u8, old_mem.ptr)[0..new_size];
224 }
225 assert(new_addr_end_rounded > old_addr_end_rounded);
226
227 // We need to commit new pages.
228 const additional_size = new_addr_end - old_addr_end_rounded;
229 const realloc_addr = w.VirtualAlloc(
230 @intToPtr(*c_void, old_addr_end_rounded),
231 additional_size,
232 w.MEM_COMMIT | w.MEM_RESERVE,
233 w.PAGE_READWRITE,
234 ) orelse {
235 // Committing new pages at the end of the existing allocation
236 // failed, we need to try a new one.
237 const new_alloc_mem = try alloc(allocator, new_size, new_align);
238 @memcpy(new_alloc_mem.ptr, old_mem.ptr, old_mem.len);
239 if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
240
241 return new_alloc_mem;
242 };
243
244 assert(@ptrToInt(realloc_addr) == old_addr_end_rounded);
245 return @ptrCast([*]u8, old_mem.ptr)[0..new_size];
246 },
247 else => @compileError("Unsupported OS"),
248 }
249 }
250};
251
252pub const HeapAllocator = switch (builtin.os) {
253 .windows => struct {
254 allocator: Allocator,
255 heap_handle: ?HeapHandle,
256
257 const HeapHandle = os.windows.HANDLE;
258
259 pub fn init() HeapAllocator {
260 return HeapAllocator{
261 .allocator = Allocator{
262 .reallocFn = realloc,
263 .shrinkFn = shrink,
264 },
265 .heap_handle = null,
266 };
267 }
268
269 pub fn deinit(self: *HeapAllocator) void {
270 if (self.heap_handle) |heap_handle| {
271 _ = os.windows.HeapDestroy(heap_handle);
272 }
273 }
274
275 fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
276 const self = @fieldParentPtr(HeapAllocator, "allocator", allocator);
277 if (n == 0)
278 return (([*]u8)(undefined))[0..0];
279
280 const amt = n + alignment + @sizeOf(usize);
281 const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, builtin.AtomicOrder.SeqCst);
282 const heap_handle = optional_heap_handle orelse blk: {
283 const options = if (builtin.single_threaded) os.windows.HEAP_NO_SERIALIZE else 0;
284 const hh = os.windows.HeapCreate(options, amt, 0) orelse return error.OutOfMemory;
285 const other_hh = @cmpxchgStrong(?HeapHandle, &self.heap_handle, null, hh, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse break :blk hh;
286 _ = os.windows.HeapDestroy(hh);
287 break :blk other_hh.?; // can't be null because of the cmpxchg
288 };
289 const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory;
290 const root_addr = @ptrToInt(ptr);
291 const adjusted_addr = mem.alignForward(root_addr, alignment);
292 const record_addr = adjusted_addr + n;
293 @intToPtr(*align(1) usize, record_addr).* = root_addr;
294 return @intToPtr([*]u8, adjusted_addr)[0..n];
295 }
296
297 fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
298 return realloc(allocator, old_mem, old_align, new_size, new_align) catch {
149 const old_adjusted_addr = @ptrToInt(old_mem.ptr);299 const old_adjusted_addr = @ptrToInt(old_mem.ptr);
150 const old_record_addr = old_adjusted_addr + old_mem.len;300 const old_record_addr = old_adjusted_addr + old_mem.len;
151 const root_addr = @intToPtr(*align(1) usize, old_record_addr).*;301 const root_addr = @intToPtr(*align(1) usize, old_record_addr).*;
152 const old_ptr = @intToPtr(*c_void, root_addr);302 const old_ptr = @intToPtr(*c_void, root_addr);
153 const amt = new_size + new_align + @sizeOf(usize);303 const new_record_addr = old_record_addr - new_size + old_mem.len;
154 const new_ptr = os.windows.HeapReAlloc(304 @intToPtr(*align(1) usize, new_record_addr).* = root_addr;
155 self.heap_handle.?,305 return old_mem[0..new_size];
156 0,306 };
157 old_ptr,
158 amt,
159 ) orelse return error.OutOfMemory;
160 const offset = old_adjusted_addr - root_addr;
161 const new_root_addr = @ptrToInt(new_ptr);
162 const new_adjusted_addr = new_root_addr + offset;
163 assert(new_adjusted_addr % new_align == 0);
164 const new_record_addr = new_adjusted_addr + new_size;
165 @intToPtr(*align(1) usize, new_record_addr).* = new_root_addr;
166 return @intToPtr([*]u8, new_adjusted_addr)[0..new_size];
167 },
168 else => @compileError("Unsupported OS"),
169 }307 }
170 }308
309 fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
310 if (old_mem.len == 0) return alloc(allocator, new_size, new_align);
311
312 const self = @fieldParentPtr(HeapAllocator, "allocator", allocator);
313 const old_adjusted_addr = @ptrToInt(old_mem.ptr);
314 const old_record_addr = old_adjusted_addr + old_mem.len;
315 const root_addr = @intToPtr(*align(1) usize, old_record_addr).*;
316 const old_ptr = @intToPtr(*c_void, root_addr);
317
318 if (new_size == 0) {
319 if (os.windows.HeapFree(self.heap_handle.?, 0, old_ptr) == 0) unreachable;
320 return old_mem[0..0];
321 }
322
323 const amt = new_size + new_align + @sizeOf(usize);
324 const new_ptr = os.windows.HeapReAlloc(
325 self.heap_handle.?,
326 0,
327 old_ptr,
328 amt,
329 ) orelse return error.OutOfMemory;
330 const offset = old_adjusted_addr - root_addr;
331 const new_root_addr = @ptrToInt(new_ptr);
332 var new_adjusted_addr = new_root_addr + offset;
333 const offset_is_valid = new_adjusted_addr + new_size + @sizeOf(usize) <= new_root_addr + amt;
334 const offset_is_aligned = new_adjusted_addr % new_align == 0;
335 if (!offset_is_valid or !offset_is_aligned) {
336 // If HeapReAlloc didn't happen to move the memory to the new alignment,
337 // or the memory starting at the old offset would be outside of the new allocation,
338 // then we need to copy the memory to a valid aligned address and use that
339 const new_aligned_addr = mem.alignForward(new_root_addr, new_align);
340 @memcpy(@intToPtr([*]u8, new_aligned_addr), @intToPtr([*]u8, new_adjusted_addr), std.math.min(old_mem.len, new_size));
341 new_adjusted_addr = new_aligned_addr;
342 }
343 const new_record_addr = new_adjusted_addr + new_size;
344 @intToPtr(*align(1) usize, new_record_addr).* = new_root_addr;
345 return @intToPtr([*]u8, new_adjusted_addr)[0..new_size];
346 }
347 },
348 else => @compileError("Unsupported OS"),
171};349};
172350
173/// This allocator takes an existing allocator, wraps it, and provides an interface351/// This allocator takes an existing allocator, wraps it, and provides an interface
...@@ -250,7 +428,7 @@ pub const ArenaAllocator = struct {...@@ -250,7 +428,7 @@ pub const ArenaAllocator = struct {
250 return error.OutOfMemory;428 return error.OutOfMemory;
251 } else {429 } else {
252 const result = try alloc(allocator, new_size, new_align);430 const result = try alloc(allocator, new_size, new_align);
253 mem.copy(u8, result, old_mem);431 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
254 return result;432 return result;
255 }433 }
256 }434 }
...@@ -306,6 +484,103 @@ pub const FixedBufferAllocator = struct {...@@ -306,6 +484,103 @@ pub const FixedBufferAllocator = struct {
306 } else if (new_size <= old_mem.len and new_align <= old_align) {484 } else if (new_size <= old_mem.len and new_align <= old_align) {
307 // We can't do anything with the memory, so tell the client to keep it.485 // We can't do anything with the memory, so tell the client to keep it.
308 return error.OutOfMemory;486 return error.OutOfMemory;
487 } else {
488 const result = try alloc(allocator, new_size, new_align);
489 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
490 return result;
491 }
492 }
493
494 fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
495 return old_mem[0..new_size];
496 }
497};
498
499// FIXME: Exposed LLVM intrinsics is a bug
500// See: https://github.com/ziglang/zig/issues/2291
501extern fn @"llvm.wasm.memory.size.i32"(u32) u32;
502extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32;
503
504pub const wasm_allocator = &wasm_allocator_state.allocator;
505var wasm_allocator_state = WasmAllocator{
506 .allocator = Allocator{
507 .reallocFn = WasmAllocator.realloc,
508 .shrinkFn = WasmAllocator.shrink,
509 },
510 .start_ptr = undefined,
511 .num_pages = 0,
512 .end_index = 0,
513};
514
515const WasmAllocator = struct {
516 allocator: Allocator,
517 start_ptr: [*]u8,
518 num_pages: usize,
519 end_index: usize,
520
521 comptime {
522 if (builtin.arch != .wasm32) {
523 @compileError("WasmAllocator is only available for wasm32 arch");
524 }
525 }
526
527 fn alloc(allocator: *Allocator, size: usize, alignment: u29) ![]u8 {
528 const self = @fieldParentPtr(WasmAllocator, "allocator", allocator);
529
530 const addr = @ptrToInt(self.start_ptr) + self.end_index;
531 const adjusted_addr = mem.alignForward(addr, alignment);
532 const adjusted_index = self.end_index + (adjusted_addr - addr);
533 const new_end_index = adjusted_index + size;
534
535 if (new_end_index > self.num_pages * os.page_size) {
536 const required_memory = new_end_index - (self.num_pages * os.page_size);
537
538 var num_pages: usize = required_memory / os.page_size;
539 if (required_memory % os.page_size != 0) {
540 num_pages += 1;
541 }
542
543 const prev_page = @"llvm.wasm.memory.grow.i32"(0, @intCast(u32, num_pages));
544 if (prev_page == -1) {
545 return error.OutOfMemory;
546 }
547
548 self.num_pages += num_pages;
549 }
550
551 const result = self.start_ptr[adjusted_index..new_end_index];
552 self.end_index = new_end_index;
553
554 return result;
555 }
556
557 // Check if memory is the last "item" and is aligned correctly
558 fn is_last_item(allocator: *Allocator, memory: []u8, alignment: u29) bool {
559 const self = @fieldParentPtr(WasmAllocator, "allocator", allocator);
560 return memory.ptr == self.start_ptr + self.end_index - memory.len and mem.alignForward(@ptrToInt(memory.ptr), alignment) == @ptrToInt(memory.ptr);
561 }
562
563 fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
564 const self = @fieldParentPtr(WasmAllocator, "allocator", allocator);
565
566 // Initialize start_ptr at the first realloc
567 if (self.num_pages == 0) {
568 self.start_ptr = @intToPtr([*]u8, @intCast(usize, @"llvm.wasm.memory.size.i32"(0)) * os.page_size);
569 }
570
571 if (is_last_item(allocator, old_mem, new_align)) {
572 const start_index = self.end_index - old_mem.len;
573 const new_end_index = start_index + new_size;
574
575 if (new_end_index > self.num_pages * os.page_size) {
576 _ = try alloc(allocator, new_end_index - self.end_index, new_align);
577 }
578 const result = self.start_ptr[start_index..new_end_index];
579
580 self.end_index = new_end_index;
581 return result;
582 } else if (new_size <= old_mem.len and new_align <= old_align) {
583 return error.OutOfMemory;
309 } else {584 } else {
310 const result = try alloc(allocator, new_size, new_align);585 const result = try alloc(allocator, new_size, new_align);
311 mem.copy(u8, result, old_mem);586 mem.copy(u8, result, old_mem);
...@@ -360,7 +635,7 @@ pub const ThreadSafeFixedBufferAllocator = blk: {...@@ -360,7 +635,7 @@ pub const ThreadSafeFixedBufferAllocator = blk: {
360 return error.OutOfMemory;635 return error.OutOfMemory;
361 } else {636 } else {
362 const result = try alloc(allocator, new_size, new_align);637 const result = try alloc(allocator, new_size, new_align);
363 mem.copy(u8, result, old_mem);638 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
364 return result;639 return result;
365 }640 }
366 }641 }
...@@ -470,6 +745,31 @@ test "DirectAllocator" {...@@ -470,6 +745,31 @@ test "DirectAllocator" {
470 try testAllocator(allocator);745 try testAllocator(allocator);
471 try testAllocatorAligned(allocator, 16);746 try testAllocatorAligned(allocator, 16);
472 try testAllocatorLargeAlignment(allocator);747 try testAllocatorLargeAlignment(allocator);
748 try testAllocatorAlignedShrink(allocator);
749
750 if (builtin.os == .windows) {
751 // Trying really large alignment. As mentionned in the implementation,
752 // VirtualAlloc returns 64K aligned addresses. We want to make sure
753 // DirectAllocator works beyond that, as it's not tested by
754 // `testAllocatorLargeAlignment`.
755 const slice = try allocator.alignedAlloc(u8, 1 << 20, 128);
756 slice[0] = 0x12;
757 slice[127] = 0x34;
758 allocator.free(slice);
759 }
760}
761
762test "HeapAllocator" {
763 if (builtin.os == .windows) {
764 var heap_allocator = HeapAllocator.init();
765 defer heap_allocator.deinit();
766
767 const allocator = &heap_allocator.allocator;
768 try testAllocator(allocator);
769 try testAllocatorAligned(allocator, 16);
770 try testAllocatorLargeAlignment(allocator);
771 try testAllocatorAlignedShrink(allocator);
772 }
473}773}
474774
475test "ArenaAllocator" {775test "ArenaAllocator" {
...@@ -482,15 +782,17 @@ test "ArenaAllocator" {...@@ -482,15 +782,17 @@ test "ArenaAllocator" {
482 try testAllocator(&arena_allocator.allocator);782 try testAllocator(&arena_allocator.allocator);
483 try testAllocatorAligned(&arena_allocator.allocator, 16);783 try testAllocatorAligned(&arena_allocator.allocator, 16);
484 try testAllocatorLargeAlignment(&arena_allocator.allocator);784 try testAllocatorLargeAlignment(&arena_allocator.allocator);
785 try testAllocatorAlignedShrink(&arena_allocator.allocator);
485}786}
486787
487var test_fixed_buffer_allocator_memory: [30000 * @sizeOf(usize)]u8 = undefined;788var test_fixed_buffer_allocator_memory: [80000 * @sizeOf(u64)]u8 = undefined;
488test "FixedBufferAllocator" {789test "FixedBufferAllocator" {
489 var fixed_buffer_allocator = FixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]);790 var fixed_buffer_allocator = FixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]);
490791
491 try testAllocator(&fixed_buffer_allocator.allocator);792 try testAllocator(&fixed_buffer_allocator.allocator);
492 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);793 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);
493 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);794 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
795 try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator);
494}796}
495797
496test "FixedBufferAllocator Reuse memory on realloc" {798test "FixedBufferAllocator Reuse memory on realloc" {
...@@ -528,6 +830,7 @@ test "ThreadSafeFixedBufferAllocator" {...@@ -528,6 +830,7 @@ test "ThreadSafeFixedBufferAllocator" {
528 try testAllocator(&fixed_buffer_allocator.allocator);830 try testAllocator(&fixed_buffer_allocator.allocator);
529 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);831 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);
530 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);832 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
833 try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator);
531}834}
532835
533fn testAllocator(allocator: *mem.Allocator) !void {836fn testAllocator(allocator: *mem.Allocator) !void {
...@@ -610,3 +913,32 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo...@@ -610,3 +913,32 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo
610913
611 allocator.free(slice);914 allocator.free(slice);
612}915}
916
917fn testAllocatorAlignedShrink(allocator: *mem.Allocator) mem.Allocator.Error!void {
918 var debug_buffer: [1000]u8 = undefined;
919 const debug_allocator = &FixedBufferAllocator.init(&debug_buffer).allocator;
920
921 const alloc_size = os.page_size * 2 + 50;
922 var slice = try allocator.alignedAlloc(u8, 16, alloc_size);
923 defer allocator.free(slice);
924
925 var stuff_to_free = std.ArrayList([]align(16) u8).init(debug_allocator);
926 // On Windows, VirtualAlloc returns addresses aligned to a 64K boundary,
927 // which is 16 pages, hence the 32. This test may require to increase
928 // the size of the allocations feeding the `allocator` parameter if they
929 // fail, because of this high over-alignment we want to have.
930 while (@ptrToInt(slice.ptr) == mem.alignForward(@ptrToInt(slice.ptr), os.page_size * 32)) {
931 try stuff_to_free.append(slice);
932 slice = try allocator.alignedAlloc(u8, 16, alloc_size);
933 }
934 while (stuff_to_free.popOrNull()) |item| {
935 allocator.free(item);
936 }
937 slice[0] = 0x12;
938 slice[60] = 0x34;
939
940 // realloc to a smaller size but with a larger alignment
941 slice = try allocator.alignedRealloc(slice, os.page_size * 32, alloc_size / 2);
942 testing.expect(slice[0] == 0x12);
943 testing.expect(slice[60] == 0x34);
944}
std/io.zig+24-17
...@@ -36,6 +36,7 @@ pub fn getStdIn() GetStdIoErrs!File {...@@ -36,6 +36,7 @@ pub fn getStdIn() GetStdIoErrs!File {
36}36}
3737
38pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;38pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
39pub const COutStream = @import("io/c_out_stream.zig").COutStream;
3940
40pub fn InStream(comptime ReadError: type) type {41pub fn InStream(comptime ReadError: type) type {
41 return struct {42 return struct {
...@@ -194,8 +195,8 @@ pub fn InStream(comptime ReadError: type) type {...@@ -194,8 +195,8 @@ pub fn InStream(comptime ReadError: type) type {
194 return mem.readVarInt(ReturnType, bytes, endian);195 return mem.readVarInt(ReturnType, bytes, endian);
195 }196 }
196197
197 pub fn skipBytes(self: *Self, num_bytes: usize) !void {198 pub fn skipBytes(self: *Self, num_bytes: u64) !void {
198 var i: usize = 0;199 var i: u64 = 0;
199 while (i < num_bytes) : (i += 1) {200 while (i < num_bytes) : (i += 1) {
200 _ = try self.readByte();201 _ = try self.readByte();
201 }202 }
...@@ -289,7 +290,7 @@ pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptim...@@ -289,7 +290,7 @@ pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptim
289 var file = try File.openRead(path);290 var file = try File.openRead(path);
290 defer file.close();291 defer file.close();
291292
292 const size = try file.getEndPos();293 const size = try math.cast(usize, try file.getEndPos());
293 const buf = try allocator.alignedAlloc(u8, A, size);294 const buf = try allocator.alignedAlloc(u8, A, size);
294 errdefer allocator.free(buf);295 errdefer allocator.free(buf);
295296
...@@ -742,7 +743,7 @@ pub fn CountingOutStream(comptime OutStreamError: type) type {...@@ -742,7 +743,7 @@ pub fn CountingOutStream(comptime OutStreamError: type) type {
742 pub const Error = OutStreamError;743 pub const Error = OutStreamError;
743744
744 pub stream: Stream,745 pub stream: Stream,
745 pub bytes_written: usize,746 pub bytes_written: u64,
746 child_stream: *Stream,747 child_stream: *Stream,
747748
748 pub fn init(child_stream: *Stream) Self {749 pub fn init(child_stream: *Stream) Self {
...@@ -1089,8 +1090,11 @@ test "io.readLineSliceFrom" {...@@ -1089,8 +1090,11 @@ test "io.readLineSliceFrom" {
1089}1090}
10901091
1091pub const Packing = enum {1092pub const Packing = enum {
1092 Byte, /// Pack data to byte alignment1093 /// Pack data to byte alignment
1093 Bit, /// Pack data to bit alignment1094 Byte,
1095
1096 /// Pack data to bit alignment
1097 Bit,
1094};1098};
10951099
1096/// Creates a deserializer that deserializes types from any stream.1100/// Creates a deserializer that deserializes types from any stream.
...@@ -1111,10 +1115,12 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,...@@ -1111,10 +1115,12 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
1111 pub const Stream = InStream(Error);1115 pub const Stream = InStream(Error);
11121116
1113 pub fn init(in_stream: *Stream) Self {1117 pub fn init(in_stream: *Stream) Self {
1114 return Self{ .in_stream = switch (packing) {1118 return Self{
1115 .Bit => BitInStream(endian, Stream.Error).init(in_stream),1119 .in_stream = switch (packing) {
1116 .Byte => in_stream,1120 .Bit => BitInStream(endian, Stream.Error).init(in_stream),
1117 } };1121 .Byte => in_stream,
1122 },
1123 };
1118 }1124 }
11191125
1120 pub fn alignToByte(self: *Self) void {1126 pub fn alignToByte(self: *Self) void {
...@@ -1281,7 +1287,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,...@@ -1281,7 +1287,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
1281 ptr.* = null;1287 ptr.* = null;
1282 return;1288 return;
1283 }1289 }
1284 1290
1285 ptr.* = OC(undefined); //make it non-null so the following .? is guaranteed safe1291 ptr.* = OC(undefined); //make it non-null so the following .? is guaranteed safe
1286 const val_ptr = &ptr.*.?;1292 const val_ptr = &ptr.*.?;
1287 try self.deserializeInto(val_ptr);1293 try self.deserializeInto(val_ptr);
...@@ -1320,10 +1326,12 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co...@@ -1320,10 +1326,12 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
1320 pub const Stream = OutStream(Error);1326 pub const Stream = OutStream(Error);
13211327
1322 pub fn init(out_stream: *Stream) Self {1328 pub fn init(out_stream: *Stream) Self {
1323 return Self{ .out_stream = switch (packing) {1329 return Self{
1324 .Bit => BitOutStream(endian, Stream.Error).init(out_stream),1330 .out_stream = switch (packing) {
1325 .Byte => out_stream,1331 .Bit => BitOutStream(endian, Stream.Error).init(out_stream),
1326 } };1332 .Byte => out_stream,
1333 },
1334 };
1327 }1335 }
13281336
1329 /// Flushes any unwritten bits to the stream1337 /// Flushes any unwritten bits to the stream
...@@ -1447,7 +1455,6 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co...@@ -1447,7 +1455,6 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
14471455
1448test "import io tests" {1456test "import io tests" {
1449 comptime {1457 comptime {
1450 _ = @import("io_test.zig");1458 _ = @import("io/test.zig");
1451 }1459 }
1452}1460}
1453
std/io/c_out_stream.zig created+48
...@@ -0,0 +1,48 @@
1const std = @import("../std.zig");
2const OutStream = std.io.OutStream;
3const builtin = @import("builtin");
4const posix = std.os.posix;
5
6/// TODO make std.os.FILE use *FILE when linking libc and this just becomes
7/// std.io.FileOutStream because std.os.File.write would do this when linking
8/// libc.
9pub const COutStream = struct {
10 pub const Error = std.os.File.WriteError;
11 pub const Stream = OutStream(Error);
12
13 stream: Stream,
14 c_file: *std.c.FILE,
15
16 pub fn init(c_file: *std.c.FILE) COutStream {
17 return COutStream{
18 .c_file = c_file,
19 .stream = Stream{ .writeFn = writeFn },
20 };
21 }
22
23 fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void {
24 const self = @fieldParentPtr(COutStream, "stream", out_stream);
25 const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);
26 if (amt_written == bytes.len) return;
27 // TODO errno on windows. should we have a posix layer for windows?
28 if (builtin.os == .windows) {
29 return error.InputOutput;
30 }
31 const errno = std.c._errno().*;
32 switch (errno) {
33 0 => unreachable,
34 posix.EINVAL => unreachable,
35 posix.EFAULT => unreachable,
36 posix.EAGAIN => unreachable, // this is a blocking API
37 posix.EBADF => unreachable, // always a race condition
38 posix.EDESTADDRREQ => unreachable, // connect was never called
39 posix.EDQUOT => return error.DiskQuota,
40 posix.EFBIG => return error.FileTooBig,
41 posix.EIO => return error.InputOutput,
42 posix.ENOSPC => return error.NoSpaceLeft,
43 posix.EPERM => return error.AccessDenied,
44 posix.EPIPE => return error.BrokenPipe,
45 else => return std.os.unexpectedErrorPosix(@intCast(usize, errno)),
46 }
47 }
48};
std/io/seekable_stream.zig+8-8
...@@ -7,25 +7,25 @@ pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType...@@ -7,25 +7,25 @@ pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType
7 pub const SeekError = SeekErrorType;7 pub const SeekError = SeekErrorType;
8 pub const GetSeekPosError = GetSeekPosErrorType;8 pub const GetSeekPosError = GetSeekPosErrorType;
99
10 seekToFn: fn (self: *Self, pos: usize) SeekError!void,10 seekToFn: fn (self: *Self, pos: u64) SeekError!void,
11 seekForwardFn: fn (self: *Self, pos: isize) SeekError!void,11 seekForwardFn: fn (self: *Self, pos: i64) SeekError!void,
1212
13 getPosFn: fn (self: *Self) GetSeekPosError!usize,13 getPosFn: fn (self: *Self) GetSeekPosError!u64,
14 getEndPosFn: fn (self: *Self) GetSeekPosError!usize,14 getEndPosFn: fn (self: *Self) GetSeekPosError!u64,
1515
16 pub fn seekTo(self: *Self, pos: usize) SeekError!void {16 pub fn seekTo(self: *Self, pos: u64) SeekError!void {
17 return self.seekToFn(self, pos);17 return self.seekToFn(self, pos);
18 }18 }
1919
20 pub fn seekForward(self: *Self, amt: isize) SeekError!void {20 pub fn seekForward(self: *Self, amt: i64) SeekError!void {
21 return self.seekForwardFn(self, amt);21 return self.seekForwardFn(self, amt);
22 }22 }
2323
24 pub fn getEndPos(self: *Self) GetSeekPosError!usize {24 pub fn getEndPos(self: *Self) GetSeekPosError!u64 {
25 return self.getEndPosFn(self);25 return self.getEndPosFn(self);
26 }26 }
2727
28 pub fn getPos(self: *Self) GetSeekPosError!usize {28 pub fn getPos(self: *Self) GetSeekPosError!u64 {
29 return self.getPosFn(self);29 return self.getPosFn(self);
30 }30 }
31 };31 };
std/io/test.zig created+602
...@@ -0,0 +1,602 @@
1const std = @import("../std.zig");
2const io = std.io;
3const meta = std.meta;
4const trait = std.trait;
5const DefaultPrng = std.rand.DefaultPrng;
6const expect = std.testing.expect;
7const expectError = std.testing.expectError;
8const mem = std.mem;
9const os = std.os;
10const builtin = @import("builtin");
11
12test "write a file, read it, then delete it" {
13 var raw_bytes: [200 * 1024]u8 = undefined;
14 var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator;
15
16 var data: [1024]u8 = undefined;
17 var prng = DefaultPrng.init(1234);
18 prng.random.bytes(data[0..]);
19 const tmp_file_name = "temp_test_file.txt";
20 {
21 var file = try os.File.openWrite(tmp_file_name);
22 defer file.close();
23
24 var file_out_stream = file.outStream();
25 var buf_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);
26 const st = &buf_stream.stream;
27 try st.print("begin");
28 try st.write(data[0..]);
29 try st.print("end");
30 try buf_stream.flush();
31 }
32
33 {
34 // make sure openWriteNoClobber doesn't harm the file
35 if (os.File.openWriteNoClobber(tmp_file_name, os.File.default_mode)) |file| {
36 unreachable;
37 } else |err| {
38 std.debug.assert(err == os.File.OpenError.PathAlreadyExists);
39 }
40 }
41
42 {
43 var file = try os.File.openRead(tmp_file_name);
44 defer file.close();
45
46 const file_size = try file.getEndPos();
47 const expected_file_size = "begin".len + data.len + "end".len;
48 expect(file_size == expected_file_size);
49
50 var file_in_stream = file.inStream();
51 var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);
52 const st = &buf_stream.stream;
53 const contents = try st.readAllAlloc(allocator, 2 * 1024);
54 defer allocator.free(contents);
55
56 expect(mem.eql(u8, contents[0.."begin".len], "begin"));
57 expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
58 expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
59 }
60 try os.deleteFile(tmp_file_name);
61}
62
63test "BufferOutStream" {
64 var bytes: [100]u8 = undefined;
65 var allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
66
67 var buffer = try std.Buffer.initSize(allocator, 0);
68 var buf_stream = &std.io.BufferOutStream.init(&buffer).stream;
69
70 const x: i32 = 42;
71 const y: i32 = 1234;
72 try buf_stream.print("x: {}\ny: {}\n", x, y);
73
74 expect(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
75}
76
77test "SliceInStream" {
78 const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7 };
79 var ss = io.SliceInStream.init(bytes);
80
81 var dest: [4]u8 = undefined;
82
83 var read = try ss.stream.read(dest[0..4]);
84 expect(read == 4);
85 expect(mem.eql(u8, dest[0..4], bytes[0..4]));
86
87 read = try ss.stream.read(dest[0..4]);
88 expect(read == 3);
89 expect(mem.eql(u8, dest[0..3], bytes[4..7]));
90
91 read = try ss.stream.read(dest[0..4]);
92 expect(read == 0);
93}
94
95test "PeekStream" {
96 const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
97 var ss = io.SliceInStream.init(bytes);
98 var ps = io.PeekStream(2, io.SliceInStream.Error).init(&ss.stream);
99
100 var dest: [4]u8 = undefined;
101
102 ps.putBackByte(9);
103 ps.putBackByte(10);
104
105 var read = try ps.stream.read(dest[0..4]);
106 expect(read == 4);
107 expect(dest[0] == 10);
108 expect(dest[1] == 9);
109 expect(mem.eql(u8, dest[2..4], bytes[0..2]));
110
111 read = try ps.stream.read(dest[0..4]);
112 expect(read == 4);
113 expect(mem.eql(u8, dest[0..4], bytes[2..6]));
114
115 read = try ps.stream.read(dest[0..4]);
116 expect(read == 2);
117 expect(mem.eql(u8, dest[0..2], bytes[6..8]));
118
119 ps.putBackByte(11);
120 ps.putBackByte(12);
121
122 read = try ps.stream.read(dest[0..4]);
123 expect(read == 2);
124 expect(dest[0] == 12);
125 expect(dest[1] == 11);
126}
127
128test "SliceOutStream" {
129 var buffer: [10]u8 = undefined;
130 var ss = io.SliceOutStream.init(buffer[0..]);
131
132 try ss.stream.write("Hello");
133 expect(mem.eql(u8, ss.getWritten(), "Hello"));
134
135 try ss.stream.write("world");
136 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
137
138 expectError(error.OutOfSpace, ss.stream.write("!"));
139 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
140
141 ss.reset();
142 expect(ss.getWritten().len == 0);
143
144 expectError(error.OutOfSpace, ss.stream.write("Hello world!"));
145 expect(mem.eql(u8, ss.getWritten(), "Hello worl"));
146}
147
148test "BitInStream" {
149 const mem_be = []u8{ 0b11001101, 0b00001011 };
150 const mem_le = []u8{ 0b00011101, 0b10010101 };
151
152 var mem_in_be = io.SliceInStream.init(mem_be[0..]);
153 const InError = io.SliceInStream.Error;
154 var bit_stream_be = io.BitInStream(builtin.Endian.Big, InError).init(&mem_in_be.stream);
155
156 var out_bits: usize = undefined;
157
158 expect(1 == try bit_stream_be.readBits(u2, 1, &out_bits));
159 expect(out_bits == 1);
160 expect(2 == try bit_stream_be.readBits(u5, 2, &out_bits));
161 expect(out_bits == 2);
162 expect(3 == try bit_stream_be.readBits(u128, 3, &out_bits));
163 expect(out_bits == 3);
164 expect(4 == try bit_stream_be.readBits(u8, 4, &out_bits));
165 expect(out_bits == 4);
166 expect(5 == try bit_stream_be.readBits(u9, 5, &out_bits));
167 expect(out_bits == 5);
168 expect(1 == try bit_stream_be.readBits(u1, 1, &out_bits));
169 expect(out_bits == 1);
170
171 mem_in_be.pos = 0;
172 bit_stream_be.bit_count = 0;
173 expect(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits));
174 expect(out_bits == 15);
175
176 mem_in_be.pos = 0;
177 bit_stream_be.bit_count = 0;
178 expect(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits));
179 expect(out_bits == 16);
180
181 _ = try bit_stream_be.readBits(u0, 0, &out_bits);
182
183 expect(0 == try bit_stream_be.readBits(u1, 1, &out_bits));
184 expect(out_bits == 0);
185 expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));
186
187 var mem_in_le = io.SliceInStream.init(mem_le[0..]);
188 var bit_stream_le = io.BitInStream(builtin.Endian.Little, InError).init(&mem_in_le.stream);
189
190 expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
191 expect(out_bits == 1);
192 expect(2 == try bit_stream_le.readBits(u5, 2, &out_bits));
193 expect(out_bits == 2);
194 expect(3 == try bit_stream_le.readBits(u128, 3, &out_bits));
195 expect(out_bits == 3);
196 expect(4 == try bit_stream_le.readBits(u8, 4, &out_bits));
197 expect(out_bits == 4);
198 expect(5 == try bit_stream_le.readBits(u9, 5, &out_bits));
199 expect(out_bits == 5);
200 expect(1 == try bit_stream_le.readBits(u1, 1, &out_bits));
201 expect(out_bits == 1);
202
203 mem_in_le.pos = 0;
204 bit_stream_le.bit_count = 0;
205 expect(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits));
206 expect(out_bits == 15);
207
208 mem_in_le.pos = 0;
209 bit_stream_le.bit_count = 0;
210 expect(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits));
211 expect(out_bits == 16);
212
213 _ = try bit_stream_le.readBits(u0, 0, &out_bits);
214
215 expect(0 == try bit_stream_le.readBits(u1, 1, &out_bits));
216 expect(out_bits == 0);
217 expectError(error.EndOfStream, bit_stream_le.readBitsNoEof(u1, 1));
218}
219
220test "BitOutStream" {
221 var mem_be = []u8{0} ** 2;
222 var mem_le = []u8{0} ** 2;
223
224 var mem_out_be = io.SliceOutStream.init(mem_be[0..]);
225 const OutError = io.SliceOutStream.Error;
226 var bit_stream_be = io.BitOutStream(builtin.Endian.Big, OutError).init(&mem_out_be.stream);
227
228 try bit_stream_be.writeBits(u2(1), 1);
229 try bit_stream_be.writeBits(u5(2), 2);
230 try bit_stream_be.writeBits(u128(3), 3);
231 try bit_stream_be.writeBits(u8(4), 4);
232 try bit_stream_be.writeBits(u9(5), 5);
233 try bit_stream_be.writeBits(u1(1), 1);
234
235 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
236
237 mem_out_be.pos = 0;
238
239 try bit_stream_be.writeBits(u15(0b110011010000101), 15);
240 try bit_stream_be.flushBits();
241 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
242
243 mem_out_be.pos = 0;
244 try bit_stream_be.writeBits(u32(0b110011010000101), 16);
245 expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
246
247 try bit_stream_be.writeBits(u0(0), 0);
248
249 var mem_out_le = io.SliceOutStream.init(mem_le[0..]);
250 var bit_stream_le = io.BitOutStream(builtin.Endian.Little, OutError).init(&mem_out_le.stream);
251
252 try bit_stream_le.writeBits(u2(1), 1);
253 try bit_stream_le.writeBits(u5(2), 2);
254 try bit_stream_le.writeBits(u128(3), 3);
255 try bit_stream_le.writeBits(u8(4), 4);
256 try bit_stream_le.writeBits(u9(5), 5);
257 try bit_stream_le.writeBits(u1(1), 1);
258
259 expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
260
261 mem_out_le.pos = 0;
262 try bit_stream_le.writeBits(u15(0b110011010000101), 15);
263 try bit_stream_le.flushBits();
264 expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
265
266 mem_out_le.pos = 0;
267 try bit_stream_le.writeBits(u32(0b1100110100001011), 16);
268 expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
269
270 try bit_stream_le.writeBits(u0(0), 0);
271}
272
273test "BitStreams with File Stream" {
274 const tmp_file_name = "temp_test_file.txt";
275 {
276 var file = try os.File.openWrite(tmp_file_name);
277 defer file.close();
278
279 var file_out = file.outStream();
280 var file_out_stream = &file_out.stream;
281 const OutError = os.File.WriteError;
282 var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
283
284 try bit_stream.writeBits(u2(1), 1);
285 try bit_stream.writeBits(u5(2), 2);
286 try bit_stream.writeBits(u128(3), 3);
287 try bit_stream.writeBits(u8(4), 4);
288 try bit_stream.writeBits(u9(5), 5);
289 try bit_stream.writeBits(u1(1), 1);
290 try bit_stream.flushBits();
291 }
292 {
293 var file = try os.File.openRead(tmp_file_name);
294 defer file.close();
295
296 var file_in = file.inStream();
297 var file_in_stream = &file_in.stream;
298 const InError = os.File.ReadError;
299 var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
300
301 var out_bits: usize = undefined;
302
303 expect(1 == try bit_stream.readBits(u2, 1, &out_bits));
304 expect(out_bits == 1);
305 expect(2 == try bit_stream.readBits(u5, 2, &out_bits));
306 expect(out_bits == 2);
307 expect(3 == try bit_stream.readBits(u128, 3, &out_bits));
308 expect(out_bits == 3);
309 expect(4 == try bit_stream.readBits(u8, 4, &out_bits));
310 expect(out_bits == 4);
311 expect(5 == try bit_stream.readBits(u9, 5, &out_bits));
312 expect(out_bits == 5);
313 expect(1 == try bit_stream.readBits(u1, 1, &out_bits));
314 expect(out_bits == 1);
315
316 expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1));
317 }
318 try os.deleteFile(tmp_file_name);
319}
320
321fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
322 //@NOTE: if this test is taking too long, reduce the maximum tested bitsize
323 const max_test_bitsize = 128;
324
325 const total_bytes = comptime blk: {
326 var bytes = 0;
327 comptime var i = 0;
328 while (i <= max_test_bitsize) : (i += 1) bytes += (i / 8) + @boolToInt(i % 8 > 0);
329 break :blk bytes * 2;
330 };
331
332 var data_mem: [total_bytes]u8 = undefined;
333 var out = io.SliceOutStream.init(data_mem[0..]);
334 const OutError = io.SliceOutStream.Error;
335 var out_stream = &out.stream;
336 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
337
338 var in = io.SliceInStream.init(data_mem[0..]);
339 const InError = io.SliceInStream.Error;
340 var in_stream = &in.stream;
341 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
342
343 comptime var i = 0;
344 inline while (i <= max_test_bitsize) : (i += 1) {
345 const U = @IntType(false, i);
346 const S = @IntType(true, i);
347 try serializer.serializeInt(U(i));
348 if (i != 0) try serializer.serializeInt(S(-1)) else try serializer.serialize(S(0));
349 }
350 try serializer.flush();
351
352 i = 0;
353 inline while (i <= max_test_bitsize) : (i += 1) {
354 const U = @IntType(false, i);
355 const S = @IntType(true, i);
356 const x = try deserializer.deserializeInt(U);
357 const y = try deserializer.deserializeInt(S);
358 expect(x == U(i));
359 if (i != 0) expect(y == S(-1)) else expect(y == 0);
360 }
361
362 const u8_bit_count = comptime meta.bitCount(u8);
363 //0 + 1 + 2 + ... n = (n * (n + 1)) / 2
364 //and we have each for unsigned and signed, so * 2
365 const total_bits = (max_test_bitsize * (max_test_bitsize + 1));
366 const extra_packed_byte = @boolToInt(total_bits % u8_bit_count > 0);
367 const total_packed_bytes = (total_bits / u8_bit_count) + extra_packed_byte;
368
369 expect(in.pos == if (packing == .Bit) total_packed_bytes else total_bytes);
370
371 //Verify that empty error set works with serializer.
372 //deserializer is covered by SliceInStream
373 const NullError = io.NullOutStream.Error;
374 var null_out = io.NullOutStream.init();
375 var null_out_stream = &null_out.stream;
376 var null_serializer = io.Serializer(endian, packing, NullError).init(null_out_stream);
377 try null_serializer.serialize(data_mem[0..]);
378 try null_serializer.flush();
379}
380
381test "Serializer/Deserializer Int" {
382 try testIntSerializerDeserializer(.Big, .Byte);
383 try testIntSerializerDeserializer(.Little, .Byte);
384 // TODO these tests are disabled due to tripping an LLVM assertion
385 // https://github.com/ziglang/zig/issues/2019
386 //try testIntSerializerDeserializer(builtin.Endian.Big, true);
387 //try testIntSerializerDeserializer(builtin.Endian.Little, true);
388}
389
390fn testIntSerializerDeserializerInfNaN(
391 comptime endian: builtin.Endian,
392 comptime packing: io.Packing,
393) !void {
394 const mem_size = (16 * 2 + 32 * 2 + 64 * 2 + 128 * 2) / comptime meta.bitCount(u8);
395 var data_mem: [mem_size]u8 = undefined;
396
397 var out = io.SliceOutStream.init(data_mem[0..]);
398 const OutError = io.SliceOutStream.Error;
399 var out_stream = &out.stream;
400 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
401
402 var in = io.SliceInStream.init(data_mem[0..]);
403 const InError = io.SliceInStream.Error;
404 var in_stream = &in.stream;
405 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
406
407 //@TODO: isInf/isNan not currently implemented for f128.
408 try serializer.serialize(std.math.nan(f16));
409 try serializer.serialize(std.math.inf(f16));
410 try serializer.serialize(std.math.nan(f32));
411 try serializer.serialize(std.math.inf(f32));
412 try serializer.serialize(std.math.nan(f64));
413 try serializer.serialize(std.math.inf(f64));
414 //try serializer.serialize(std.math.nan(f128));
415 //try serializer.serialize(std.math.inf(f128));
416 const nan_check_f16 = try deserializer.deserialize(f16);
417 const inf_check_f16 = try deserializer.deserialize(f16);
418 const nan_check_f32 = try deserializer.deserialize(f32);
419 const inf_check_f32 = try deserializer.deserialize(f32);
420 const nan_check_f64 = try deserializer.deserialize(f64);
421 const inf_check_f64 = try deserializer.deserialize(f64);
422 //const nan_check_f128 = try deserializer.deserialize(f128);
423 //const inf_check_f128 = try deserializer.deserialize(f128);
424 expect(std.math.isNan(nan_check_f16));
425 expect(std.math.isInf(inf_check_f16));
426 expect(std.math.isNan(nan_check_f32));
427 expect(std.math.isInf(inf_check_f32));
428 expect(std.math.isNan(nan_check_f64));
429 expect(std.math.isInf(inf_check_f64));
430 //expect(std.math.isNan(nan_check_f128));
431 //expect(std.math.isInf(inf_check_f128));
432}
433
434test "Serializer/Deserializer Int: Inf/NaN" {
435 try testIntSerializerDeserializerInfNaN(.Big, .Byte);
436 try testIntSerializerDeserializerInfNaN(.Little, .Byte);
437 try testIntSerializerDeserializerInfNaN(.Big, .Bit);
438 try testIntSerializerDeserializerInfNaN(.Little, .Bit);
439}
440
441fn testAlternateSerializer(self: var, serializer: var) !void {
442 try serializer.serialize(self.f_f16);
443}
444
445fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
446 const ColorType = enum(u4) {
447 RGB8 = 1,
448 RA16 = 2,
449 R32 = 3,
450 };
451
452 const TagAlign = union(enum(u32)) {
453 A: u8,
454 B: u8,
455 C: u8,
456 };
457
458 const Color = union(ColorType) {
459 RGB8: struct {
460 r: u8,
461 g: u8,
462 b: u8,
463 a: u8,
464 },
465 RA16: struct {
466 r: u16,
467 a: u16,
468 },
469 R32: u32,
470 };
471
472 const PackedStruct = packed struct {
473 f_i3: i3,
474 f_u2: u2,
475 };
476
477 //to test custom serialization
478 const Custom = struct {
479 f_f16: f16,
480 f_unused_u32: u32,
481
482 pub fn deserialize(self: *@This(), deserializer: var) !void {
483 try deserializer.deserializeInto(&self.f_f16);
484 self.f_unused_u32 = 47;
485 }
486
487 pub const serialize = testAlternateSerializer;
488 };
489
490 const MyStruct = struct {
491 f_i3: i3,
492 f_u8: u8,
493 f_tag_align: TagAlign,
494 f_u24: u24,
495 f_i19: i19,
496 f_void: void,
497 f_f32: f32,
498 f_f128: f128,
499 f_packed_0: PackedStruct,
500 f_i7arr: [10]i7,
501 f_of64n: ?f64,
502 f_of64v: ?f64,
503 f_color_type: ColorType,
504 f_packed_1: PackedStruct,
505 f_custom: Custom,
506 f_color: Color,
507 };
508
509 const my_inst = MyStruct{
510 .f_i3 = -1,
511 .f_u8 = 8,
512 .f_tag_align = TagAlign{ .B = 148 },
513 .f_u24 = 24,
514 .f_i19 = 19,
515 .f_void = {},
516 .f_f32 = 32.32,
517 .f_f128 = 128.128,
518 .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 },
519 .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
520 .f_of64n = null,
521 .f_of64v = 64.64,
522 .f_color_type = ColorType.R32,
523 .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 },
524 .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 },
525 .f_color = Color{ .R32 = 123822 },
526 };
527
528 var data_mem: [@sizeOf(MyStruct)]u8 = undefined;
529 var out = io.SliceOutStream.init(data_mem[0..]);
530 const OutError = io.SliceOutStream.Error;
531 var out_stream = &out.stream;
532 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
533
534 var in = io.SliceInStream.init(data_mem[0..]);
535 const InError = io.SliceInStream.Error;
536 var in_stream = &in.stream;
537 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
538
539 try serializer.serialize(my_inst);
540
541 const my_copy = try deserializer.deserialize(MyStruct);
542 expect(meta.eql(my_copy, my_inst));
543}
544
545test "Serializer/Deserializer generic" {
546 try testSerializerDeserializer(builtin.Endian.Big, .Byte);
547 try testSerializerDeserializer(builtin.Endian.Little, .Byte);
548 try testSerializerDeserializer(builtin.Endian.Big, .Bit);
549 try testSerializerDeserializer(builtin.Endian.Little, .Bit);
550}
551
552fn testBadData(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
553 const E = enum(u14) {
554 One = 1,
555 Two = 2,
556 };
557
558 const A = struct {
559 e: E,
560 };
561
562 const C = union(E) {
563 One: u14,
564 Two: f16,
565 };
566
567 var data_mem: [4]u8 = undefined;
568 var out = io.SliceOutStream.init(data_mem[0..]);
569 const OutError = io.SliceOutStream.Error;
570 var out_stream = &out.stream;
571 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
572
573 var in = io.SliceInStream.init(data_mem[0..]);
574 const InError = io.SliceInStream.Error;
575 var in_stream = &in.stream;
576 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
577
578 try serializer.serialize(u14(3));
579 expectError(error.InvalidEnumTag, deserializer.deserialize(A));
580 out.pos = 0;
581 try serializer.serialize(u14(3));
582 try serializer.serialize(u14(88));
583 expectError(error.InvalidEnumTag, deserializer.deserialize(C));
584}
585
586test "Deserializer bad data" {
587 try testBadData(.Big, .Byte);
588 try testBadData(.Little, .Byte);
589 try testBadData(.Big, .Bit);
590 try testBadData(.Little, .Bit);
591}
592
593test "c out stream" {
594 if (!builtin.link_libc) return error.SkipZigTest;
595
596 const filename = c"tmp_io_test_file.txt";
597 const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;
598 defer std.os.deleteFileC(filename) catch {};
599
600 const out_stream = &io.COutStream.init(out_file).stream;
601 try out_stream.print("hi: {}\n", i32(123));
602}
std/io_test.zig deleted-591
...@@ -1,591 +0,0 @@
1const std = @import("std.zig");
2const io = std.io;
3const meta = std.meta;
4const trait = std.trait;
5const DefaultPrng = std.rand.DefaultPrng;
6const expect = std.testing.expect;
7const expectError = std.testing.expectError;
8const mem = std.mem;
9const os = std.os;
10const builtin = @import("builtin");
11
12test "write a file, read it, then delete it" {
13 var raw_bytes: [200 * 1024]u8 = undefined;
14 var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator;
15
16 var data: [1024]u8 = undefined;
17 var prng = DefaultPrng.init(1234);
18 prng.random.bytes(data[0..]);
19 const tmp_file_name = "temp_test_file.txt";
20 {
21 var file = try os.File.openWrite(tmp_file_name);
22 defer file.close();
23
24 var file_out_stream = file.outStream();
25 var buf_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);
26 const st = &buf_stream.stream;
27 try st.print("begin");
28 try st.write(data[0..]);
29 try st.print("end");
30 try buf_stream.flush();
31 }
32
33 {
34 // make sure openWriteNoClobber doesn't harm the file
35 if (os.File.openWriteNoClobber(tmp_file_name, os.File.default_mode)) |file| {
36 unreachable;
37 } else |err| {
38 std.debug.assert(err == os.File.OpenError.PathAlreadyExists);
39 }
40 }
41
42 {
43 var file = try os.File.openRead(tmp_file_name);
44 defer file.close();
45
46 const file_size = try file.getEndPos();
47 const expected_file_size = "begin".len + data.len + "end".len;
48 expect(file_size == expected_file_size);
49
50 var file_in_stream = file.inStream();
51 var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);
52 const st = &buf_stream.stream;
53 const contents = try st.readAllAlloc(allocator, 2 * 1024);
54 defer allocator.free(contents);
55
56 expect(mem.eql(u8, contents[0.."begin".len], "begin"));
57 expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
58 expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
59 }
60 try os.deleteFile(tmp_file_name);
61}
62
63test "BufferOutStream" {
64 var bytes: [100]u8 = undefined;
65 var allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
66
67 var buffer = try std.Buffer.initSize(allocator, 0);
68 var buf_stream = &std.io.BufferOutStream.init(&buffer).stream;
69
70 const x: i32 = 42;
71 const y: i32 = 1234;
72 try buf_stream.print("x: {}\ny: {}\n", x, y);
73
74 expect(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
75}
76
77test "SliceInStream" {
78 const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7 };
79 var ss = io.SliceInStream.init(bytes);
80
81 var dest: [4]u8 = undefined;
82
83 var read = try ss.stream.read(dest[0..4]);
84 expect(read == 4);
85 expect(mem.eql(u8, dest[0..4], bytes[0..4]));
86
87 read = try ss.stream.read(dest[0..4]);
88 expect(read == 3);
89 expect(mem.eql(u8, dest[0..3], bytes[4..7]));
90
91 read = try ss.stream.read(dest[0..4]);
92 expect(read == 0);
93}
94
95test "PeekStream" {
96 const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
97 var ss = io.SliceInStream.init(bytes);
98 var ps = io.PeekStream(2, io.SliceInStream.Error).init(&ss.stream);
99
100 var dest: [4]u8 = undefined;
101
102 ps.putBackByte(9);
103 ps.putBackByte(10);
104
105 var read = try ps.stream.read(dest[0..4]);
106 expect(read == 4);
107 expect(dest[0] == 10);
108 expect(dest[1] == 9);
109 expect(mem.eql(u8, dest[2..4], bytes[0..2]));
110
111 read = try ps.stream.read(dest[0..4]);
112 expect(read == 4);
113 expect(mem.eql(u8, dest[0..4], bytes[2..6]));
114
115 read = try ps.stream.read(dest[0..4]);
116 expect(read == 2);
117 expect(mem.eql(u8, dest[0..2], bytes[6..8]));
118
119 ps.putBackByte(11);
120 ps.putBackByte(12);
121
122 read = try ps.stream.read(dest[0..4]);
123 expect(read == 2);
124 expect(dest[0] == 12);
125 expect(dest[1] == 11);
126}
127
128test "SliceOutStream" {
129 var buffer: [10]u8 = undefined;
130 var ss = io.SliceOutStream.init(buffer[0..]);
131
132 try ss.stream.write("Hello");
133 expect(mem.eql(u8, ss.getWritten(), "Hello"));
134
135 try ss.stream.write("world");
136 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
137
138 expectError(error.OutOfSpace, ss.stream.write("!"));
139 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
140
141 ss.reset();
142 expect(ss.getWritten().len == 0);
143
144 expectError(error.OutOfSpace, ss.stream.write("Hello world!"));
145 expect(mem.eql(u8, ss.getWritten(), "Hello worl"));
146}
147
148test "BitInStream" {
149 const mem_be = []u8{ 0b11001101, 0b00001011 };
150 const mem_le = []u8{ 0b00011101, 0b10010101 };
151
152 var mem_in_be = io.SliceInStream.init(mem_be[0..]);
153 const InError = io.SliceInStream.Error;
154 var bit_stream_be = io.BitInStream(builtin.Endian.Big, InError).init(&mem_in_be.stream);
155
156 var out_bits: usize = undefined;
157
158 expect(1 == try bit_stream_be.readBits(u2, 1, &out_bits));
159 expect(out_bits == 1);
160 expect(2 == try bit_stream_be.readBits(u5, 2, &out_bits));
161 expect(out_bits == 2);
162 expect(3 == try bit_stream_be.readBits(u128, 3, &out_bits));
163 expect(out_bits == 3);
164 expect(4 == try bit_stream_be.readBits(u8, 4, &out_bits));
165 expect(out_bits == 4);
166 expect(5 == try bit_stream_be.readBits(u9, 5, &out_bits));
167 expect(out_bits == 5);
168 expect(1 == try bit_stream_be.readBits(u1, 1, &out_bits));
169 expect(out_bits == 1);
170
171 mem_in_be.pos = 0;
172 bit_stream_be.bit_count = 0;
173 expect(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits));
174 expect(out_bits == 15);
175
176 mem_in_be.pos = 0;
177 bit_stream_be.bit_count = 0;
178 expect(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits));
179 expect(out_bits == 16);
180
181 _ = try bit_stream_be.readBits(u0, 0, &out_bits);
182
183 expect(0 == try bit_stream_be.readBits(u1, 1, &out_bits));
184 expect(out_bits == 0);
185 expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));
186
187 var mem_in_le = io.SliceInStream.init(mem_le[0..]);
188 var bit_stream_le = io.BitInStream(builtin.Endian.Little, InError).init(&mem_in_le.stream);
189
190 expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
191 expect(out_bits == 1);
192 expect(2 == try bit_stream_le.readBits(u5, 2, &out_bits));
193 expect(out_bits == 2);
194 expect(3 == try bit_stream_le.readBits(u128, 3, &out_bits));
195 expect(out_bits == 3);
196 expect(4 == try bit_stream_le.readBits(u8, 4, &out_bits));
197 expect(out_bits == 4);
198 expect(5 == try bit_stream_le.readBits(u9, 5, &out_bits));
199 expect(out_bits == 5);
200 expect(1 == try bit_stream_le.readBits(u1, 1, &out_bits));
201 expect(out_bits == 1);
202
203 mem_in_le.pos = 0;
204 bit_stream_le.bit_count = 0;
205 expect(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits));
206 expect(out_bits == 15);
207
208 mem_in_le.pos = 0;
209 bit_stream_le.bit_count = 0;
210 expect(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits));
211 expect(out_bits == 16);
212
213 _ = try bit_stream_le.readBits(u0, 0, &out_bits);
214
215 expect(0 == try bit_stream_le.readBits(u1, 1, &out_bits));
216 expect(out_bits == 0);
217 expectError(error.EndOfStream, bit_stream_le.readBitsNoEof(u1, 1));
218}
219
220test "BitOutStream" {
221 var mem_be = []u8{0} ** 2;
222 var mem_le = []u8{0} ** 2;
223
224 var mem_out_be = io.SliceOutStream.init(mem_be[0..]);
225 const OutError = io.SliceOutStream.Error;
226 var bit_stream_be = io.BitOutStream(builtin.Endian.Big, OutError).init(&mem_out_be.stream);
227
228 try bit_stream_be.writeBits(u2(1), 1);
229 try bit_stream_be.writeBits(u5(2), 2);
230 try bit_stream_be.writeBits(u128(3), 3);
231 try bit_stream_be.writeBits(u8(4), 4);
232 try bit_stream_be.writeBits(u9(5), 5);
233 try bit_stream_be.writeBits(u1(1), 1);
234
235 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
236
237 mem_out_be.pos = 0;
238
239 try bit_stream_be.writeBits(u15(0b110011010000101), 15);
240 try bit_stream_be.flushBits();
241 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
242
243 mem_out_be.pos = 0;
244 try bit_stream_be.writeBits(u32(0b110011010000101), 16);
245 expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
246
247 try bit_stream_be.writeBits(u0(0), 0);
248
249 var mem_out_le = io.SliceOutStream.init(mem_le[0..]);
250 var bit_stream_le = io.BitOutStream(builtin.Endian.Little, OutError).init(&mem_out_le.stream);
251
252 try bit_stream_le.writeBits(u2(1), 1);
253 try bit_stream_le.writeBits(u5(2), 2);
254 try bit_stream_le.writeBits(u128(3), 3);
255 try bit_stream_le.writeBits(u8(4), 4);
256 try bit_stream_le.writeBits(u9(5), 5);
257 try bit_stream_le.writeBits(u1(1), 1);
258
259 expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
260
261 mem_out_le.pos = 0;
262 try bit_stream_le.writeBits(u15(0b110011010000101), 15);
263 try bit_stream_le.flushBits();
264 expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
265
266 mem_out_le.pos = 0;
267 try bit_stream_le.writeBits(u32(0b1100110100001011), 16);
268 expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
269
270 try bit_stream_le.writeBits(u0(0), 0);
271}
272
273test "BitStreams with File Stream" {
274 const tmp_file_name = "temp_test_file.txt";
275 {
276 var file = try os.File.openWrite(tmp_file_name);
277 defer file.close();
278
279 var file_out = file.outStream();
280 var file_out_stream = &file_out.stream;
281 const OutError = os.File.WriteError;
282 var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
283
284 try bit_stream.writeBits(u2(1), 1);
285 try bit_stream.writeBits(u5(2), 2);
286 try bit_stream.writeBits(u128(3), 3);
287 try bit_stream.writeBits(u8(4), 4);
288 try bit_stream.writeBits(u9(5), 5);
289 try bit_stream.writeBits(u1(1), 1);
290 try bit_stream.flushBits();
291 }
292 {
293 var file = try os.File.openRead(tmp_file_name);
294 defer file.close();
295
296 var file_in = file.inStream();
297 var file_in_stream = &file_in.stream;
298 const InError = os.File.ReadError;
299 var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
300
301 var out_bits: usize = undefined;
302
303 expect(1 == try bit_stream.readBits(u2, 1, &out_bits));
304 expect(out_bits == 1);
305 expect(2 == try bit_stream.readBits(u5, 2, &out_bits));
306 expect(out_bits == 2);
307 expect(3 == try bit_stream.readBits(u128, 3, &out_bits));
308 expect(out_bits == 3);
309 expect(4 == try bit_stream.readBits(u8, 4, &out_bits));
310 expect(out_bits == 4);
311 expect(5 == try bit_stream.readBits(u9, 5, &out_bits));
312 expect(out_bits == 5);
313 expect(1 == try bit_stream.readBits(u1, 1, &out_bits));
314 expect(out_bits == 1);
315
316 expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1));
317 }
318 try os.deleteFile(tmp_file_name);
319}
320
321fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
322 //@NOTE: if this test is taking too long, reduce the maximum tested bitsize
323 const max_test_bitsize = 128;
324
325 const total_bytes = comptime blk: {
326 var bytes = 0;
327 comptime var i = 0;
328 while (i <= max_test_bitsize) : (i += 1) bytes += (i / 8) + @boolToInt(i % 8 > 0);
329 break :blk bytes * 2;
330 };
331
332 var data_mem: [total_bytes]u8 = undefined;
333 var out = io.SliceOutStream.init(data_mem[0..]);
334 const OutError = io.SliceOutStream.Error;
335 var out_stream = &out.stream;
336 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
337
338 var in = io.SliceInStream.init(data_mem[0..]);
339 const InError = io.SliceInStream.Error;
340 var in_stream = &in.stream;
341 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
342
343 comptime var i = 0;
344 inline while (i <= max_test_bitsize) : (i += 1) {
345 const U = @IntType(false, i);
346 const S = @IntType(true, i);
347 try serializer.serializeInt(U(i));
348 if (i != 0) try serializer.serializeInt(S(-1)) else try serializer.serialize(S(0));
349 }
350 try serializer.flush();
351
352 i = 0;
353 inline while (i <= max_test_bitsize) : (i += 1) {
354 const U = @IntType(false, i);
355 const S = @IntType(true, i);
356 const x = try deserializer.deserializeInt(U);
357 const y = try deserializer.deserializeInt(S);
358 expect(x == U(i));
359 if (i != 0) expect(y == S(-1)) else expect(y == 0);
360 }
361
362 const u8_bit_count = comptime meta.bitCount(u8);
363 //0 + 1 + 2 + ... n = (n * (n + 1)) / 2
364 //and we have each for unsigned and signed, so * 2
365 const total_bits = (max_test_bitsize * (max_test_bitsize + 1));
366 const extra_packed_byte = @boolToInt(total_bits % u8_bit_count > 0);
367 const total_packed_bytes = (total_bits / u8_bit_count) + extra_packed_byte;
368
369 expect(in.pos == if (packing == .Bit) total_packed_bytes else total_bytes);
370
371 //Verify that empty error set works with serializer.
372 //deserializer is covered by SliceInStream
373 const NullError = io.NullOutStream.Error;
374 var null_out = io.NullOutStream.init();
375 var null_out_stream = &null_out.stream;
376 var null_serializer = io.Serializer(endian, packing, NullError).init(null_out_stream);
377 try null_serializer.serialize(data_mem[0..]);
378 try null_serializer.flush();
379}
380
381test "Serializer/Deserializer Int" {
382 try testIntSerializerDeserializer(.Big, .Byte);
383 try testIntSerializerDeserializer(.Little, .Byte);
384 // TODO these tests are disabled due to tripping an LLVM assertion
385 // https://github.com/ziglang/zig/issues/2019
386 //try testIntSerializerDeserializer(builtin.Endian.Big, true);
387 //try testIntSerializerDeserializer(builtin.Endian.Little, true);
388}
389
390fn testIntSerializerDeserializerInfNaN(
391 comptime endian: builtin.Endian,
392 comptime packing: io.Packing,
393) !void {
394 const mem_size = (16 * 2 + 32 * 2 + 64 * 2 + 128 * 2) / comptime meta.bitCount(u8);
395 var data_mem: [mem_size]u8 = undefined;
396
397 var out = io.SliceOutStream.init(data_mem[0..]);
398 const OutError = io.SliceOutStream.Error;
399 var out_stream = &out.stream;
400 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
401
402 var in = io.SliceInStream.init(data_mem[0..]);
403 const InError = io.SliceInStream.Error;
404 var in_stream = &in.stream;
405 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
406
407 //@TODO: isInf/isNan not currently implemented for f128.
408 try serializer.serialize(std.math.nan(f16));
409 try serializer.serialize(std.math.inf(f16));
410 try serializer.serialize(std.math.nan(f32));
411 try serializer.serialize(std.math.inf(f32));
412 try serializer.serialize(std.math.nan(f64));
413 try serializer.serialize(std.math.inf(f64));
414 //try serializer.serialize(std.math.nan(f128));
415 //try serializer.serialize(std.math.inf(f128));
416 const nan_check_f16 = try deserializer.deserialize(f16);
417 const inf_check_f16 = try deserializer.deserialize(f16);
418 const nan_check_f32 = try deserializer.deserialize(f32);
419 const inf_check_f32 = try deserializer.deserialize(f32);
420 const nan_check_f64 = try deserializer.deserialize(f64);
421 const inf_check_f64 = try deserializer.deserialize(f64);
422 //const nan_check_f128 = try deserializer.deserialize(f128);
423 //const inf_check_f128 = try deserializer.deserialize(f128);
424 expect(std.math.isNan(nan_check_f16));
425 expect(std.math.isInf(inf_check_f16));
426 expect(std.math.isNan(nan_check_f32));
427 expect(std.math.isInf(inf_check_f32));
428 expect(std.math.isNan(nan_check_f64));
429 expect(std.math.isInf(inf_check_f64));
430 //expect(std.math.isNan(nan_check_f128));
431 //expect(std.math.isInf(inf_check_f128));
432}
433
434test "Serializer/Deserializer Int: Inf/NaN" {
435 try testIntSerializerDeserializerInfNaN(.Big, .Byte);
436 try testIntSerializerDeserializerInfNaN(.Little, .Byte);
437 try testIntSerializerDeserializerInfNaN(.Big, .Bit);
438 try testIntSerializerDeserializerInfNaN(.Little, .Bit);
439}
440
441fn testAlternateSerializer(self: var, serializer: var) !void {
442 try serializer.serialize(self.f_f16);
443}
444
445fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
446 const ColorType = enum(u4) {
447 RGB8 = 1,
448 RA16 = 2,
449 R32 = 3,
450 };
451
452 const TagAlign = union(enum(u32)) {
453 A: u8,
454 B: u8,
455 C: u8,
456 };
457
458 const Color = union(ColorType) {
459 RGB8: struct {
460 r: u8,
461 g: u8,
462 b: u8,
463 a: u8,
464 },
465 RA16: struct {
466 r: u16,
467 a: u16,
468 },
469 R32: u32,
470 };
471
472 const PackedStruct = packed struct {
473 f_i3: i3,
474 f_u2: u2,
475 };
476
477 //to test custom serialization
478 const Custom = struct {
479 f_f16: f16,
480 f_unused_u32: u32,
481
482 pub fn deserialize(self: *@This(), deserializer: var) !void {
483 try deserializer.deserializeInto(&self.f_f16);
484 self.f_unused_u32 = 47;
485 }
486
487 pub const serialize = testAlternateSerializer;
488 };
489
490 const MyStruct = struct {
491 f_i3: i3,
492 f_u8: u8,
493 f_tag_align: TagAlign,
494 f_u24: u24,
495 f_i19: i19,
496 f_void: void,
497 f_f32: f32,
498 f_f128: f128,
499 f_packed_0: PackedStruct,
500 f_i7arr: [10]i7,
501 f_of64n: ?f64,
502 f_of64v: ?f64,
503 f_color_type: ColorType,
504 f_packed_1: PackedStruct,
505 f_custom: Custom,
506 f_color: Color,
507 };
508
509 const my_inst = MyStruct{
510 .f_i3 = -1,
511 .f_u8 = 8,
512 .f_tag_align = TagAlign{ .B = 148 },
513 .f_u24 = 24,
514 .f_i19 = 19,
515 .f_void = {},
516 .f_f32 = 32.32,
517 .f_f128 = 128.128,
518 .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 },
519 .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
520 .f_of64n = null,
521 .f_of64v = 64.64,
522 .f_color_type = ColorType.R32,
523 .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 },
524 .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 },
525 .f_color = Color{ .R32 = 123822 },
526 };
527
528 var data_mem: [@sizeOf(MyStruct)]u8 = undefined;
529 var out = io.SliceOutStream.init(data_mem[0..]);
530 const OutError = io.SliceOutStream.Error;
531 var out_stream = &out.stream;
532 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
533
534 var in = io.SliceInStream.init(data_mem[0..]);
535 const InError = io.SliceInStream.Error;
536 var in_stream = &in.stream;
537 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
538
539 try serializer.serialize(my_inst);
540
541 const my_copy = try deserializer.deserialize(MyStruct);
542 expect(meta.eql(my_copy, my_inst));
543}
544
545test "Serializer/Deserializer generic" {
546 try testSerializerDeserializer(builtin.Endian.Big, .Byte);
547 try testSerializerDeserializer(builtin.Endian.Little, .Byte);
548 try testSerializerDeserializer(builtin.Endian.Big, .Bit);
549 try testSerializerDeserializer(builtin.Endian.Little, .Bit);
550}
551
552fn testBadData(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
553 const E = enum(u14) {
554 One = 1,
555 Two = 2,
556 };
557
558 const A = struct {
559 e: E,
560 };
561
562 const C = union(E) {
563 One: u14,
564 Two: f16,
565 };
566
567 var data_mem: [4]u8 = undefined;
568 var out = io.SliceOutStream.init(data_mem[0..]);
569 const OutError = io.SliceOutStream.Error;
570 var out_stream = &out.stream;
571 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
572
573 var in = io.SliceInStream.init(data_mem[0..]);
574 const InError = io.SliceInStream.Error;
575 var in_stream = &in.stream;
576 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
577
578 try serializer.serialize(u14(3));
579 expectError(error.InvalidEnumTag, deserializer.deserialize(A));
580 out.pos = 0;
581 try serializer.serialize(u14(3));
582 try serializer.serialize(u14(88));
583 expectError(error.InvalidEnumTag, deserializer.deserialize(C));
584}
585
586test "Deserializer bad data" {
587 try testBadData(.Big, .Byte);
588 try testBadData(.Little, .Byte);
589 try testBadData(.Big, .Bit);
590 try testBadData(.Little, .Bit);
591}
std/json.zig+4
...@@ -1400,3 +1400,7 @@ test "json.parser.dynamic" {...@@ -1400,3 +1400,7 @@ test "json.parser.dynamic" {
1400 const double = image.Object.get("double").?.value;1400 const double = image.Object.get("double").?.value;
1401 testing.expect(double.Float == 1.3412);1401 testing.expect(double.Float == 1.3412);
1402}1402}
1403
1404test "import more json tests" {
1405 _ = @import("json/test.zig");
1406}
std/json/test.zig created+1904
...@@ -0,0 +1,1904 @@
1// RFC 8529 conformance tests.
2//
3// Tests are taken from https://github.com/nst/JSONTestSuite
4// Read also http://seriot.ch/parsing_json.php for a good overview.
5
6const std = @import("../std.zig");
7
8fn ok(comptime s: []const u8) void {
9 std.testing.expect(std.json.validate(s));
10}
11
12fn err(comptime s: []const u8) void {
13 std.testing.expect(!std.json.validate(s));
14}
15
16fn any(comptime s: []const u8) void {
17 std.testing.expect(true);
18}
19
20////////////////////////////////////////////////////////////////////////////////////////////////////
21//
22// Additional tests not part of test JSONTestSuite.
23
24test "y_trailing_comma_after_empty" {
25 ok(
26 \\{"1":[],"2":{},"3":"4"}
27 );
28}
29
30////////////////////////////////////////////////////////////////////////////////////////////////////
31
32test "y_array_arraysWithSpaces" {
33 ok(
34 \\[[] ]
35 );
36}
37
38test "y_array_empty" {
39 ok(
40 \\[]
41 );
42}
43
44test "y_array_empty-string" {
45 ok(
46 \\[""]
47 );
48}
49
50test "y_array_ending_with_newline" {
51 ok(
52 \\["a"]
53 );
54}
55
56test "y_array_false" {
57 ok(
58 \\[false]
59 );
60}
61
62test "y_array_heterogeneous" {
63 ok(
64 \\[null, 1, "1", {}]
65 );
66}
67
68test "y_array_null" {
69 ok(
70 \\[null]
71 );
72}
73
74test "y_array_with_1_and_newline" {
75 ok(
76 \\[1
77 \\]
78 );
79}
80
81test "y_array_with_leading_space" {
82 ok(
83 \\ [1]
84 );
85}
86
87test "y_array_with_several_null" {
88 ok(
89 \\[1,null,null,null,2]
90 );
91}
92
93test "y_array_with_trailing_space" {
94 ok("[2] ");
95}
96
97test "y_number_0e+1" {
98 ok(
99 \\[0e+1]
100 );
101}
102
103test "y_number_0e1" {
104 ok(
105 \\[0e1]
106 );
107}
108
109test "y_number_after_space" {
110 ok(
111 \\[ 4]
112 );
113}
114
115test "y_number_double_close_to_zero" {
116 ok(
117 \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]
118 );
119}
120
121test "y_number_int_with_exp" {
122 ok(
123 \\[20e1]
124 );
125}
126
127test "y_number" {
128 ok(
129 \\[123e65]
130 );
131}
132
133test "y_number_minus_zero" {
134 ok(
135 \\[-0]
136 );
137}
138
139test "y_number_negative_int" {
140 ok(
141 \\[-123]
142 );
143}
144
145test "y_number_negative_one" {
146 ok(
147 \\[-1]
148 );
149}
150
151test "y_number_negative_zero" {
152 ok(
153 \\[-0]
154 );
155}
156
157test "y_number_real_capital_e" {
158 ok(
159 \\[1E22]
160 );
161}
162
163test "y_number_real_capital_e_neg_exp" {
164 ok(
165 \\[1E-2]
166 );
167}
168
169test "y_number_real_capital_e_pos_exp" {
170 ok(
171 \\[1E+2]
172 );
173}
174
175test "y_number_real_exponent" {
176 ok(
177 \\[123e45]
178 );
179}
180
181test "y_number_real_fraction_exponent" {
182 ok(
183 \\[123.456e78]
184 );
185}
186
187test "y_number_real_neg_exp" {
188 ok(
189 \\[1e-2]
190 );
191}
192
193test "y_number_real_pos_exponent" {
194 ok(
195 \\[1e+2]
196 );
197}
198
199test "y_number_simple_int" {
200 ok(
201 \\[123]
202 );
203}
204
205test "y_number_simple_real" {
206 ok(
207 \\[123.456789]
208 );
209}
210
211test "y_object_basic" {
212 ok(
213 \\{"asd":"sdf"}
214 );
215}
216
217test "y_object_duplicated_key_and_value" {
218 ok(
219 \\{"a":"b","a":"b"}
220 );
221}
222
223test "y_object_duplicated_key" {
224 ok(
225 \\{"a":"b","a":"c"}
226 );
227}
228
229test "y_object_empty" {
230 ok(
231 \\{}
232 );
233}
234
235test "y_object_empty_key" {
236 ok(
237 \\{"":0}
238 );
239}
240
241test "y_object_escaped_null_in_key" {
242 ok(
243 \\{"foo\u0000bar": 42}
244 );
245}
246
247test "y_object_extreme_numbers" {
248 ok(
249 \\{ "min": -1.0e+28, "max": 1.0e+28 }
250 );
251}
252
253test "y_object" {
254 ok(
255 \\{"asd":"sdf", "dfg":"fgh"}
256 );
257}
258
259test "y_object_long_strings" {
260 ok(
261 \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
262 );
263}
264
265test "y_object_simple" {
266 ok(
267 \\{"a":[]}
268 );
269}
270
271test "y_object_string_unicode" {
272 ok(
273 \\{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" }
274 );
275}
276
277test "y_object_with_newlines" {
278 ok(
279 \\{
280 \\"a": "b"
281 \\}
282 );
283}
284
285test "y_string_1_2_3_bytes_UTF-8_sequences" {
286 ok(
287 \\["\u0060\u012a\u12AB"]
288 );
289}
290
291test "y_string_accepted_surrogate_pair" {
292 ok(
293 \\["\uD801\udc37"]
294 );
295}
296
297test "y_string_accepted_surrogate_pairs" {
298 ok(
299 \\["\ud83d\ude39\ud83d\udc8d"]
300 );
301}
302
303test "y_string_allowed_escapes" {
304 ok(
305 \\["\"\\\/\b\f\n\r\t"]
306 );
307}
308
309test "y_string_backslash_and_u_escaped_zero" {
310 ok(
311 \\["\\u0000"]
312 );
313}
314
315test "y_string_backslash_doublequotes" {
316 ok(
317 \\["\""]
318 );
319}
320
321test "y_string_comments" {
322 ok(
323 \\["a/*b*/c/*d//e"]
324 );
325}
326
327test "y_string_double_escape_a" {
328 ok(
329 \\["\\a"]
330 );
331}
332
333test "y_string_double_escape_n" {
334 ok(
335 \\["\\n"]
336 );
337}
338
339test "y_string_escaped_control_character" {
340 ok(
341 \\["\u0012"]
342 );
343}
344
345test "y_string_escaped_noncharacter" {
346 ok(
347 \\["\uFFFF"]
348 );
349}
350
351test "y_string_in_array" {
352 ok(
353 \\["asd"]
354 );
355}
356
357test "y_string_in_array_with_leading_space" {
358 ok(
359 \\[ "asd"]
360 );
361}
362
363test "y_string_last_surrogates_1_and_2" {
364 ok(
365 \\["\uDBFF\uDFFF"]
366 );
367}
368
369test "y_string_nbsp_uescaped" {
370 ok(
371 \\["new\u00A0line"]
372 );
373}
374
375test "y_string_nonCharacterInUTF-8_U+10FFFF" {
376 ok(
377 \\["􏿿"]
378 );
379}
380
381test "y_string_nonCharacterInUTF-8_U+FFFF" {
382 ok(
383 \\["￿"]
384 );
385}
386
387test "y_string_null_escape" {
388 ok(
389 \\["\u0000"]
390 );
391}
392
393test "y_string_one-byte-utf-8" {
394 ok(
395 \\["\u002c"]
396 );
397}
398
399test "y_string_pi" {
400 ok(
401 \\["π"]
402 );
403}
404
405test "y_string_reservedCharacterInUTF-8_U+1BFFF" {
406 ok(
407 \\["𛿿"]
408 );
409}
410
411test "y_string_simple_ascii" {
412 ok(
413 \\["asd "]
414 );
415}
416
417test "y_string_space" {
418 ok(
419 \\" "
420 );
421}
422
423test "y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" {
424 ok(
425 \\["\uD834\uDd1e"]
426 );
427}
428
429test "y_string_three-byte-utf-8" {
430 ok(
431 \\["\u0821"]
432 );
433}
434
435test "y_string_two-byte-utf-8" {
436 ok(
437 \\["\u0123"]
438 );
439}
440
441test "y_string_u+2028_line_sep" {
442 ok("[\"\xe2\x80\xa8\"]");
443}
444
445test "y_string_u+2029_par_sep" {
446 ok("[\"\xe2\x80\xa9\"]");
447}
448
449test "y_string_uescaped_newline" {
450 ok(
451 \\["new\u000Aline"]
452 );
453}
454
455test "y_string_uEscape" {
456 ok(
457 \\["\u0061\u30af\u30EA\u30b9"]
458 );
459}
460
461test "y_string_unescaped_char_delete" {
462 ok("[\"\x7f\"]");
463}
464
465test "y_string_unicode_2" {
466 ok(
467 \\["⍂㈴⍂"]
468 );
469}
470
471test "y_string_unicodeEscapedBackslash" {
472 ok(
473 \\["\u005C"]
474 );
475}
476
477test "y_string_unicode_escaped_double_quote" {
478 ok(
479 \\["\u0022"]
480 );
481}
482
483test "y_string_unicode" {
484 ok(
485 \\["\uA66D"]
486 );
487}
488
489test "y_string_unicode_U+10FFFE_nonchar" {
490 ok(
491 \\["\uDBFF\uDFFE"]
492 );
493}
494
495test "y_string_unicode_U+1FFFE_nonchar" {
496 ok(
497 \\["\uD83F\uDFFE"]
498 );
499}
500
501test "y_string_unicode_U+200B_ZERO_WIDTH_SPACE" {
502 ok(
503 \\["\u200B"]
504 );
505}
506
507test "y_string_unicode_U+2064_invisible_plus" {
508 ok(
509 \\["\u2064"]
510 );
511}
512
513test "y_string_unicode_U+FDD0_nonchar" {
514 ok(
515 \\["\uFDD0"]
516 );
517}
518
519test "y_string_unicode_U+FFFE_nonchar" {
520 ok(
521 \\["\uFFFE"]
522 );
523}
524
525test "y_string_utf8" {
526 ok(
527 \\["€𝄞"]
528 );
529}
530
531test "y_string_with_del_character" {
532 ok("[\"a\x7fa\"]");
533}
534
535test "y_structure_lonely_false" {
536 ok(
537 \\false
538 );
539}
540
541test "y_structure_lonely_int" {
542 ok(
543 \\42
544 );
545}
546
547test "y_structure_lonely_negative_real" {
548 ok(
549 \\-0.1
550 );
551}
552
553test "y_structure_lonely_null" {
554 ok(
555 \\null
556 );
557}
558
559test "y_structure_lonely_string" {
560 ok(
561 \\"asd"
562 );
563}
564
565test "y_structure_lonely_true" {
566 ok(
567 \\true
568 );
569}
570
571test "y_structure_string_empty" {
572 ok(
573 \\""
574 );
575}
576
577test "y_structure_trailing_newline" {
578 ok(
579 \\["a"]
580 );
581}
582
583test "y_structure_true_in_array" {
584 ok(
585 \\[true]
586 );
587}
588
589test "y_structure_whitespace_array" {
590 ok(" [] ");
591}
592
593////////////////////////////////////////////////////////////////////////////////////////////////////
594
595test "n_array_1_true_without_comma" {
596 err(
597 \\[1 true]
598 );
599}
600
601test "n_array_a_invalid_utf8" {
602 err(
603 \\[aå]
604 );
605}
606
607test "n_array_colon_instead_of_comma" {
608 err(
609 \\["": 1]
610 );
611}
612
613test "n_array_comma_after_close" {
614 //err(
615 // \\[""],
616 //);
617}
618
619test "n_array_comma_and_number" {
620 err(
621 \\[,1]
622 );
623}
624
625test "n_array_double_comma" {
626 err(
627 \\[1,,2]
628 );
629}
630
631test "n_array_double_extra_comma" {
632 err(
633 \\["x",,]
634 );
635}
636
637test "n_array_extra_close" {
638 err(
639 \\["x"]]
640 );
641}
642
643test "n_array_extra_comma" {
644 //err(
645 // \\["",]
646 //);
647}
648
649test "n_array_incomplete_invalid_value" {
650 err(
651 \\[x
652 );
653}
654
655test "n_array_incomplete" {
656 err(
657 \\["x"
658 );
659}
660
661test "n_array_inner_array_no_comma" {
662 err(
663 \\[3[4]]
664 );
665}
666
667test "n_array_invalid_utf8" {
668 err(
669 \\[ÿ]
670 );
671}
672
673test "n_array_items_separated_by_semicolon" {
674 err(
675 \\[1:2]
676 );
677}
678
679test "n_array_just_comma" {
680 err(
681 \\[,]
682 );
683}
684
685test "n_array_just_minus" {
686 err(
687 \\[-]
688 );
689}
690
691test "n_array_missing_value" {
692 err(
693 \\[ , ""]
694 );
695}
696
697test "n_array_newlines_unclosed" {
698 err(
699 \\["a",
700 \\4
701 \\,1,
702 );
703}
704
705test "n_array_number_and_comma" {
706 err(
707 \\[1,]
708 );
709}
710
711test "n_array_number_and_several_commas" {
712 err(
713 \\[1,,]
714 );
715}
716
717test "n_array_spaces_vertical_tab_formfeed" {
718 err("[\"\x0aa\"\\f]");
719}
720
721test "n_array_star_inside" {
722 err(
723 \\[*]
724 );
725}
726
727test "n_array_unclosed" {
728 err(
729 \\[""
730 );
731}
732
733test "n_array_unclosed_trailing_comma" {
734 err(
735 \\[1,
736 );
737}
738
739test "n_array_unclosed_with_new_lines" {
740 err(
741 \\[1,
742 \\1
743 \\,1
744 );
745}
746
747test "n_array_unclosed_with_object_inside" {
748 err(
749 \\[{}
750 );
751}
752
753test "n_incomplete_false" {
754 err(
755 \\[fals]
756 );
757}
758
759test "n_incomplete_null" {
760 err(
761 \\[nul]
762 );
763}
764
765test "n_incomplete_true" {
766 err(
767 \\[tru]
768 );
769}
770
771test "n_multidigit_number_then_00" {
772 err("123\x00");
773}
774
775test "n_number_0.1.2" {
776 err(
777 \\[0.1.2]
778 );
779}
780
781test "n_number_-01" {
782 err(
783 \\[-01]
784 );
785}
786
787test "n_number_0.3e" {
788 err(
789 \\[0.3e]
790 );
791}
792
793test "n_number_0.3e+" {
794 err(
795 \\[0.3e+]
796 );
797}
798
799test "n_number_0_capital_E" {
800 err(
801 \\[0E]
802 );
803}
804
805test "n_number_0_capital_E+" {
806 err(
807 \\[0E+]
808 );
809}
810
811test "n_number_0.e1" {
812 err(
813 \\[0.e1]
814 );
815}
816
817test "n_number_0e" {
818 err(
819 \\[0e]
820 );
821}
822
823test "n_number_0e+" {
824 err(
825 \\[0e+]
826 );
827}
828
829test "n_number_1_000" {
830 err(
831 \\[1 000.0]
832 );
833}
834
835test "n_number_1.0e-" {
836 err(
837 \\[1.0e-]
838 );
839}
840
841test "n_number_1.0e" {
842 err(
843 \\[1.0e]
844 );
845}
846
847test "n_number_1.0e+" {
848 err(
849 \\[1.0e+]
850 );
851}
852
853test "n_number_-1.0." {
854 err(
855 \\[-1.0.]
856 );
857}
858
859test "n_number_1eE2" {
860 err(
861 \\[1eE2]
862 );
863}
864
865test "n_number_.-1" {
866 err(
867 \\[.-1]
868 );
869}
870
871test "n_number_+1" {
872 err(
873 \\[+1]
874 );
875}
876
877test "n_number_.2e-3" {
878 err(
879 \\[.2e-3]
880 );
881}
882
883test "n_number_2.e-3" {
884 err(
885 \\[2.e-3]
886 );
887}
888
889test "n_number_2.e+3" {
890 err(
891 \\[2.e+3]
892 );
893}
894
895test "n_number_2.e3" {
896 err(
897 \\[2.e3]
898 );
899}
900
901test "n_number_-2." {
902 err(
903 \\[-2.]
904 );
905}
906
907test "n_number_9.e+" {
908 err(
909 \\[9.e+]
910 );
911}
912
913test "n_number_expression" {
914 err(
915 \\[1+2]
916 );
917}
918
919test "n_number_hex_1_digit" {
920 err(
921 \\[0x1]
922 );
923}
924
925test "n_number_hex_2_digits" {
926 err(
927 \\[0x42]
928 );
929}
930
931test "n_number_infinity" {
932 err(
933 \\[Infinity]
934 );
935}
936
937test "n_number_+Inf" {
938 err(
939 \\[+Inf]
940 );
941}
942
943test "n_number_Inf" {
944 err(
945 \\[Inf]
946 );
947}
948
949test "n_number_invalid+-" {
950 err(
951 \\[0e+-1]
952 );
953}
954
955test "n_number_invalid-negative-real" {
956 err(
957 \\[-123.123foo]
958 );
959}
960
961test "n_number_invalid-utf-8-in-bigger-int" {
962 err(
963 \\[123å]
964 );
965}
966
967test "n_number_invalid-utf-8-in-exponent" {
968 err(
969 \\[1e1å]
970 );
971}
972
973test "n_number_invalid-utf-8-in-int" {
974 err(
975 \\[0å]
976 );
977}
978
979test "n_number_++" {
980 err(
981 \\[++1234]
982 );
983}
984
985test "n_number_minus_infinity" {
986 err(
987 \\[-Infinity]
988 );
989}
990
991test "n_number_minus_sign_with_trailing_garbage" {
992 err(
993 \\[-foo]
994 );
995}
996
997test "n_number_minus_space_1" {
998 err(
999 \\[- 1]
1000 );
1001}
1002
1003test "n_number_-NaN" {
1004 err(
1005 \\[-NaN]
1006 );
1007}
1008
1009test "n_number_NaN" {
1010 err(
1011 \\[NaN]
1012 );
1013}
1014
1015test "n_number_neg_int_starting_with_zero" {
1016 err(
1017 \\[-012]
1018 );
1019}
1020
1021test "n_number_neg_real_without_int_part" {
1022 err(
1023 \\[-.123]
1024 );
1025}
1026
1027test "n_number_neg_with_garbage_at_end" {
1028 err(
1029 \\[-1x]
1030 );
1031}
1032
1033test "n_number_real_garbage_after_e" {
1034 err(
1035 \\[1ea]
1036 );
1037}
1038
1039test "n_number_real_with_invalid_utf8_after_e" {
1040 err(
1041 \\[1eå]
1042 );
1043}
1044
1045test "n_number_real_without_fractional_part" {
1046 err(
1047 \\[1.]
1048 );
1049}
1050
1051test "n_number_starting_with_dot" {
1052 err(
1053 \\[.123]
1054 );
1055}
1056
1057test "n_number_U+FF11_fullwidth_digit_one" {
1058 err(
1059 \\[1]
1060 );
1061}
1062
1063test "n_number_with_alpha_char" {
1064 err(
1065 \\[1.8011670033376514H-308]
1066 );
1067}
1068
1069test "n_number_with_alpha" {
1070 err(
1071 \\[1.2a-3]
1072 );
1073}
1074
1075test "n_number_with_leading_zero" {
1076 err(
1077 \\[012]
1078 );
1079}
1080
1081test "n_object_bad_value" {
1082 err(
1083 \\["x", truth]
1084 );
1085}
1086
1087test "n_object_bracket_key" {
1088 err(
1089 \\{[: "x"}
1090 );
1091}
1092
1093test "n_object_comma_instead_of_colon" {
1094 err(
1095 \\{"x", null}
1096 );
1097}
1098
1099test "n_object_double_colon" {
1100 err(
1101 \\{"x"::"b"}
1102 );
1103}
1104
1105test "n_object_emoji" {
1106 err(
1107 \\{🇨🇭}
1108 );
1109}
1110
1111test "n_object_garbage_at_end" {
1112 err(
1113 \\{"a":"a" 123}
1114 );
1115}
1116
1117test "n_object_key_with_single_quotes" {
1118 err(
1119 \\{key: 'value'}
1120 );
1121}
1122
1123test "n_object_lone_continuation_byte_in_key_and_trailing_comma" {
1124 err(
1125 \\{"¹":"0",}
1126 );
1127}
1128
1129test "n_object_missing_colon" {
1130 err(
1131 \\{"a" b}
1132 );
1133}
1134
1135test "n_object_missing_key" {
1136 err(
1137 \\{:"b"}
1138 );
1139}
1140
1141test "n_object_missing_semicolon" {
1142 err(
1143 \\{"a" "b"}
1144 );
1145}
1146
1147test "n_object_missing_value" {
1148 err(
1149 \\{"a":
1150 );
1151}
1152
1153test "n_object_no-colon" {
1154 err(
1155 \\{"a"
1156 );
1157}
1158
1159test "n_object_non_string_key_but_huge_number_instead" {
1160 err(
1161 \\{9999E9999:1}
1162 );
1163}
1164
1165test "n_object_non_string_key" {
1166 err(
1167 \\{1:1}
1168 );
1169}
1170
1171test "n_object_repeated_null_null" {
1172 err(
1173 \\{null:null,null:null}
1174 );
1175}
1176
1177test "n_object_several_trailing_commas" {
1178 err(
1179 \\{"id":0,,,,,}
1180 );
1181}
1182
1183test "n_object_single_quote" {
1184 err(
1185 \\{'a':0}
1186 );
1187}
1188
1189test "n_object_trailing_comma" {
1190 err(
1191 \\{"id":0,}
1192 );
1193}
1194
1195test "n_object_trailing_comment" {
1196 err(
1197 \\{"a":"b"}/**/
1198 );
1199}
1200
1201test "n_object_trailing_comment_open" {
1202 err(
1203 \\{"a":"b"}/**//
1204 );
1205}
1206
1207test "n_object_trailing_comment_slash_open_incomplete" {
1208 err(
1209 \\{"a":"b"}/
1210 );
1211}
1212
1213test "n_object_trailing_comment_slash_open" {
1214 err(
1215 \\{"a":"b"}//
1216 );
1217}
1218
1219test "n_object_two_commas_in_a_row" {
1220 err(
1221 \\{"a":"b",,"c":"d"}
1222 );
1223}
1224
1225test "n_object_unquoted_key" {
1226 err(
1227 \\{a: "b"}
1228 );
1229}
1230
1231test "n_object_unterminated-value" {
1232 err(
1233 \\{"a":"a
1234 );
1235}
1236
1237test "n_object_with_single_string" {
1238 err(
1239 \\{ "foo" : "bar", "a" }
1240 );
1241}
1242
1243test "n_object_with_trailing_garbage" {
1244 err(
1245 \\{"a":"b"}#
1246 );
1247}
1248
1249test "n_single_space" {
1250 err(" ");
1251}
1252
1253test "n_string_1_surrogate_then_escape" {
1254 err(
1255 \\["\uD800\"]
1256 );
1257}
1258
1259test "n_string_1_surrogate_then_escape_u1" {
1260 err(
1261 \\["\uD800\u1"]
1262 );
1263}
1264
1265test "n_string_1_surrogate_then_escape_u1x" {
1266 err(
1267 \\["\uD800\u1x"]
1268 );
1269}
1270
1271test "n_string_1_surrogate_then_escape_u" {
1272 err(
1273 \\["\uD800\u"]
1274 );
1275}
1276
1277test "n_string_accentuated_char_no_quotes" {
1278 err(
1279 \\[é]
1280 );
1281}
1282
1283test "n_string_backslash_00" {
1284 err("[\"\x00\"]");
1285}
1286
1287test "n_string_escaped_backslash_bad" {
1288 err(
1289 \\["\\\"]
1290 );
1291}
1292
1293test "n_string_escaped_ctrl_char_tab" {
1294 err("\x5b\x22\x5c\x09\x22\x5d");
1295}
1296
1297test "n_string_escaped_emoji" {
1298 err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]");
1299}
1300
1301test "n_string_escape_x" {
1302 err(
1303 \\["\x00"]
1304 );
1305}
1306
1307test "n_string_incomplete_escaped_character" {
1308 err(
1309 \\["\u00A"]
1310 );
1311}
1312
1313test "n_string_incomplete_escape" {
1314 err(
1315 \\["\"]
1316 );
1317}
1318
1319test "n_string_incomplete_surrogate_escape_invalid" {
1320 err(
1321 \\["\uD800\uD800\x"]
1322 );
1323}
1324
1325test "n_string_incomplete_surrogate" {
1326 err(
1327 \\["\uD834\uDd"]
1328 );
1329}
1330
1331test "n_string_invalid_backslash_esc" {
1332 err(
1333 \\["\a"]
1334 );
1335}
1336
1337test "n_string_invalid_unicode_escape" {
1338 err(
1339 \\["\uqqqq"]
1340 );
1341}
1342
1343test "n_string_invalid_utf8_after_escape" {
1344 err("[\"\\\x75\xc3\xa5\"]");
1345}
1346
1347test "n_string_invalid-utf-8-in-escape" {
1348 err(
1349 \\["\uå"]
1350 );
1351}
1352
1353test "n_string_leading_uescaped_thinspace" {
1354 err(
1355 \\[\u0020"asd"]
1356 );
1357}
1358
1359test "n_string_no_quotes_with_bad_escape" {
1360 err(
1361 \\[\n]
1362 );
1363}
1364
1365test "n_string_single_doublequote" {
1366 err(
1367 \\"
1368 );
1369}
1370
1371test "n_string_single_quote" {
1372 err(
1373 \\['single quote']
1374 );
1375}
1376
1377test "n_string_single_string_no_double_quotes" {
1378 err(
1379 \\abc
1380 );
1381}
1382
1383test "n_string_start_escape_unclosed" {
1384 err(
1385 \\["\
1386 );
1387}
1388
1389test "n_string_unescaped_crtl_char" {
1390 err("[\"a\x00a\"]");
1391}
1392
1393test "n_string_unescaped_newline" {
1394 err(
1395 \\["new
1396 \\line"]
1397 );
1398}
1399
1400test "n_string_unescaped_tab" {
1401 err("[\"\t\"]");
1402}
1403
1404test "n_string_unicode_CapitalU" {
1405 err(
1406 \\"\UA66D"
1407 );
1408}
1409
1410test "n_string_with_trailing_garbage" {
1411 err(
1412 \\""x
1413 );
1414}
1415
1416test "n_structure_100000_opening_arrays" {
1417 err("[" ** 100000);
1418}
1419
1420test "n_structure_angle_bracket_." {
1421 err(
1422 \\<.>
1423 );
1424}
1425
1426test "n_structure_angle_bracket_null" {
1427 err(
1428 \\[<null>]
1429 );
1430}
1431
1432test "n_structure_array_trailing_garbage" {
1433 err(
1434 \\[1]x
1435 );
1436}
1437
1438test "n_structure_array_with_extra_array_close" {
1439 err(
1440 \\[1]]
1441 );
1442}
1443
1444test "n_structure_array_with_unclosed_string" {
1445 err(
1446 \\["asd]
1447 );
1448}
1449
1450test "n_structure_ascii-unicode-identifier" {
1451 err(
1452 \\aå
1453 );
1454}
1455
1456test "n_structure_capitalized_True" {
1457 err(
1458 \\[True]
1459 );
1460}
1461
1462test "n_structure_close_unopened_array" {
1463 err(
1464 \\1]
1465 );
1466}
1467
1468test "n_structure_comma_instead_of_closing_brace" {
1469 err(
1470 \\{"x": true,
1471 );
1472}
1473
1474test "n_structure_double_array" {
1475 err(
1476 \\[][]
1477 );
1478}
1479
1480test "n_structure_end_array" {
1481 err(
1482 \\]
1483 );
1484}
1485
1486test "n_structure_incomplete_UTF8_BOM" {
1487 err(
1488 \\ï»{}
1489 );
1490}
1491
1492test "n_structure_lone-invalid-utf-8" {
1493 err(
1494 \\å
1495 );
1496}
1497
1498test "n_structure_lone-open-bracket" {
1499 err(
1500 \\[
1501 );
1502}
1503
1504test "n_structure_no_data" {
1505 err(
1506 \\
1507 );
1508}
1509
1510test "n_structure_null-byte-outside-string" {
1511 err("[\x00]");
1512}
1513
1514test "n_structure_number_with_trailing_garbage" {
1515 err(
1516 \\2@
1517 );
1518}
1519
1520test "n_structure_object_followed_by_closing_object" {
1521 err(
1522 \\{}}
1523 );
1524}
1525
1526test "n_structure_object_unclosed_no_value" {
1527 err(
1528 \\{"":
1529 );
1530}
1531
1532test "n_structure_object_with_comment" {
1533 err(
1534 \\{"a":/*comment*/"b"}
1535 );
1536}
1537
1538test "n_structure_object_with_trailing_garbage" {
1539 err(
1540 \\{"a": true} "x"
1541 );
1542}
1543
1544test "n_structure_open_array_apostrophe" {
1545 err(
1546 \\['
1547 );
1548}
1549
1550test "n_structure_open_array_comma" {
1551 err(
1552 \\[,
1553 );
1554}
1555
1556test "n_structure_open_array_object" {
1557 err("[{\"\":" ** 50000);
1558}
1559
1560test "n_structure_open_array_open_object" {
1561 err(
1562 \\[{
1563 );
1564}
1565
1566test "n_structure_open_array_open_string" {
1567 err(
1568 \\["a
1569 );
1570}
1571
1572test "n_structure_open_array_string" {
1573 err(
1574 \\["a"
1575 );
1576}
1577
1578test "n_structure_open_object_close_array" {
1579 err(
1580 \\{]
1581 );
1582}
1583
1584test "n_structure_open_object_comma" {
1585 err(
1586 \\{,
1587 );
1588}
1589
1590test "n_structure_open_object" {
1591 err(
1592 \\{
1593 );
1594}
1595
1596test "n_structure_open_object_open_array" {
1597 err(
1598 \\{[
1599 );
1600}
1601
1602test "n_structure_open_object_open_string" {
1603 err(
1604 \\{"a
1605 );
1606}
1607
1608test "n_structure_open_object_string_with_apostrophes" {
1609 err(
1610 \\{'a'
1611 );
1612}
1613
1614test "n_structure_open_open" {
1615 err(
1616 \\["\{["\{["\{["\{
1617 );
1618}
1619
1620test "n_structure_single_eacute" {
1621 err(
1622 \\é
1623 );
1624}
1625
1626test "n_structure_single_star" {
1627 err(
1628 \\*
1629 );
1630}
1631
1632test "n_structure_trailing_#" {
1633 err(
1634 \\{"a":"b"}#{}
1635 );
1636}
1637
1638test "n_structure_U+2060_word_joined" {
1639 err(
1640 \\[⁠]
1641 );
1642}
1643
1644test "n_structure_uescaped_LF_before_string" {
1645 err(
1646 \\[\u000A""]
1647 );
1648}
1649
1650test "n_structure_unclosed_array" {
1651 err(
1652 \\[1
1653 );
1654}
1655
1656test "n_structure_unclosed_array_partial_null" {
1657 err(
1658 \\[ false, nul
1659 );
1660}
1661
1662test "n_structure_unclosed_array_unfinished_false" {
1663 err(
1664 \\[ true, fals
1665 );
1666}
1667
1668test "n_structure_unclosed_array_unfinished_true" {
1669 err(
1670 \\[ false, tru
1671 );
1672}
1673
1674test "n_structure_unclosed_object" {
1675 err(
1676 \\{"asd":"asd"
1677 );
1678}
1679
1680test "n_structure_unicode-identifier" {
1681 err(
1682 \\Ã¥
1683 );
1684}
1685
1686test "n_structure_UTF8_BOM_no_data" {
1687 err(
1688 \\
1689 );
1690}
1691
1692test "n_structure_whitespace_formfeed" {
1693 err("[\x0c]");
1694}
1695
1696test "n_structure_whitespace_U+2060_word_joiner" {
1697 err(
1698 \\[⁠]
1699 );
1700}
1701
1702////////////////////////////////////////////////////////////////////////////////////////////////////
1703
1704test "i_number_double_huge_neg_exp" {
1705 any(
1706 \\[123.456e-789]
1707 );
1708}
1709
1710test "i_number_huge_exp" {
1711 any(
1712 \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]
1713 );
1714}
1715
1716test "i_number_neg_int_huge_exp" {
1717 any(
1718 \\[-1e+9999]
1719 );
1720}
1721
1722test "i_number_pos_double_huge_exp" {
1723 any(
1724 \\[1.5e+9999]
1725 );
1726}
1727
1728test "i_number_real_neg_overflow" {
1729 any(
1730 \\[-123123e100000]
1731 );
1732}
1733
1734test "i_number_real_pos_overflow" {
1735 any(
1736 \\[123123e100000]
1737 );
1738}
1739
1740test "i_number_real_underflow" {
1741 any(
1742 \\[123e-10000000]
1743 );
1744}
1745
1746test "i_number_too_big_neg_int" {
1747 any(
1748 \\[-123123123123123123123123123123]
1749 );
1750}
1751
1752test "i_number_too_big_pos_int" {
1753 any(
1754 \\[100000000000000000000]
1755 );
1756}
1757
1758test "i_number_very_big_negative_int" {
1759 any(
1760 \\[-237462374673276894279832749832423479823246327846]
1761 );
1762}
1763
1764test "i_object_key_lone_2nd_surrogate" {
1765 any(
1766 \\{"\uDFAA":0}
1767 );
1768}
1769
1770test "i_string_1st_surrogate_but_2nd_missing" {
1771 any(
1772 \\["\uDADA"]
1773 );
1774}
1775
1776test "i_string_1st_valid_surrogate_2nd_invalid" {
1777 any(
1778 \\["\uD888\u1234"]
1779 );
1780}
1781
1782test "i_string_incomplete_surrogate_and_escape_valid" {
1783 any(
1784 \\["\uD800\n"]
1785 );
1786}
1787
1788test "i_string_incomplete_surrogate_pair" {
1789 any(
1790 \\["\uDd1ea"]
1791 );
1792}
1793
1794test "i_string_incomplete_surrogates_escape_valid" {
1795 any(
1796 \\["\uD800\uD800\n"]
1797 );
1798}
1799
1800test "i_string_invalid_lonely_surrogate" {
1801 any(
1802 \\["\ud800"]
1803 );
1804}
1805
1806test "i_string_invalid_surrogate" {
1807 any(
1808 \\["\ud800abc"]
1809 );
1810}
1811
1812test "i_string_invalid_utf-8" {
1813 any(
1814 \\["ÿ"]
1815 );
1816}
1817
1818test "i_string_inverted_surrogates_U+1D11E" {
1819 any(
1820 \\["\uDd1e\uD834"]
1821 );
1822}
1823
1824test "i_string_iso_latin_1" {
1825 any(
1826 \\["é"]
1827 );
1828}
1829
1830test "i_string_lone_second_surrogate" {
1831 any(
1832 \\["\uDFAA"]
1833 );
1834}
1835
1836test "i_string_lone_utf8_continuation_byte" {
1837 any(
1838 \\[""]
1839 );
1840}
1841
1842test "i_string_not_in_unicode_range" {
1843 any(
1844 \\["ô¿¿¿"]
1845 );
1846}
1847
1848test "i_string_overlong_sequence_2_bytes" {
1849 any(
1850 \\["À¯"]
1851 );
1852}
1853
1854test "i_string_overlong_sequence_6_bytes" {
1855 any(
1856 \\["üƒ¿¿¿¿"]
1857 );
1858}
1859
1860test "i_string_overlong_sequence_6_bytes_null" {
1861 any(
1862 \\["ü€€€€€"]
1863 );
1864}
1865
1866test "i_string_truncated-utf-8" {
1867 any(
1868 \\["àÿ"]
1869 );
1870}
1871
1872test "i_string_utf16BE_no_BOM" {
1873 any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d");
1874}
1875
1876test "i_string_utf16LE_no_BOM" {
1877 any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
1878}
1879
1880test "i_string_UTF-16LE_with_BOM" {
1881 any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
1882}
1883
1884test "i_string_UTF-8_invalid_sequence" {
1885 any(
1886 \\["日шú"]
1887 );
1888}
1889
1890test "i_string_UTF8_surrogate_U+D800" {
1891 any(
1892 \\["í €"]
1893 );
1894}
1895
1896test "i_structure_500_nested_arrays" {
1897 any(("[" ** 500) ++ ("]" ** 500));
1898}
1899
1900test "i_structure_UTF-8_BOM_empty_object" {
1901 any(
1902 \\{}
1903 );
1904}
std/json_test.zig deleted-1904
...@@ -1,1904 +0,0 @@
1// RFC 8529 conformance tests.
2//
3// Tests are taken from https://github.com/nst/JSONTestSuite
4// Read also http://seriot.ch/parsing_json.php for a good overview.
5
6const std = @import("std.zig");
7
8fn ok(comptime s: []const u8) void {
9 std.testing.expect(std.json.validate(s));
10}
11
12fn err(comptime s: []const u8) void {
13 std.testing.expect(!std.json.validate(s));
14}
15
16fn any(comptime s: []const u8) void {
17 std.testing.expect(true);
18}
19
20////////////////////////////////////////////////////////////////////////////////////////////////////
21//
22// Additional tests not part of test JSONTestSuite.
23
24test "json.test.y_trailing_comma_after_empty" {
25 ok(
26 \\{"1":[],"2":{},"3":"4"}
27 );
28}
29
30////////////////////////////////////////////////////////////////////////////////////////////////////
31
32test "json.test.y_array_arraysWithSpaces" {
33 ok(
34 \\[[] ]
35 );
36}
37
38test "json.test.y_array_empty" {
39 ok(
40 \\[]
41 );
42}
43
44test "json.test.y_array_empty-string" {
45 ok(
46 \\[""]
47 );
48}
49
50test "json.test.y_array_ending_with_newline" {
51 ok(
52 \\["a"]
53 );
54}
55
56test "json.test.y_array_false" {
57 ok(
58 \\[false]
59 );
60}
61
62test "json.test.y_array_heterogeneous" {
63 ok(
64 \\[null, 1, "1", {}]
65 );
66}
67
68test "json.test.y_array_null" {
69 ok(
70 \\[null]
71 );
72}
73
74test "json.test.y_array_with_1_and_newline" {
75 ok(
76 \\[1
77 \\]
78 );
79}
80
81test "json.test.y_array_with_leading_space" {
82 ok(
83 \\ [1]
84 );
85}
86
87test "json.test.y_array_with_several_null" {
88 ok(
89 \\[1,null,null,null,2]
90 );
91}
92
93test "json.test.y_array_with_trailing_space" {
94 ok("[2] ");
95}
96
97test "json.test.y_number_0e+1" {
98 ok(
99 \\[0e+1]
100 );
101}
102
103test "json.test.y_number_0e1" {
104 ok(
105 \\[0e1]
106 );
107}
108
109test "json.test.y_number_after_space" {
110 ok(
111 \\[ 4]
112 );
113}
114
115test "json.test.y_number_double_close_to_zero" {
116 ok(
117 \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]
118 );
119}
120
121test "json.test.y_number_int_with_exp" {
122 ok(
123 \\[20e1]
124 );
125}
126
127test "json.test.y_number" {
128 ok(
129 \\[123e65]
130 );
131}
132
133test "json.test.y_number_minus_zero" {
134 ok(
135 \\[-0]
136 );
137}
138
139test "json.test.y_number_negative_int" {
140 ok(
141 \\[-123]
142 );
143}
144
145test "json.test.y_number_negative_one" {
146 ok(
147 \\[-1]
148 );
149}
150
151test "json.test.y_number_negative_zero" {
152 ok(
153 \\[-0]
154 );
155}
156
157test "json.test.y_number_real_capital_e" {
158 ok(
159 \\[1E22]
160 );
161}
162
163test "json.test.y_number_real_capital_e_neg_exp" {
164 ok(
165 \\[1E-2]
166 );
167}
168
169test "json.test.y_number_real_capital_e_pos_exp" {
170 ok(
171 \\[1E+2]
172 );
173}
174
175test "json.test.y_number_real_exponent" {
176 ok(
177 \\[123e45]
178 );
179}
180
181test "json.test.y_number_real_fraction_exponent" {
182 ok(
183 \\[123.456e78]
184 );
185}
186
187test "json.test.y_number_real_neg_exp" {
188 ok(
189 \\[1e-2]
190 );
191}
192
193test "json.test.y_number_real_pos_exponent" {
194 ok(
195 \\[1e+2]
196 );
197}
198
199test "json.test.y_number_simple_int" {
200 ok(
201 \\[123]
202 );
203}
204
205test "json.test.y_number_simple_real" {
206 ok(
207 \\[123.456789]
208 );
209}
210
211test "json.test.y_object_basic" {
212 ok(
213 \\{"asd":"sdf"}
214 );
215}
216
217test "json.test.y_object_duplicated_key_and_value" {
218 ok(
219 \\{"a":"b","a":"b"}
220 );
221}
222
223test "json.test.y_object_duplicated_key" {
224 ok(
225 \\{"a":"b","a":"c"}
226 );
227}
228
229test "json.test.y_object_empty" {
230 ok(
231 \\{}
232 );
233}
234
235test "json.test.y_object_empty_key" {
236 ok(
237 \\{"":0}
238 );
239}
240
241test "json.test.y_object_escaped_null_in_key" {
242 ok(
243 \\{"foo\u0000bar": 42}
244 );
245}
246
247test "json.test.y_object_extreme_numbers" {
248 ok(
249 \\{ "min": -1.0e+28, "max": 1.0e+28 }
250 );
251}
252
253test "json.test.y_object" {
254 ok(
255 \\{"asd":"sdf", "dfg":"fgh"}
256 );
257}
258
259test "json.test.y_object_long_strings" {
260 ok(
261 \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
262 );
263}
264
265test "json.test.y_object_simple" {
266 ok(
267 \\{"a":[]}
268 );
269}
270
271test "json.test.y_object_string_unicode" {
272 ok(
273 \\{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" }
274 );
275}
276
277test "json.test.y_object_with_newlines" {
278 ok(
279 \\{
280 \\"a": "b"
281 \\}
282 );
283}
284
285test "json.test.y_string_1_2_3_bytes_UTF-8_sequences" {
286 ok(
287 \\["\u0060\u012a\u12AB"]
288 );
289}
290
291test "json.test.y_string_accepted_surrogate_pair" {
292 ok(
293 \\["\uD801\udc37"]
294 );
295}
296
297test "json.test.y_string_accepted_surrogate_pairs" {
298 ok(
299 \\["\ud83d\ude39\ud83d\udc8d"]
300 );
301}
302
303test "json.test.y_string_allowed_escapes" {
304 ok(
305 \\["\"\\\/\b\f\n\r\t"]
306 );
307}
308
309test "json.test.y_string_backslash_and_u_escaped_zero" {
310 ok(
311 \\["\\u0000"]
312 );
313}
314
315test "json.test.y_string_backslash_doublequotes" {
316 ok(
317 \\["\""]
318 );
319}
320
321test "json.test.y_string_comments" {
322 ok(
323 \\["a/*b*/c/*d//e"]
324 );
325}
326
327test "json.test.y_string_double_escape_a" {
328 ok(
329 \\["\\a"]
330 );
331}
332
333test "json.test.y_string_double_escape_n" {
334 ok(
335 \\["\\n"]
336 );
337}
338
339test "json.test.y_string_escaped_control_character" {
340 ok(
341 \\["\u0012"]
342 );
343}
344
345test "json.test.y_string_escaped_noncharacter" {
346 ok(
347 \\["\uFFFF"]
348 );
349}
350
351test "json.test.y_string_in_array" {
352 ok(
353 \\["asd"]
354 );
355}
356
357test "json.test.y_string_in_array_with_leading_space" {
358 ok(
359 \\[ "asd"]
360 );
361}
362
363test "json.test.y_string_last_surrogates_1_and_2" {
364 ok(
365 \\["\uDBFF\uDFFF"]
366 );
367}
368
369test "json.test.y_string_nbsp_uescaped" {
370 ok(
371 \\["new\u00A0line"]
372 );
373}
374
375test "json.test.y_string_nonCharacterInUTF-8_U+10FFFF" {
376 ok(
377 \\["􏿿"]
378 );
379}
380
381test "json.test.y_string_nonCharacterInUTF-8_U+FFFF" {
382 ok(
383 \\["￿"]
384 );
385}
386
387test "json.test.y_string_null_escape" {
388 ok(
389 \\["\u0000"]
390 );
391}
392
393test "json.test.y_string_one-byte-utf-8" {
394 ok(
395 \\["\u002c"]
396 );
397}
398
399test "json.test.y_string_pi" {
400 ok(
401 \\["π"]
402 );
403}
404
405test "json.test.y_string_reservedCharacterInUTF-8_U+1BFFF" {
406 ok(
407 \\["𛿿"]
408 );
409}
410
411test "json.test.y_string_simple_ascii" {
412 ok(
413 \\["asd "]
414 );
415}
416
417test "json.test.y_string_space" {
418 ok(
419 \\" "
420 );
421}
422
423test "json.test.y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" {
424 ok(
425 \\["\uD834\uDd1e"]
426 );
427}
428
429test "json.test.y_string_three-byte-utf-8" {
430 ok(
431 \\["\u0821"]
432 );
433}
434
435test "json.test.y_string_two-byte-utf-8" {
436 ok(
437 \\["\u0123"]
438 );
439}
440
441test "json.test.y_string_u+2028_line_sep" {
442 ok("[\"\xe2\x80\xa8\"]");
443}
444
445test "json.test.y_string_u+2029_par_sep" {
446 ok("[\"\xe2\x80\xa9\"]");
447}
448
449test "json.test.y_string_uescaped_newline" {
450 ok(
451 \\["new\u000Aline"]
452 );
453}
454
455test "json.test.y_string_uEscape" {
456 ok(
457 \\["\u0061\u30af\u30EA\u30b9"]
458 );
459}
460
461test "json.test.y_string_unescaped_char_delete" {
462 ok("[\"\x7f\"]");
463}
464
465test "json.test.y_string_unicode_2" {
466 ok(
467 \\["⍂㈴⍂"]
468 );
469}
470
471test "json.test.y_string_unicodeEscapedBackslash" {
472 ok(
473 \\["\u005C"]
474 );
475}
476
477test "json.test.y_string_unicode_escaped_double_quote" {
478 ok(
479 \\["\u0022"]
480 );
481}
482
483test "json.test.y_string_unicode" {
484 ok(
485 \\["\uA66D"]
486 );
487}
488
489test "json.test.y_string_unicode_U+10FFFE_nonchar" {
490 ok(
491 \\["\uDBFF\uDFFE"]
492 );
493}
494
495test "json.test.y_string_unicode_U+1FFFE_nonchar" {
496 ok(
497 \\["\uD83F\uDFFE"]
498 );
499}
500
501test "json.test.y_string_unicode_U+200B_ZERO_WIDTH_SPACE" {
502 ok(
503 \\["\u200B"]
504 );
505}
506
507test "json.test.y_string_unicode_U+2064_invisible_plus" {
508 ok(
509 \\["\u2064"]
510 );
511}
512
513test "json.test.y_string_unicode_U+FDD0_nonchar" {
514 ok(
515 \\["\uFDD0"]
516 );
517}
518
519test "json.test.y_string_unicode_U+FFFE_nonchar" {
520 ok(
521 \\["\uFFFE"]
522 );
523}
524
525test "json.test.y_string_utf8" {
526 ok(
527 \\["€𝄞"]
528 );
529}
530
531test "json.test.y_string_with_del_character" {
532 ok("[\"a\x7fa\"]");
533}
534
535test "json.test.y_structure_lonely_false" {
536 ok(
537 \\false
538 );
539}
540
541test "json.test.y_structure_lonely_int" {
542 ok(
543 \\42
544 );
545}
546
547test "json.test.y_structure_lonely_negative_real" {
548 ok(
549 \\-0.1
550 );
551}
552
553test "json.test.y_structure_lonely_null" {
554 ok(
555 \\null
556 );
557}
558
559test "json.test.y_structure_lonely_string" {
560 ok(
561 \\"asd"
562 );
563}
564
565test "json.test.y_structure_lonely_true" {
566 ok(
567 \\true
568 );
569}
570
571test "json.test.y_structure_string_empty" {
572 ok(
573 \\""
574 );
575}
576
577test "json.test.y_structure_trailing_newline" {
578 ok(
579 \\["a"]
580 );
581}
582
583test "json.test.y_structure_true_in_array" {
584 ok(
585 \\[true]
586 );
587}
588
589test "json.test.y_structure_whitespace_array" {
590 ok(" [] ");
591}
592
593////////////////////////////////////////////////////////////////////////////////////////////////////
594
595test "json.test.n_array_1_true_without_comma" {
596 err(
597 \\[1 true]
598 );
599}
600
601test "json.test.n_array_a_invalid_utf8" {
602 err(
603 \\[aå]
604 );
605}
606
607test "json.test.n_array_colon_instead_of_comma" {
608 err(
609 \\["": 1]
610 );
611}
612
613test "json.test.n_array_comma_after_close" {
614 //err(
615 // \\[""],
616 //);
617}
618
619test "json.test.n_array_comma_and_number" {
620 err(
621 \\[,1]
622 );
623}
624
625test "json.test.n_array_double_comma" {
626 err(
627 \\[1,,2]
628 );
629}
630
631test "json.test.n_array_double_extra_comma" {
632 err(
633 \\["x",,]
634 );
635}
636
637test "json.test.n_array_extra_close" {
638 err(
639 \\["x"]]
640 );
641}
642
643test "json.test.n_array_extra_comma" {
644 //err(
645 // \\["",]
646 //);
647}
648
649test "json.test.n_array_incomplete_invalid_value" {
650 err(
651 \\[x
652 );
653}
654
655test "json.test.n_array_incomplete" {
656 err(
657 \\["x"
658 );
659}
660
661test "json.test.n_array_inner_array_no_comma" {
662 err(
663 \\[3[4]]
664 );
665}
666
667test "json.test.n_array_invalid_utf8" {
668 err(
669 \\[ÿ]
670 );
671}
672
673test "json.test.n_array_items_separated_by_semicolon" {
674 err(
675 \\[1:2]
676 );
677}
678
679test "json.test.n_array_just_comma" {
680 err(
681 \\[,]
682 );
683}
684
685test "json.test.n_array_just_minus" {
686 err(
687 \\[-]
688 );
689}
690
691test "json.test.n_array_missing_value" {
692 err(
693 \\[ , ""]
694 );
695}
696
697test "json.test.n_array_newlines_unclosed" {
698 err(
699 \\["a",
700 \\4
701 \\,1,
702 );
703}
704
705test "json.test.n_array_number_and_comma" {
706 err(
707 \\[1,]
708 );
709}
710
711test "json.test.n_array_number_and_several_commas" {
712 err(
713 \\[1,,]
714 );
715}
716
717test "json.test.n_array_spaces_vertical_tab_formfeed" {
718 err("[\"\x0aa\"\\f]");
719}
720
721test "json.test.n_array_star_inside" {
722 err(
723 \\[*]
724 );
725}
726
727test "json.test.n_array_unclosed" {
728 err(
729 \\[""
730 );
731}
732
733test "json.test.n_array_unclosed_trailing_comma" {
734 err(
735 \\[1,
736 );
737}
738
739test "json.test.n_array_unclosed_with_new_lines" {
740 err(
741 \\[1,
742 \\1
743 \\,1
744 );
745}
746
747test "json.test.n_array_unclosed_with_object_inside" {
748 err(
749 \\[{}
750 );
751}
752
753test "json.test.n_incomplete_false" {
754 err(
755 \\[fals]
756 );
757}
758
759test "json.test.n_incomplete_null" {
760 err(
761 \\[nul]
762 );
763}
764
765test "json.test.n_incomplete_true" {
766 err(
767 \\[tru]
768 );
769}
770
771test "json.test.n_multidigit_number_then_00" {
772 err("123\x00");
773}
774
775test "json.test.n_number_0.1.2" {
776 err(
777 \\[0.1.2]
778 );
779}
780
781test "json.test.n_number_-01" {
782 err(
783 \\[-01]
784 );
785}
786
787test "json.test.n_number_0.3e" {
788 err(
789 \\[0.3e]
790 );
791}
792
793test "json.test.n_number_0.3e+" {
794 err(
795 \\[0.3e+]
796 );
797}
798
799test "json.test.n_number_0_capital_E" {
800 err(
801 \\[0E]
802 );
803}
804
805test "json.test.n_number_0_capital_E+" {
806 err(
807 \\[0E+]
808 );
809}
810
811test "json.test.n_number_0.e1" {
812 err(
813 \\[0.e1]
814 );
815}
816
817test "json.test.n_number_0e" {
818 err(
819 \\[0e]
820 );
821}
822
823test "json.test.n_number_0e+" {
824 err(
825 \\[0e+]
826 );
827}
828
829test "json.test.n_number_1_000" {
830 err(
831 \\[1 000.0]
832 );
833}
834
835test "json.test.n_number_1.0e-" {
836 err(
837 \\[1.0e-]
838 );
839}
840
841test "json.test.n_number_1.0e" {
842 err(
843 \\[1.0e]
844 );
845}
846
847test "json.test.n_number_1.0e+" {
848 err(
849 \\[1.0e+]
850 );
851}
852
853test "json.test.n_number_-1.0." {
854 err(
855 \\[-1.0.]
856 );
857}
858
859test "json.test.n_number_1eE2" {
860 err(
861 \\[1eE2]
862 );
863}
864
865test "json.test.n_number_.-1" {
866 err(
867 \\[.-1]
868 );
869}
870
871test "json.test.n_number_+1" {
872 err(
873 \\[+1]
874 );
875}
876
877test "json.test.n_number_.2e-3" {
878 err(
879 \\[.2e-3]
880 );
881}
882
883test "json.test.n_number_2.e-3" {
884 err(
885 \\[2.e-3]
886 );
887}
888
889test "json.test.n_number_2.e+3" {
890 err(
891 \\[2.e+3]
892 );
893}
894
895test "json.test.n_number_2.e3" {
896 err(
897 \\[2.e3]
898 );
899}
900
901test "json.test.n_number_-2." {
902 err(
903 \\[-2.]
904 );
905}
906
907test "json.test.n_number_9.e+" {
908 err(
909 \\[9.e+]
910 );
911}
912
913test "json.test.n_number_expression" {
914 err(
915 \\[1+2]
916 );
917}
918
919test "json.test.n_number_hex_1_digit" {
920 err(
921 \\[0x1]
922 );
923}
924
925test "json.test.n_number_hex_2_digits" {
926 err(
927 \\[0x42]
928 );
929}
930
931test "json.test.n_number_infinity" {
932 err(
933 \\[Infinity]
934 );
935}
936
937test "json.test.n_number_+Inf" {
938 err(
939 \\[+Inf]
940 );
941}
942
943test "json.test.n_number_Inf" {
944 err(
945 \\[Inf]
946 );
947}
948
949test "json.test.n_number_invalid+-" {
950 err(
951 \\[0e+-1]
952 );
953}
954
955test "json.test.n_number_invalid-negative-real" {
956 err(
957 \\[-123.123foo]
958 );
959}
960
961test "json.test.n_number_invalid-utf-8-in-bigger-int" {
962 err(
963 \\[123å]
964 );
965}
966
967test "json.test.n_number_invalid-utf-8-in-exponent" {
968 err(
969 \\[1e1å]
970 );
971}
972
973test "json.test.n_number_invalid-utf-8-in-int" {
974 err(
975 \\[0å]
976 );
977}
978
979test "json.test.n_number_++" {
980 err(
981 \\[++1234]
982 );
983}
984
985test "json.test.n_number_minus_infinity" {
986 err(
987 \\[-Infinity]
988 );
989}
990
991test "json.test.n_number_minus_sign_with_trailing_garbage" {
992 err(
993 \\[-foo]
994 );
995}
996
997test "json.test.n_number_minus_space_1" {
998 err(
999 \\[- 1]
1000 );
1001}
1002
1003test "json.test.n_number_-NaN" {
1004 err(
1005 \\[-NaN]
1006 );
1007}
1008
1009test "json.test.n_number_NaN" {
1010 err(
1011 \\[NaN]
1012 );
1013}
1014
1015test "json.test.n_number_neg_int_starting_with_zero" {
1016 err(
1017 \\[-012]
1018 );
1019}
1020
1021test "json.test.n_number_neg_real_without_int_part" {
1022 err(
1023 \\[-.123]
1024 );
1025}
1026
1027test "json.test.n_number_neg_with_garbage_at_end" {
1028 err(
1029 \\[-1x]
1030 );
1031}
1032
1033test "json.test.n_number_real_garbage_after_e" {
1034 err(
1035 \\[1ea]
1036 );
1037}
1038
1039test "json.test.n_number_real_with_invalid_utf8_after_e" {
1040 err(
1041 \\[1eå]
1042 );
1043}
1044
1045test "json.test.n_number_real_without_fractional_part" {
1046 err(
1047 \\[1.]
1048 );
1049}
1050
1051test "json.test.n_number_starting_with_dot" {
1052 err(
1053 \\[.123]
1054 );
1055}
1056
1057test "json.test.n_number_U+FF11_fullwidth_digit_one" {
1058 err(
1059 \\[1]
1060 );
1061}
1062
1063test "json.test.n_number_with_alpha_char" {
1064 err(
1065 \\[1.8011670033376514H-308]
1066 );
1067}
1068
1069test "json.test.n_number_with_alpha" {
1070 err(
1071 \\[1.2a-3]
1072 );
1073}
1074
1075test "json.test.n_number_with_leading_zero" {
1076 err(
1077 \\[012]
1078 );
1079}
1080
1081test "json.test.n_object_bad_value" {
1082 err(
1083 \\["x", truth]
1084 );
1085}
1086
1087test "json.test.n_object_bracket_key" {
1088 err(
1089 \\{[: "x"}
1090 );
1091}
1092
1093test "json.test.n_object_comma_instead_of_colon" {
1094 err(
1095 \\{"x", null}
1096 );
1097}
1098
1099test "json.test.n_object_double_colon" {
1100 err(
1101 \\{"x"::"b"}
1102 );
1103}
1104
1105test "json.test.n_object_emoji" {
1106 err(
1107 \\{🇨🇭}
1108 );
1109}
1110
1111test "json.test.n_object_garbage_at_end" {
1112 err(
1113 \\{"a":"a" 123}
1114 );
1115}
1116
1117test "json.test.n_object_key_with_single_quotes" {
1118 err(
1119 \\{key: 'value'}
1120 );
1121}
1122
1123test "json.test.n_object_lone_continuation_byte_in_key_and_trailing_comma" {
1124 err(
1125 \\{"¹":"0",}
1126 );
1127}
1128
1129test "json.test.n_object_missing_colon" {
1130 err(
1131 \\{"a" b}
1132 );
1133}
1134
1135test "json.test.n_object_missing_key" {
1136 err(
1137 \\{:"b"}
1138 );
1139}
1140
1141test "json.test.n_object_missing_semicolon" {
1142 err(
1143 \\{"a" "b"}
1144 );
1145}
1146
1147test "json.test.n_object_missing_value" {
1148 err(
1149 \\{"a":
1150 );
1151}
1152
1153test "json.test.n_object_no-colon" {
1154 err(
1155 \\{"a"
1156 );
1157}
1158
1159test "json.test.n_object_non_string_key_but_huge_number_instead" {
1160 err(
1161 \\{9999E9999:1}
1162 );
1163}
1164
1165test "json.test.n_object_non_string_key" {
1166 err(
1167 \\{1:1}
1168 );
1169}
1170
1171test "json.test.n_object_repeated_null_null" {
1172 err(
1173 \\{null:null,null:null}
1174 );
1175}
1176
1177test "json.test.n_object_several_trailing_commas" {
1178 err(
1179 \\{"id":0,,,,,}
1180 );
1181}
1182
1183test "json.test.n_object_single_quote" {
1184 err(
1185 \\{'a':0}
1186 );
1187}
1188
1189test "json.test.n_object_trailing_comma" {
1190 err(
1191 \\{"id":0,}
1192 );
1193}
1194
1195test "json.test.n_object_trailing_comment" {
1196 err(
1197 \\{"a":"b"}/**/
1198 );
1199}
1200
1201test "json.test.n_object_trailing_comment_open" {
1202 err(
1203 \\{"a":"b"}/**//
1204 );
1205}
1206
1207test "json.test.n_object_trailing_comment_slash_open_incomplete" {
1208 err(
1209 \\{"a":"b"}/
1210 );
1211}
1212
1213test "json.test.n_object_trailing_comment_slash_open" {
1214 err(
1215 \\{"a":"b"}//
1216 );
1217}
1218
1219test "json.test.n_object_two_commas_in_a_row" {
1220 err(
1221 \\{"a":"b",,"c":"d"}
1222 );
1223}
1224
1225test "json.test.n_object_unquoted_key" {
1226 err(
1227 \\{a: "b"}
1228 );
1229}
1230
1231test "json.test.n_object_unterminated-value" {
1232 err(
1233 \\{"a":"a
1234 );
1235}
1236
1237test "json.test.n_object_with_single_string" {
1238 err(
1239 \\{ "foo" : "bar", "a" }
1240 );
1241}
1242
1243test "json.test.n_object_with_trailing_garbage" {
1244 err(
1245 \\{"a":"b"}#
1246 );
1247}
1248
1249test "json.test.n_single_space" {
1250 err(" ");
1251}
1252
1253test "json.test.n_string_1_surrogate_then_escape" {
1254 err(
1255 \\["\uD800\"]
1256 );
1257}
1258
1259test "json.test.n_string_1_surrogate_then_escape_u1" {
1260 err(
1261 \\["\uD800\u1"]
1262 );
1263}
1264
1265test "json.test.n_string_1_surrogate_then_escape_u1x" {
1266 err(
1267 \\["\uD800\u1x"]
1268 );
1269}
1270
1271test "json.test.n_string_1_surrogate_then_escape_u" {
1272 err(
1273 \\["\uD800\u"]
1274 );
1275}
1276
1277test "json.test.n_string_accentuated_char_no_quotes" {
1278 err(
1279 \\[é]
1280 );
1281}
1282
1283test "json.test.n_string_backslash_00" {
1284 err("[\"\x00\"]");
1285}
1286
1287test "json.test.n_string_escaped_backslash_bad" {
1288 err(
1289 \\["\\\"]
1290 );
1291}
1292
1293test "json.test.n_string_escaped_ctrl_char_tab" {
1294 err("\x5b\x22\x5c\x09\x22\x5d");
1295}
1296
1297test "json.test.n_string_escaped_emoji" {
1298 err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]");
1299}
1300
1301test "json.test.n_string_escape_x" {
1302 err(
1303 \\["\x00"]
1304 );
1305}
1306
1307test "json.test.n_string_incomplete_escaped_character" {
1308 err(
1309 \\["\u00A"]
1310 );
1311}
1312
1313test "json.test.n_string_incomplete_escape" {
1314 err(
1315 \\["\"]
1316 );
1317}
1318
1319test "json.test.n_string_incomplete_surrogate_escape_invalid" {
1320 err(
1321 \\["\uD800\uD800\x"]
1322 );
1323}
1324
1325test "json.test.n_string_incomplete_surrogate" {
1326 err(
1327 \\["\uD834\uDd"]
1328 );
1329}
1330
1331test "json.test.n_string_invalid_backslash_esc" {
1332 err(
1333 \\["\a"]
1334 );
1335}
1336
1337test "json.test.n_string_invalid_unicode_escape" {
1338 err(
1339 \\["\uqqqq"]
1340 );
1341}
1342
1343test "json.test.n_string_invalid_utf8_after_escape" {
1344 err("[\"\\\x75\xc3\xa5\"]");
1345}
1346
1347test "json.test.n_string_invalid-utf-8-in-escape" {
1348 err(
1349 \\["\uå"]
1350 );
1351}
1352
1353test "json.test.n_string_leading_uescaped_thinspace" {
1354 err(
1355 \\[\u0020"asd"]
1356 );
1357}
1358
1359test "json.test.n_string_no_quotes_with_bad_escape" {
1360 err(
1361 \\[\n]
1362 );
1363}
1364
1365test "json.test.n_string_single_doublequote" {
1366 err(
1367 \\"
1368 );
1369}
1370
1371test "json.test.n_string_single_quote" {
1372 err(
1373 \\['single quote']
1374 );
1375}
1376
1377test "json.test.n_string_single_string_no_double_quotes" {
1378 err(
1379 \\abc
1380 );
1381}
1382
1383test "json.test.n_string_start_escape_unclosed" {
1384 err(
1385 \\["\
1386 );
1387}
1388
1389test "json.test.n_string_unescaped_crtl_char" {
1390 err("[\"a\x00a\"]");
1391}
1392
1393test "json.test.n_string_unescaped_newline" {
1394 err(
1395 \\["new
1396 \\line"]
1397 );
1398}
1399
1400test "json.test.n_string_unescaped_tab" {
1401 err("[\"\t\"]");
1402}
1403
1404test "json.test.n_string_unicode_CapitalU" {
1405 err(
1406 \\"\UA66D"
1407 );
1408}
1409
1410test "json.test.n_string_with_trailing_garbage" {
1411 err(
1412 \\""x
1413 );
1414}
1415
1416test "json.test.n_structure_100000_opening_arrays" {
1417 err("[" ** 100000);
1418}
1419
1420test "json.test.n_structure_angle_bracket_." {
1421 err(
1422 \\<.>
1423 );
1424}
1425
1426test "json.test.n_structure_angle_bracket_null" {
1427 err(
1428 \\[<null>]
1429 );
1430}
1431
1432test "json.test.n_structure_array_trailing_garbage" {
1433 err(
1434 \\[1]x
1435 );
1436}
1437
1438test "json.test.n_structure_array_with_extra_array_close" {
1439 err(
1440 \\[1]]
1441 );
1442}
1443
1444test "json.test.n_structure_array_with_unclosed_string" {
1445 err(
1446 \\["asd]
1447 );
1448}
1449
1450test "json.test.n_structure_ascii-unicode-identifier" {
1451 err(
1452 \\aå
1453 );
1454}
1455
1456test "json.test.n_structure_capitalized_True" {
1457 err(
1458 \\[True]
1459 );
1460}
1461
1462test "json.test.n_structure_close_unopened_array" {
1463 err(
1464 \\1]
1465 );
1466}
1467
1468test "json.test.n_structure_comma_instead_of_closing_brace" {
1469 err(
1470 \\{"x": true,
1471 );
1472}
1473
1474test "json.test.n_structure_double_array" {
1475 err(
1476 \\[][]
1477 );
1478}
1479
1480test "json.test.n_structure_end_array" {
1481 err(
1482 \\]
1483 );
1484}
1485
1486test "json.test.n_structure_incomplete_UTF8_BOM" {
1487 err(
1488 \\ï»{}
1489 );
1490}
1491
1492test "json.test.n_structure_lone-invalid-utf-8" {
1493 err(
1494 \\å
1495 );
1496}
1497
1498test "json.test.n_structure_lone-open-bracket" {
1499 err(
1500 \\[
1501 );
1502}
1503
1504test "json.test.n_structure_no_data" {
1505 err(
1506 \\
1507 );
1508}
1509
1510test "json.test.n_structure_null-byte-outside-string" {
1511 err("[\x00]");
1512}
1513
1514test "json.test.n_structure_number_with_trailing_garbage" {
1515 err(
1516 \\2@
1517 );
1518}
1519
1520test "json.test.n_structure_object_followed_by_closing_object" {
1521 err(
1522 \\{}}
1523 );
1524}
1525
1526test "json.test.n_structure_object_unclosed_no_value" {
1527 err(
1528 \\{"":
1529 );
1530}
1531
1532test "json.test.n_structure_object_with_comment" {
1533 err(
1534 \\{"a":/*comment*/"b"}
1535 );
1536}
1537
1538test "json.test.n_structure_object_with_trailing_garbage" {
1539 err(
1540 \\{"a": true} "x"
1541 );
1542}
1543
1544test "json.test.n_structure_open_array_apostrophe" {
1545 err(
1546 \\['
1547 );
1548}
1549
1550test "json.test.n_structure_open_array_comma" {
1551 err(
1552 \\[,
1553 );
1554}
1555
1556test "json.test.n_structure_open_array_object" {
1557 err("[{\"\":" ** 50000);
1558}
1559
1560test "json.test.n_structure_open_array_open_object" {
1561 err(
1562 \\[{
1563 );
1564}
1565
1566test "json.test.n_structure_open_array_open_string" {
1567 err(
1568 \\["a
1569 );
1570}
1571
1572test "json.test.n_structure_open_array_string" {
1573 err(
1574 \\["a"
1575 );
1576}
1577
1578test "json.test.n_structure_open_object_close_array" {
1579 err(
1580 \\{]
1581 );
1582}
1583
1584test "json.test.n_structure_open_object_comma" {
1585 err(
1586 \\{,
1587 );
1588}
1589
1590test "json.test.n_structure_open_object" {
1591 err(
1592 \\{
1593 );
1594}
1595
1596test "json.test.n_structure_open_object_open_array" {
1597 err(
1598 \\{[
1599 );
1600}
1601
1602test "json.test.n_structure_open_object_open_string" {
1603 err(
1604 \\{"a
1605 );
1606}
1607
1608test "json.test.n_structure_open_object_string_with_apostrophes" {
1609 err(
1610 \\{'a'
1611 );
1612}
1613
1614test "json.test.n_structure_open_open" {
1615 err(
1616 \\["\{["\{["\{["\{
1617 );
1618}
1619
1620test "json.test.n_structure_single_eacute" {
1621 err(
1622 \\é
1623 );
1624}
1625
1626test "json.test.n_structure_single_star" {
1627 err(
1628 \\*
1629 );
1630}
1631
1632test "json.test.n_structure_trailing_#" {
1633 err(
1634 \\{"a":"b"}#{}
1635 );
1636}
1637
1638test "json.test.n_structure_U+2060_word_joined" {
1639 err(
1640 \\[⁠]
1641 );
1642}
1643
1644test "json.test.n_structure_uescaped_LF_before_string" {
1645 err(
1646 \\[\u000A""]
1647 );
1648}
1649
1650test "json.test.n_structure_unclosed_array" {
1651 err(
1652 \\[1
1653 );
1654}
1655
1656test "json.test.n_structure_unclosed_array_partial_null" {
1657 err(
1658 \\[ false, nul
1659 );
1660}
1661
1662test "json.test.n_structure_unclosed_array_unfinished_false" {
1663 err(
1664 \\[ true, fals
1665 );
1666}
1667
1668test "json.test.n_structure_unclosed_array_unfinished_true" {
1669 err(
1670 \\[ false, tru
1671 );
1672}
1673
1674test "json.test.n_structure_unclosed_object" {
1675 err(
1676 \\{"asd":"asd"
1677 );
1678}
1679
1680test "json.test.n_structure_unicode-identifier" {
1681 err(
1682 \\Ã¥
1683 );
1684}
1685
1686test "json.test.n_structure_UTF8_BOM_no_data" {
1687 err(
1688 \\
1689 );
1690}
1691
1692test "json.test.n_structure_whitespace_formfeed" {
1693 err("[\x0c]");
1694}
1695
1696test "json.test.n_structure_whitespace_U+2060_word_joiner" {
1697 err(
1698 \\[⁠]
1699 );
1700}
1701
1702////////////////////////////////////////////////////////////////////////////////////////////////////
1703
1704test "json.test.i_number_double_huge_neg_exp" {
1705 any(
1706 \\[123.456e-789]
1707 );
1708}
1709
1710test "json.test.i_number_huge_exp" {
1711 any(
1712 \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]
1713 );
1714}
1715
1716test "json.test.i_number_neg_int_huge_exp" {
1717 any(
1718 \\[-1e+9999]
1719 );
1720}
1721
1722test "json.test.i_number_pos_double_huge_exp" {
1723 any(
1724 \\[1.5e+9999]
1725 );
1726}
1727
1728test "json.test.i_number_real_neg_overflow" {
1729 any(
1730 \\[-123123e100000]
1731 );
1732}
1733
1734test "json.test.i_number_real_pos_overflow" {
1735 any(
1736 \\[123123e100000]
1737 );
1738}
1739
1740test "json.test.i_number_real_underflow" {
1741 any(
1742 \\[123e-10000000]
1743 );
1744}
1745
1746test "json.test.i_number_too_big_neg_int" {
1747 any(
1748 \\[-123123123123123123123123123123]
1749 );
1750}
1751
1752test "json.test.i_number_too_big_pos_int" {
1753 any(
1754 \\[100000000000000000000]
1755 );
1756}
1757
1758test "json.test.i_number_very_big_negative_int" {
1759 any(
1760 \\[-237462374673276894279832749832423479823246327846]
1761 );
1762}
1763
1764test "json.test.i_object_key_lone_2nd_surrogate" {
1765 any(
1766 \\{"\uDFAA":0}
1767 );
1768}
1769
1770test "json.test.i_string_1st_surrogate_but_2nd_missing" {
1771 any(
1772 \\["\uDADA"]
1773 );
1774}
1775
1776test "json.test.i_string_1st_valid_surrogate_2nd_invalid" {
1777 any(
1778 \\["\uD888\u1234"]
1779 );
1780}
1781
1782test "json.test.i_string_incomplete_surrogate_and_escape_valid" {
1783 any(
1784 \\["\uD800\n"]
1785 );
1786}
1787
1788test "json.test.i_string_incomplete_surrogate_pair" {
1789 any(
1790 \\["\uDd1ea"]
1791 );
1792}
1793
1794test "json.test.i_string_incomplete_surrogates_escape_valid" {
1795 any(
1796 \\["\uD800\uD800\n"]
1797 );
1798}
1799
1800test "json.test.i_string_invalid_lonely_surrogate" {
1801 any(
1802 \\["\ud800"]
1803 );
1804}
1805
1806test "json.test.i_string_invalid_surrogate" {
1807 any(
1808 \\["\ud800abc"]
1809 );
1810}
1811
1812test "json.test.i_string_invalid_utf-8" {
1813 any(
1814 \\["ÿ"]
1815 );
1816}
1817
1818test "json.test.i_string_inverted_surrogates_U+1D11E" {
1819 any(
1820 \\["\uDd1e\uD834"]
1821 );
1822}
1823
1824test "json.test.i_string_iso_latin_1" {
1825 any(
1826 \\["é"]
1827 );
1828}
1829
1830test "json.test.i_string_lone_second_surrogate" {
1831 any(
1832 \\["\uDFAA"]
1833 );
1834}
1835
1836test "json.test.i_string_lone_utf8_continuation_byte" {
1837 any(
1838 \\[""]
1839 );
1840}
1841
1842test "json.test.i_string_not_in_unicode_range" {
1843 any(
1844 \\["ô¿¿¿"]
1845 );
1846}
1847
1848test "json.test.i_string_overlong_sequence_2_bytes" {
1849 any(
1850 \\["À¯"]
1851 );
1852}
1853
1854test "json.test.i_string_overlong_sequence_6_bytes" {
1855 any(
1856 \\["üƒ¿¿¿¿"]
1857 );
1858}
1859
1860test "json.test.i_string_overlong_sequence_6_bytes_null" {
1861 any(
1862 \\["ü€€€€€"]
1863 );
1864}
1865
1866test "json.test.i_string_truncated-utf-8" {
1867 any(
1868 \\["àÿ"]
1869 );
1870}
1871
1872test "json.test.i_string_utf16BE_no_BOM" {
1873 any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d");
1874}
1875
1876test "json.test.i_string_utf16LE_no_BOM" {
1877 any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
1878}
1879
1880test "json.test.i_string_UTF-16LE_with_BOM" {
1881 any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
1882}
1883
1884test "json.test.i_string_UTF-8_invalid_sequence" {
1885 any(
1886 \\["日шú"]
1887 );
1888}
1889
1890test "json.test.i_string_UTF8_surrogate_U+D800" {
1891 any(
1892 \\["í €"]
1893 );
1894}
1895
1896test "json.test.i_structure_500_nested_arrays" {
1897 any(("[" ** 500) ++ ("]" ** 500));
1898}
1899
1900test "json.test.i_structure_UTF-8_BOM_empty_object" {
1901 any(
1902 \\{}
1903 );
1904}
std/math/acos.zig+8-2
...@@ -1,11 +1,17 @@...@@ -1,11 +1,17 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - acos(x) = nan if x < -1 or x > 14// https://git.musl-libc.org/cgit/musl/tree/src/math/acosf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/math/acos.c
46
5const std = @import("../std.zig");7const std = @import("../std.zig");
6const math = std.math;8const math = std.math;
7const expect = std.testing.expect;9const expect = std.testing.expect;
810
11/// Returns the arc-cosine of x.
12///
13/// Special cases:
14/// - acos(x) = nan if x < -1 or x > 1
9pub fn acos(x: var) @typeOf(x) {15pub fn acos(x: var) @typeOf(x) {
10 const T = @typeOf(x);16 const T = @typeOf(x);
11 return switch (T) {17 return switch (T) {
std/math/acosh.zig+9-3
...@@ -1,13 +1,19 @@...@@ -1,13 +1,19 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - acosh(x) = snan if x < 14// https://git.musl-libc.org/cgit/musl/tree/src/math/acoshf.c
4// - acosh(nan) = nan5// https://git.musl-libc.org/cgit/musl/tree/src/math/acosh.c
56
6const builtin = @import("builtin");7const builtin = @import("builtin");
7const std = @import("../std.zig");8const std = @import("../std.zig");
8const math = std.math;9const math = std.math;
9const expect = std.testing.expect;10const expect = std.testing.expect;
1011
12/// Returns the hyperbolic arc-cosine of x.
13///
14/// Special cases:
15/// - acosh(x) = snan if x < 1
16/// - acosh(nan) = nan
11pub fn acosh(x: var) @typeOf(x) {17pub fn acosh(x: var) @typeOf(x) {
12 const T = @typeOf(x);18 const T = @typeOf(x);
13 return switch (T) {19 return switch (T) {
std/math/asin.zig+9-3
...@@ -1,12 +1,18 @@...@@ -1,12 +1,18 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - asin(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/asinf.c
4// - asin(x) = nan if x < -1 or x > 15// https://git.musl-libc.org/cgit/musl/tree/src/math/asin.c
56
6const std = @import("../std.zig");7const std = @import("../std.zig");
7const math = std.math;8const math = std.math;
8const expect = std.testing.expect;9const expect = std.testing.expect;
910
11/// Returns the arc-sin of x.
12///
13/// Special Cases:
14/// - asin(+-0) = +-0
15/// - asin(x) = nan if x < -1 or x > 1
10pub fn asin(x: var) @typeOf(x) {16pub fn asin(x: var) @typeOf(x) {
11 const T = @typeOf(x);17 const T = @typeOf(x);
12 return switch (T) {18 return switch (T) {
std/math/asinh.zig+10-4
...@@ -1,14 +1,20 @@...@@ -1,14 +1,20 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - asinh(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/asinhf.c
4// - asinh(+-inf) = +-inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/asinh.c
5// - asinh(nan) = nan
66
7const std = @import("../std.zig");7const std = @import("../std.zig");
8const math = std.math;8const math = std.math;
9const expect = std.testing.expect;9const expect = std.testing.expect;
10const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
1111
12/// Returns the hyperbolic arc-sin of x.
13///
14/// Special Cases:
15/// - asinh(+-0) = +-0
16/// - asinh(+-inf) = +-inf
17/// - asinh(nan) = nan
12pub fn asinh(x: var) @typeOf(x) {18pub fn asinh(x: var) @typeOf(x) {
13 const T = @typeOf(x);19 const T = @typeOf(x);
14 return switch (T) {20 return switch (T) {
std/math/atan.zig+9-3
...@@ -1,12 +1,18 @@...@@ -1,12 +1,18 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - atan(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/atanf.c
4// - atan(+-inf) = +-pi/25// https://git.musl-libc.org/cgit/musl/tree/src/math/atan.c
56
6const std = @import("../std.zig");7const std = @import("../std.zig");
7const math = std.math;8const math = std.math;
8const expect = std.testing.expect;9const expect = std.testing.expect;
910
11/// Returns the arc-tangent of x.
12///
13/// Special Cases:
14/// - atan(+-0) = +-0
15/// - atan(+-inf) = +-pi/2
10pub fn atan(x: var) @typeOf(x) {16pub fn atan(x: var) @typeOf(x) {
11 const T = @typeOf(x);17 const T = @typeOf(x);
12 return switch (T) {18 return switch (T) {
std/math/atan2.zig+24-18
...@@ -1,27 +1,33 @@...@@ -1,27 +1,33 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// atan2(y, nan) = nan4// https://git.musl-libc.org/cgit/musl/tree/src/math/atan2f.c
4// atan2(nan, x) = nan5// https://git.musl-libc.org/cgit/musl/tree/src/math/atan2.c
5// atan2(+0, x>=0) = +0
6// atan2(-0, x>=0) = -0
7// atan2(+0, x<=-0) = +pi
8// atan2(-0, x<=-0) = -pi
9// atan2(y>0, 0) = +pi/2
10// atan2(y<0, 0) = -pi/2
11// atan2(+inf, +inf) = +pi/4
12// atan2(-inf, +inf) = -pi/4
13// atan2(+inf, -inf) = 3pi/4
14// atan2(-inf, -inf) = -3pi/4
15// atan2(y, +inf) = 0
16// atan2(y>0, -inf) = +pi
17// atan2(y<0, -inf) = -pi
18// atan2(+inf, x) = +pi/2
19// atan2(-inf, x) = -pi/2
206
21const std = @import("../std.zig");7const std = @import("../std.zig");
22const math = std.math;8const math = std.math;
23const expect = std.testing.expect;9const expect = std.testing.expect;
2410
11/// Returns the arc-tangent of y/x.
12///
13/// Special Cases:
14/// - atan2(y, nan) = nan
15/// - atan2(nan, x) = nan
16/// - atan2(+0, x>=0) = +0
17/// - atan2(-0, x>=0) = -0
18/// - atan2(+0, x<=-0) = +pi
19/// - atan2(-0, x<=-0) = -pi
20/// - atan2(y>0, 0) = +pi/2
21/// - atan2(y<0, 0) = -pi/2
22/// - atan2(+inf, +inf) = +pi/4
23/// - atan2(-inf, +inf) = -pi/4
24/// - atan2(+inf, -inf) = 3pi/4
25/// - atan2(-inf, -inf) = -3pi/4
26/// - atan2(y, +inf) = 0
27/// - atan2(y>0, -inf) = +pi
28/// - atan2(y<0, -inf) = -pi
29/// - atan2(+inf, x) = +pi/2
30/// - atan2(-inf, x) = -pi/2
25pub fn atan2(comptime T: type, y: T, x: T) T {31pub fn atan2(comptime T: type, y: T, x: T) T {
26 return switch (T) {32 return switch (T) {
27 f32 => atan2_32(y, x),33 f32 => atan2_32(y, x),
std/math/atanh.zig+10-4
...@@ -1,14 +1,20 @@...@@ -1,14 +1,20 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - atanh(+-1) = +-inf with signal4// https://git.musl-libc.org/cgit/musl/tree/src/math/atanhf.c
4// - atanh(x) = nan if |x| > 1 with signal5// https://git.musl-libc.org/cgit/musl/tree/src/math/atanh.c
5// - atanh(nan) = nan
66
7const std = @import("../std.zig");7const std = @import("../std.zig");
8const math = std.math;8const math = std.math;
9const expect = std.testing.expect;9const expect = std.testing.expect;
10const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
1111
12/// Returns the hyperbolic arc-tangent of x.
13///
14/// Special Cases:
15/// - atanh(+-1) = +-inf with signal
16/// - atanh(x) = nan if |x| > 1 with signal
17/// - atanh(nan) = nan
12pub fn atanh(x: var) @typeOf(x) {18pub fn atanh(x: var) @typeOf(x) {
13 const T = @typeOf(x);19 const T = @typeOf(x);
14 return switch (T) {20 return switch (T) {
std/math/big.zig+2
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1pub use @import("big/int.zig");1pub use @import("big/int.zig");
2pub use @import("big/rational.zig");
23
3test "math.big" {4test "math.big" {
4 _ = @import("big/int.zig");5 _ = @import("big/int.zig");
6 _ = @import("big/rational.zig");
5}7}
std/math/big/int.zig+504-282
...@@ -21,78 +21,160 @@ comptime {...@@ -21,78 +21,160 @@ comptime {
21 debug.assert(Limb.is_signed == false);21 debug.assert(Limb.is_signed == false);
22}22}
2323
24/// An arbitrary-precision big integer.
25///
26/// Memory is allocated by an Int as needed to ensure operations never overflow. The range of an
27/// Int is bounded only by available memory.
24pub const Int = struct {28pub const Int = struct {
25 allocator: *Allocator,29 const sign_bit: usize = 1 << (usize.bit_count - 1);
26 positive: bool,30
27 // - little-endian ordered31 /// Default number of limbs to allocate on creation of an Int.
28 // - len >= 1 always32 pub const default_capacity = 4;
29 // - zero value -> len == 1 with limbs[0] == 033
34 /// Allocator used by the Int when requesting memory.
35 allocator: ?*Allocator,
36
37 /// Raw digits. These are:
38 ///
39 /// * Little-endian ordered
40 /// * limbs.len >= 1
41 /// * Zero is represent as Int.len() == 1 with limbs[0] == 0.
42 ///
43 /// Accessing limbs directly should be avoided.
30 limbs: []Limb,44 limbs: []Limb,
31 len: usize,
3245
33 const default_capacity = 4;46 /// High bit is the sign bit. If set, Int is negative, else Int is positive.
47 /// The remaining bits represent the number of limbs used by Int.
48 metadata: usize,
3449
50 /// Creates a new Int. default_capacity limbs will be allocated immediately.
51 /// Int will be zeroed.
35 pub fn init(allocator: *Allocator) !Int {52 pub fn init(allocator: *Allocator) !Int {
36 return try Int.initCapacity(allocator, default_capacity);53 return try Int.initCapacity(allocator, default_capacity);
37 }54 }
3855
56 /// Creates a new Int. Int will be set to `value`.
57 ///
58 /// This is identical to an `init`, followed by a `set`.
39 pub fn initSet(allocator: *Allocator, value: var) !Int {59 pub fn initSet(allocator: *Allocator, value: var) !Int {
40 var s = try Int.init(allocator);60 var s = try Int.init(allocator);
41 try s.set(value);61 try s.set(value);
42 return s;62 return s;
43 }63 }
4464
65 /// Creates a new Int with a specific capacity. If capacity < default_capacity then the
66 /// default capacity will be used instead.
45 pub fn initCapacity(allocator: *Allocator, capacity: usize) !Int {67 pub fn initCapacity(allocator: *Allocator, capacity: usize) !Int {
46 return Int{68 return Int{
47 .allocator = allocator,69 .allocator = allocator,
48 .positive = true,70 .metadata = 1,
49 .limbs = block: {71 .limbs = block: {
50 var limbs = try allocator.alloc(Limb, math.max(default_capacity, capacity));72 var limbs = try allocator.alloc(Limb, math.max(default_capacity, capacity));
51 limbs[0] = 0;73 limbs[0] = 0;
52 break :block limbs;74 break :block limbs;
53 },75 },
54 .len = 1,
55 };76 };
56 }77 }
5778
79 /// Returns the number of limbs currently in use.
80 pub fn len(self: Int) usize {
81 return self.metadata & ~sign_bit;
82 }
83
84 /// Returns whether an Int is positive.
85 pub fn isPositive(self: Int) bool {
86 return self.metadata & sign_bit == 0;
87 }
88
89 /// Sets the sign of an Int.
90 pub fn setSign(self: *Int, positive: bool) void {
91 if (positive) {
92 self.metadata &= ~sign_bit;
93 } else {
94 self.metadata |= sign_bit;
95 }
96 }
97
98 /// Sets the length of an Int.
99 ///
100 /// If setLen is used, then the Int must be normalized to suit.
101 pub fn setLen(self: *Int, new_len: usize) void {
102 self.metadata &= sign_bit;
103 self.metadata |= new_len;
104 }
105
106 /// Returns an Int backed by a fixed set of limb values.
107 /// This is read-only and cannot be used as a result argument. If the Int tries to allocate
108 /// memory a runtime panic will occur.
109 pub fn initFixed(limbs: []const Limb) Int {
110 var self = Int{
111 .allocator = null,
112 .metadata = limbs.len,
113 // Cast away the const, invalid use to pass as a pointer argument.
114 .limbs = @intToPtr([*]Limb, @ptrToInt(limbs.ptr))[0..limbs.len],
115 };
116
117 self.normalize(limbs.len);
118 return self;
119 }
120
121 /// Ensures an Int has enough space allocated for capacity limbs. If the Int does not have
122 /// sufficient capacity, the exact amount will be allocated. This occurs even if the requested
123 /// capacity is only greater than the current capacity by one limb.
58 pub fn ensureCapacity(self: *Int, capacity: usize) !void {124 pub fn ensureCapacity(self: *Int, capacity: usize) !void {
125 self.assertWritable();
59 if (capacity <= self.limbs.len) {126 if (capacity <= self.limbs.len) {
60 return;127 return;
61 }128 }
62129
63 self.limbs = try self.allocator.realloc(self.limbs, capacity);130 self.limbs = try self.allocator.?.realloc(self.limbs, capacity);
64 }131 }
65132
133 fn assertWritable(self: Int) void {
134 if (self.allocator == null) {
135 @panic("provided Int value is read-only but must be writable");
136 }
137 }
138
139 /// Frees all memory associated with an Int.
66 pub fn deinit(self: *Int) void {140 pub fn deinit(self: *Int) void {
67 self.allocator.free(self.limbs);141 self.assertWritable();
142 self.allocator.?.free(self.limbs);
68 self.* = undefined;143 self.* = undefined;
69 }144 }
70145
146 /// Clones an Int and returns a new Int with the same value. The new Int is a deep copy and
147 /// can be modified separately from the original.
71 pub fn clone(other: Int) !Int {148 pub fn clone(other: Int) !Int {
149 other.assertWritable();
72 return Int{150 return Int{
73 .allocator = other.allocator,151 .allocator = other.allocator,
74 .positive = other.positive,152 .metadata = other.metadata,
75 .limbs = block: {153 .limbs = block: {
76 var limbs = try other.allocator.alloc(Limb, other.len);154 var limbs = try other.allocator.?.alloc(Limb, other.len());
77 mem.copy(Limb, limbs[0..], other.limbs[0..other.len]);155 mem.copy(Limb, limbs[0..], other.limbs[0..other.len()]);
78 break :block limbs;156 break :block limbs;
79 },157 },
80 .len = other.len,
81 };158 };
82 }159 }
83160
161 /// Copies the value of an Int to an existing Int so that they both have the same value.
162 /// Extra memory will be allocated if the receiver does not have enough capacity.
84 pub fn copy(self: *Int, other: Int) !void {163 pub fn copy(self: *Int, other: Int) !void {
85 if (self == &other) {164 self.assertWritable();
165 if (self.limbs.ptr == other.limbs.ptr) {
86 return;166 return;
87 }167 }
88168
89 self.positive = other.positive;169 try self.ensureCapacity(other.len());
90 try self.ensureCapacity(other.len);170 mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len()]);
91 mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len]);171 self.metadata = other.metadata;
92 self.len = other.len;
93 }172 }
94173
174 /// Efficiently swap an Int with another. This swaps the limb pointers and a full copy is not
175 /// performed. The address of the limbs field will not be the same after this function.
95 pub fn swap(self: *Int, other: *Int) void {176 pub fn swap(self: *Int, other: *Int) void {
177 self.assertWritable();
96 mem.swap(Int, self, other);178 mem.swap(Int, self, other);
97 }179 }
98180
...@@ -103,45 +185,49 @@ pub const Int = struct {...@@ -103,45 +185,49 @@ pub const Int = struct {
103 debug.warn("\n");185 debug.warn("\n");
104 }186 }
105187
106 pub fn negate(r: *Int) void {188 /// Negate the sign of an Int.
107 r.positive = !r.positive;189 pub fn negate(self: *Int) void {
190 self.metadata ^= sign_bit;
108 }191 }
109192
110 pub fn abs(r: *Int) void {193 /// Make an Int positive.
111 r.positive = true;194 pub fn abs(self: *Int) void {
195 self.metadata &= ~sign_bit;
112 }196 }
113197
114 pub fn isOdd(r: Int) bool {198 /// Returns true if an Int is odd.
115 return r.limbs[0] & 1 != 0;199 pub fn isOdd(self: Int) bool {
200 return self.limbs[0] & 1 != 0;
116 }201 }
117202
118 pub fn isEven(r: Int) bool {203 /// Returns true if an Int is even.
119 return !r.isOdd();204 pub fn isEven(self: Int) bool {
205 return !self.isOdd();
120 }206 }
121207
122 // Returns the number of bits required to represent the absolute value of self.208 /// Returns the number of bits required to represent the absolute value an Int.
123 fn bitCountAbs(self: Int) usize {209 fn bitCountAbs(self: Int) usize {
124 return (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1]));210 return (self.len() - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len() - 1]));
125 }211 }
126212
127 // Returns the number of bits required to represent the integer in twos-complement form.213 /// Returns the number of bits required to represent the integer in twos-complement form.
128 //214 ///
129 // If the integer is negative the value returned is the number of bits needed by a signed215 /// If the integer is negative the value returned is the number of bits needed by a signed
130 // integer to represent the value. If positive the value is the number of bits for an216 /// integer to represent the value. If positive the value is the number of bits for an
131 // unsigned integer. Any unsigned integer will fit in the signed integer with bitcount217 /// unsigned integer. Any unsigned integer will fit in the signed integer with bitcount
132 // one greater than the returned value.218 /// one greater than the returned value.
133 //219 ///
134 // e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7.220 /// e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7.
135 fn bitCountTwosComp(self: Int) usize {221 fn bitCountTwosComp(self: Int) usize {
136 var bits = self.bitCountAbs();222 var bits = self.bitCountAbs();
137223
138 // If the entire value has only one bit set (e.g. 0b100000000) then the negation in twos224 // If the entire value has only one bit set (e.g. 0b100000000) then the negation in twos
139 // complement requires one less bit.225 // complement requires one less bit.
140 if (!self.positive) block: {226 if (!self.isPositive()) block: {
141 bits += 1;227 bits += 1;
142228
143 if (@popCount(self.limbs[self.len - 1]) == 1) {229 if (@popCount(self.limbs[self.len() - 1]) == 1) {
144 for (self.limbs[0 .. self.len - 1]) |limb| {230 for (self.limbs[0 .. self.len() - 1]) |limb| {
145 if (@popCount(limb) != 0) {231 if (@popCount(limb) != 0) {
146 break :block;232 break :block;
147 }233 }
...@@ -154,31 +240,34 @@ pub const Int = struct {...@@ -154,31 +240,34 @@ pub const Int = struct {
154 return bits;240 return bits;
155 }241 }
156242
157 pub fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool {243 fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool {
158 if (self.eqZero()) {244 if (self.eqZero()) {
159 return true;245 return true;
160 }246 }
161 if (!is_signed and !self.positive) {247 if (!is_signed and !self.isPositive()) {
162 return false;248 return false;
163 }249 }
164250
165 const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and is_signed);251 const req_bits = self.bitCountTwosComp() + @boolToInt(self.isPositive() and is_signed);
166 return bit_count >= req_bits;252 return bit_count >= req_bits;
167 }253 }
168254
255 /// Returns whether self can fit into an integer of the requested type.
169 pub fn fits(self: Int, comptime T: type) bool {256 pub fn fits(self: Int, comptime T: type) bool {
170 return self.fitsInTwosComp(T.is_signed, T.bit_count);257 return self.fitsInTwosComp(T.is_signed, T.bit_count);
171 }258 }
172259
173 // Returns the approximate size of the integer in the given base. Negative values accommodate for260 /// Returns the approximate size of the integer in the given base. Negative values accommodate for
174 // the minus sign. This is used for determining the number of characters needed to print the261 /// the minus sign. This is used for determining the number of characters needed to print the
175 // value. It is inexact and will exceed the given value by 1-2 digits.262 /// value. It is inexact and may exceed the given value by ~1-2 bytes.
176 pub fn sizeInBase(self: Int, base: usize) usize {263 pub fn sizeInBase(self: Int, base: usize) usize {
177 const bit_count = usize(@boolToInt(!self.positive)) + self.bitCountAbs();264 const bit_count = usize(@boolToInt(!self.isPositive())) + self.bitCountAbs();
178 return (bit_count / math.log2(base)) + 1;265 return (bit_count / math.log2(base)) + 1;
179 }266 }
180267
268 /// Sets an Int to value. Value must be an primitive integer type.
181 pub fn set(self: *Int, value: var) Allocator.Error!void {269 pub fn set(self: *Int, value: var) Allocator.Error!void {
270 self.assertWritable();
182 const T = @typeOf(value);271 const T = @typeOf(value);
183272
184 switch (@typeInfo(T)) {273 switch (@typeInfo(T)) {
...@@ -186,19 +275,19 @@ pub const Int = struct {...@@ -186,19 +275,19 @@ pub const Int = struct {
186 const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T;275 const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T;
187276
188 try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb));277 try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb));
189 self.positive = value >= 0;278 self.metadata = 0;
190 self.len = 0;279 self.setSign(value >= 0);
191280
192 var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value);281 var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value);
193282
194 if (info.bits <= Limb.bit_count) {283 if (info.bits <= Limb.bit_count) {
195 self.limbs[0] = Limb(w_value);284 self.limbs[0] = Limb(w_value);
196 self.len = 1;285 self.metadata += 1;
197 } else {286 } else {
198 var i: usize = 0;287 var i: usize = 0;
199 while (w_value != 0) : (i += 1) {288 while (w_value != 0) : (i += 1) {
200 self.limbs[i] = @truncate(Limb, w_value);289 self.limbs[i] = @truncate(Limb, w_value);
201 self.len += 1;290 self.metadata += 1;
202291
203 // TODO: shift == 64 at compile-time fails. Fails on u128 limbs.292 // TODO: shift == 64 at compile-time fails. Fails on u128 limbs.
204 w_value >>= Limb.bit_count / 2;293 w_value >>= Limb.bit_count / 2;
...@@ -212,8 +301,8 @@ pub const Int = struct {...@@ -212,8 +301,8 @@ pub const Int = struct {
212 const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1;301 const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1;
213 try self.ensureCapacity(req_limbs);302 try self.ensureCapacity(req_limbs);
214303
215 self.positive = value >= 0;304 self.metadata = req_limbs;
216 self.len = req_limbs;305 self.setSign(value >= 0);
217306
218 if (w_value <= maxInt(Limb)) {307 if (w_value <= maxInt(Limb)) {
219 self.limbs[0] = w_value;308 self.limbs[0] = w_value;
...@@ -240,6 +329,9 @@ pub const Int = struct {...@@ -240,6 +329,9 @@ pub const Int = struct {
240 TargetTooSmall,329 TargetTooSmall,
241 };330 };
242331
332 /// Convert self to type T.
333 ///
334 /// Returns an error if self cannot be narrowed into the requested type without truncation.
243 pub fn to(self: Int, comptime T: type) ConvertError!T {335 pub fn to(self: Int, comptime T: type) ConvertError!T {
244 switch (@typeId(T)) {336 switch (@typeId(T)) {
245 TypeId.Int => {337 TypeId.Int => {
...@@ -254,17 +346,17 @@ pub const Int = struct {...@@ -254,17 +346,17 @@ pub const Int = struct {
254 if (@sizeOf(UT) <= @sizeOf(Limb)) {346 if (@sizeOf(UT) <= @sizeOf(Limb)) {
255 r = @intCast(UT, self.limbs[0]);347 r = @intCast(UT, self.limbs[0]);
256 } else {348 } else {
257 for (self.limbs[0..self.len]) |_, ri| {349 for (self.limbs[0..self.len()]) |_, ri| {
258 const limb = self.limbs[self.len - ri - 1];350 const limb = self.limbs[self.len() - ri - 1];
259 r <<= Limb.bit_count;351 r <<= Limb.bit_count;
260 r |= limb;352 r |= limb;
261 }353 }
262 }354 }
263355
264 if (!T.is_signed) {356 if (!T.is_signed) {
265 return if (self.positive) @intCast(T, r) else error.NegativeIntoUnsigned;357 return if (self.isPositive()) @intCast(T, r) else error.NegativeIntoUnsigned;
266 } else {358 } else {
267 if (self.positive) {359 if (self.isPositive()) {
268 return @intCast(T, r);360 return @intCast(T, r);
269 } else {361 } else {
270 if (math.cast(T, r)) |ok| {362 if (math.cast(T, r)) |ok| {
...@@ -303,7 +395,15 @@ pub const Int = struct {...@@ -303,7 +395,15 @@ pub const Int = struct {
303 };395 };
304 }396 }
305397
398 /// Set self from the string representation `value`.
399 ///
400 /// value must contain only digits <= `base`. Base prefixes are not allowed (e.g. 0x43 should
401 /// simply be 43).
402 ///
403 /// Returns an error if memory could not be allocated or `value` has invalid digits for the
404 /// requested base.
306 pub fn setString(self: *Int, base: u8, value: []const u8) !void {405 pub fn setString(self: *Int, base: u8, value: []const u8) !void {
406 self.assertWritable();
307 if (base < 2 or base > 16) {407 if (base < 2 or base > 16) {
308 return error.InvalidBase;408 return error.InvalidBase;
309 }409 }
...@@ -315,27 +415,22 @@ pub const Int = struct {...@@ -315,27 +415,22 @@ pub const Int = struct {
315 i += 1;415 i += 1;
316 }416 }
317417
318 // TODO values less than limb size should guarantee non allocating418 const ap_base = Int.initFixed(([]Limb{base})[0..]);
319 var base_buffer: [512]u8 = undefined;
320 const base_al = &std.heap.FixedBufferAllocator.init(base_buffer[0..]).allocator;
321 const base_ap = try Int.initSet(base_al, base);
322
323 var d_buffer: [512]u8 = undefined;
324 var d_fba = std.heap.FixedBufferAllocator.init(d_buffer[0..]);
325 const d_al = &d_fba.allocator;
326
327 try self.set(0);419 try self.set(0);
420
328 for (value[i..]) |ch| {421 for (value[i..]) |ch| {
329 const d = try charToDigit(ch, base);422 const d = try charToDigit(ch, base);
330 d_fba.end_index = 0;
331 const d_ap = try Int.initSet(d_al, d);
332423
333 try self.mul(self.*, base_ap);424 const ap_d = Int.initFixed(([]Limb{d})[0..]);
334 try self.add(self.*, d_ap);425
426 try self.mul(self.*, ap_base);
427 try self.add(self.*, ap_d);
335 }428 }
336 self.positive = positive;429 self.setSign(positive);
337 }430 }
338431
432 /// Converts self to a string in the requested base. Memory is allocated from the provided
433 /// allocator and not the one present in self.
339 /// TODO make this call format instead of the other way around434 /// TODO make this call format instead of the other way around
340 pub fn toString(self: Int, allocator: *Allocator, base: u8) ![]const u8 {435 pub fn toString(self: Int, allocator: *Allocator, base: u8) ![]const u8 {
341 if (base < 2 or base > 16) {436 if (base < 2 or base > 16) {
...@@ -355,7 +450,7 @@ pub const Int = struct {...@@ -355,7 +450,7 @@ pub const Int = struct {
355 if (base & (base - 1) == 0) {450 if (base & (base - 1) == 0) {
356 const base_shift = math.log2_int(Limb, base);451 const base_shift = math.log2_int(Limb, base);
357452
358 for (self.limbs[0..self.len]) |limb| {453 for (self.limbs[0..self.len()]) |limb| {
359 var shift: usize = 0;454 var shift: usize = 0;
360 while (shift < Limb.bit_count) : (shift += base_shift) {455 while (shift < Limb.bit_count) : (shift += base_shift) {
361 const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & Limb(base - 1));456 const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & Limb(base - 1));
...@@ -382,11 +477,11 @@ pub const Int = struct {...@@ -382,11 +477,11 @@ pub const Int = struct {
382 }477 }
383478
384 var q = try self.clone();479 var q = try self.clone();
385 q.positive = true;480 q.abs();
386 var r = try Int.init(allocator);481 var r = try Int.init(allocator);
387 var b = try Int.initSet(allocator, limb_base);482 var b = try Int.initSet(allocator, limb_base);
388483
389 while (q.len >= 2) {484 while (q.len() >= 2) {
390 try Int.divTrunc(&q, &r, q, b);485 try Int.divTrunc(&q, &r, q, b);
391486
392 var r_word = r.limbs[0];487 var r_word = r.limbs[0];
...@@ -399,7 +494,7 @@ pub const Int = struct {...@@ -399,7 +494,7 @@ pub const Int = struct {
399 }494 }
400495
401 {496 {
402 debug.assert(q.len == 1);497 debug.assert(q.len() == 1);
403498
404 var r_word = q.limbs[0];499 var r_word = q.limbs[0];
405 while (r_word != 0) {500 while (r_word != 0) {
...@@ -410,7 +505,7 @@ pub const Int = struct {...@@ -410,7 +505,7 @@ pub const Int = struct {
410 }505 }
411 }506 }
412507
413 if (!self.positive) {508 if (!self.isPositive()) {
414 try digits.append('-');509 try digits.append('-');
415 }510 }
416511
...@@ -419,7 +514,7 @@ pub const Int = struct {...@@ -419,7 +514,7 @@ pub const Int = struct {
419 return s;514 return s;
420 }515 }
421516
422 /// for the std lib format function517 /// To allow `std.fmt.printf` to work with Int.
423 /// TODO make this non-allocating518 /// TODO make this non-allocating
424 pub fn format(519 pub fn format(
425 self: Int,520 self: Int,
...@@ -428,22 +523,24 @@ pub const Int = struct {...@@ -428,22 +523,24 @@ pub const Int = struct {
428 comptime FmtError: type,523 comptime FmtError: type,
429 output: fn (@typeOf(context), []const u8) FmtError!void,524 output: fn (@typeOf(context), []const u8) FmtError!void,
430 ) FmtError!void {525 ) FmtError!void {
526 self.assertWritable();
431 // TODO look at fmt and support other bases527 // TODO look at fmt and support other bases
432 const str = self.toString(self.allocator, 10) catch @panic("TODO make this non allocating");528 // TODO support read-only fixed integers
433 defer self.allocator.free(str);529 const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
530 defer self.allocator.?.free(str);
434 return output(context, str);531 return output(context, str);
435 }532 }
436533
437 // returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.534 /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
438 pub fn cmpAbs(a: Int, b: Int) i8 {535 pub fn cmpAbs(a: Int, b: Int) i8 {
439 if (a.len < b.len) {536 if (a.len() < b.len()) {
440 return -1;537 return -1;
441 }538 }
442 if (a.len > b.len) {539 if (a.len() > b.len()) {
443 return 1;540 return 1;
444 }541 }
445542
446 var i: usize = a.len - 1;543 var i: usize = a.len() - 1;
447 while (i != 0) : (i -= 1) {544 while (i != 0) : (i -= 1) {
448 if (a.limbs[i] != b.limbs[i]) {545 if (a.limbs[i] != b.limbs[i]) {
449 break;546 break;
...@@ -459,53 +556,37 @@ pub const Int = struct {...@@ -459,53 +556,37 @@ pub const Int = struct {
459 }556 }
460 }557 }
461558
462 // returns -1, 0, 1 if a < b, a == b or a > b respectively.559 /// Returns -1, 0, 1 if a < b, a == b or a > b respectively.
463 pub fn cmp(a: Int, b: Int) i8 {560 pub fn cmp(a: Int, b: Int) i8 {
464 if (a.positive != b.positive) {561 if (a.isPositive() != b.isPositive()) {
465 return if (a.positive) i8(1) else -1;562 return if (a.isPositive()) i8(1) else -1;
466 } else {563 } else {
467 const r = cmpAbs(a, b);564 const r = cmpAbs(a, b);
468 return if (a.positive) r else -r;565 return if (a.isPositive()) r else -r;
469 }566 }
470 }567 }
471568
472 // if a == 0569 /// Returns true if a == 0.
473 pub fn eqZero(a: Int) bool {570 pub fn eqZero(a: Int) bool {
474 return a.len == 1 and a.limbs[0] == 0;571 return a.len() == 1 and a.limbs[0] == 0;
475 }572 }
476573
477 // if |a| == |b|574 /// Returns true if |a| == |b|.
478 pub fn eqAbs(a: Int, b: Int) bool {575 pub fn eqAbs(a: Int, b: Int) bool {
479 return cmpAbs(a, b) == 0;576 return cmpAbs(a, b) == 0;
480 }577 }
481578
482 // if a == b579 /// Returns true if a == b.
483 pub fn eq(a: Int, b: Int) bool {580 pub fn eq(a: Int, b: Int) bool {
484 return cmp(a, b) == 0;581 return cmp(a, b) == 0;
485 }582 }
486583
487 // Normalize for a possible single carry digit.
488 //
489 // [1, 2, 3, 4, 0] -> [1, 2, 3, 4]
490 // [1, 2, 3, 4, 5] -> [1, 2, 3, 4, 5]
491 // [0] -> [0]
492 fn norm1(r: *Int, length: usize) void {
493 debug.assert(length > 0);
494 debug.assert(length <= r.limbs.len);
495
496 if (r.limbs[length - 1] == 0) {
497 r.len = if (length > 1) length - 1 else 1;
498 } else {
499 r.len = length;
500 }
501 }
502
503 // Normalize a possible sequence of leading zeros.584 // Normalize a possible sequence of leading zeros.
504 //585 //
505 // [1, 2, 3, 4, 0] -> [1, 2, 3, 4]586 // [1, 2, 3, 4, 0] -> [1, 2, 3, 4]
506 // [1, 2, 0, 0, 0] -> [1, 2]587 // [1, 2, 0, 0, 0] -> [1, 2]
507 // [0, 0, 0, 0, 0] -> [0]588 // [0, 0, 0, 0, 0] -> [0]
508 fn normN(r: *Int, length: usize) void {589 fn normalize(r: *Int, length: usize) void {
509 debug.assert(length > 0);590 debug.assert(length > 0);
510 debug.assert(length <= r.limbs.len);591 debug.assert(length <= r.limbs.len);
511592
...@@ -517,11 +598,25 @@ pub const Int = struct {...@@ -517,11 +598,25 @@ pub const Int = struct {
517 }598 }
518599
519 // Handle zero600 // Handle zero
520 r.len = if (j != 0) j else 1;601 r.setLen(if (j != 0) j else 1);
521 }602 }
522603
523 // r = a + b604 // Cannot be used as a result argument to any function.
605 fn readOnlyPositive(a: Int) Int {
606 return Int{
607 .allocator = null,
608 .metadata = a.len(),
609 .limbs = a.limbs,
610 };
611 }
612
613 /// r = a + b
614 ///
615 /// r, a and b may be aliases.
616 ///
617 /// Returns an error if memory could not be allocated.
524 pub fn add(r: *Int, a: Int, b: Int) Allocator.Error!void {618 pub fn add(r: *Int, a: Int, b: Int) Allocator.Error!void {
619 r.assertWritable();
525 if (a.eqZero()) {620 if (a.eqZero()) {
526 try r.copy(b);621 try r.copy(b);
527 return;622 return;
...@@ -530,38 +625,26 @@ pub const Int = struct {...@@ -530,38 +625,26 @@ pub const Int = struct {
530 return;625 return;
531 }626 }
532627
533 if (a.positive != b.positive) {628 if (a.isPositive() != b.isPositive()) {
534 if (a.positive) {629 if (a.isPositive()) {
535 // (a) + (-b) => a - b630 // (a) + (-b) => a - b
536 const bp = Int{631 try r.sub(a, readOnlyPositive(b));
537 .allocator = undefined,
538 .positive = true,
539 .limbs = b.limbs,
540 .len = b.len,
541 };
542 try r.sub(a, bp);
543 } else {632 } else {
544 // (-a) + (b) => b - a633 // (-a) + (b) => b - a
545 const ap = Int{634 try r.sub(b, readOnlyPositive(a));
546 .allocator = undefined,
547 .positive = true,
548 .limbs = a.limbs,
549 .len = a.len,
550 };
551 try r.sub(b, ap);
552 }635 }
553 } else {636 } else {
554 if (a.len >= b.len) {637 if (a.len() >= b.len()) {
555 try r.ensureCapacity(a.len + 1);638 try r.ensureCapacity(a.len() + 1);
556 lladd(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);639 lladd(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
557 r.norm1(a.len + 1);640 r.normalize(a.len() + 1);
558 } else {641 } else {
559 try r.ensureCapacity(b.len + 1);642 try r.ensureCapacity(b.len() + 1);
560 lladd(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);643 lladd(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
561 r.norm1(b.len + 1);644 r.normalize(b.len() + 1);
562 }645 }
563646
564 r.positive = a.positive;647 r.setSign(a.isPositive());
565 }648 }
566 }649 }
567650
...@@ -589,55 +672,48 @@ pub const Int = struct {...@@ -589,55 +672,48 @@ pub const Int = struct {
589 r[i] = carry;672 r[i] = carry;
590 }673 }
591674
592 // r = a - b675 /// r = a - b
676 ///
677 /// r, a and b may be aliases.
678 ///
679 /// Returns an error if memory could not be allocated.
593 pub fn sub(r: *Int, a: Int, b: Int) !void {680 pub fn sub(r: *Int, a: Int, b: Int) !void {
594 if (a.positive != b.positive) {681 r.assertWritable();
595 if (a.positive) {682 if (a.isPositive() != b.isPositive()) {
683 if (a.isPositive()) {
596 // (a) - (-b) => a + b684 // (a) - (-b) => a + b
597 const bp = Int{685 try r.add(a, readOnlyPositive(b));
598 .allocator = undefined,
599 .positive = true,
600 .limbs = b.limbs,
601 .len = b.len,
602 };
603 try r.add(a, bp);
604 } else {686 } else {
605 // (-a) - (b) => -(a + b)687 // (-a) - (b) => -(a + b)
606 const ap = Int{688 try r.add(readOnlyPositive(a), b);
607 .allocator = undefined,689 r.setSign(false);
608 .positive = true,
609 .limbs = a.limbs,
610 .len = a.len,
611 };
612 try r.add(ap, b);
613 r.positive = false;
614 }690 }
615 } else {691 } else {
616 if (a.positive) {692 if (a.isPositive()) {
617 // (a) - (b) => a - b693 // (a) - (b) => a - b
618 if (a.cmp(b) >= 0) {694 if (a.cmp(b) >= 0) {
619 try r.ensureCapacity(a.len + 1);695 try r.ensureCapacity(a.len() + 1);
620 llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);696 llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
621 r.normN(a.len);697 r.normalize(a.len());
622 r.positive = true;698 r.setSign(true);
623 } else {699 } else {
624 try r.ensureCapacity(b.len + 1);700 try r.ensureCapacity(b.len() + 1);
625 llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);701 llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
626 r.normN(b.len);702 r.normalize(b.len());
627 r.positive = false;703 r.setSign(false);
628 }704 }
629 } else {705 } else {
630 // (-a) - (-b) => -(a - b)706 // (-a) - (-b) => -(a - b)
631 if (a.cmp(b) < 0) {707 if (a.cmp(b) < 0) {
632 try r.ensureCapacity(a.len + 1);708 try r.ensureCapacity(a.len() + 1);
633 llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);709 llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
634 r.normN(a.len);710 r.normalize(a.len());
635 r.positive = false;711 r.setSign(false);
636 } else {712 } else {
637 try r.ensureCapacity(b.len + 1);713 try r.ensureCapacity(b.len() + 1);
638 llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);714 llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
639 r.normN(b.len);715 r.normalize(b.len());
640 r.positive = true;716 r.setSign(true);
641 }717 }
642 }718 }
643 }719 }
...@@ -667,16 +743,20 @@ pub const Int = struct {...@@ -667,16 +743,20 @@ pub const Int = struct {
667 debug.assert(borrow == 0);743 debug.assert(borrow == 0);
668 }744 }
669745
670 // rma = a * b746 /// rma = a * b
671 //747 ///
672 // For greatest efficiency, ensure rma does not alias a or b.748 /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
749 ///
750 /// Returns an error if memory could not be allocated.
673 pub fn mul(rma: *Int, a: Int, b: Int) !void {751 pub fn mul(rma: *Int, a: Int, b: Int) !void {
752 rma.assertWritable();
753
674 var r = rma;754 var r = rma;
675 var aliased = rma.limbs.ptr == a.limbs.ptr or rma.limbs.ptr == b.limbs.ptr;755 var aliased = rma.limbs.ptr == a.limbs.ptr or rma.limbs.ptr == b.limbs.ptr;
676756
677 var sr: Int = undefined;757 var sr: Int = undefined;
678 if (aliased) {758 if (aliased) {
679 sr = try Int.initCapacity(rma.allocator, a.len + b.len);759 sr = try Int.initCapacity(rma.allocator.?, a.len() + b.len());
680 r = &sr;760 r = &sr;
681 aliased = true;761 aliased = true;
682 }762 }
...@@ -685,16 +765,16 @@ pub const Int = struct {...@@ -685,16 +765,16 @@ pub const Int = struct {
685 r.deinit();765 r.deinit();
686 };766 };
687767
688 try r.ensureCapacity(a.len + b.len);768 try r.ensureCapacity(a.len() + b.len());
689769
690 if (a.len >= b.len) {770 if (a.len() >= b.len()) {
691 llmul(r.limbs, a.limbs[0..a.len], b.limbs[0..b.len]);771 llmul(r.limbs, a.limbs[0..a.len()], b.limbs[0..b.len()]);
692 } else {772 } else {
693 llmul(r.limbs, b.limbs[0..b.len], a.limbs[0..a.len]);773 llmul(r.limbs, b.limbs[0..b.len()], a.limbs[0..a.len()]);
694 }774 }
695775
696 r.positive = a.positive == b.positive;776 r.normalize(a.len() + b.len());
697 r.normN(a.len + b.len);777 r.setSign(a.isPositive() == b.isPositive());
698 }778 }
699779
700 // a + b * c + *carry, sets carry to the overflow bits780 // a + b * c + *carry, sets carry to the overflow bits
...@@ -740,29 +820,34 @@ pub const Int = struct {...@@ -740,29 +820,34 @@ pub const Int = struct {
740 }820 }
741 }821 }
742822
823 /// q = a / b (rem r)
824 ///
825 /// a / b are floored (rounded towards 0).
743 pub fn divFloor(q: *Int, r: *Int, a: Int, b: Int) !void {826 pub fn divFloor(q: *Int, r: *Int, a: Int, b: Int) !void {
744 try div(q, r, a, b);827 try div(q, r, a, b);
745828
746 // Trunc -> Floor.829 // Trunc -> Floor.
747 if (!q.positive) {830 if (!q.isPositive()) {
748 // TODO values less than limb size should guarantee non allocating831 const one = Int.initFixed(([]Limb{1})[0..]);
749 var one_buffer: [512]u8 = undefined;832 try q.sub(q.*, one);
750 const one_al = &std.heap.FixedBufferAllocator.init(one_buffer[0..]).allocator;833 try r.add(q.*, one);
751 const one_ap = try Int.initSet(one_al, 1);
752
753 try q.sub(q.*, one_ap);
754 try r.add(q.*, one_ap);
755 }834 }
756 r.positive = b.positive;835 r.setSign(b.isPositive());
757 }836 }
758837
838 /// q = a / b (rem r)
839 ///
840 /// a / b are truncated (rounded towards -inf).
759 pub fn divTrunc(q: *Int, r: *Int, a: Int, b: Int) !void {841 pub fn divTrunc(q: *Int, r: *Int, a: Int, b: Int) !void {
760 try div(q, r, a, b);842 try div(q, r, a, b);
761 r.positive = a.positive;843 r.setSign(a.isPositive());
762 }844 }
763845
764 // Truncates by default.846 // Truncates by default.
765 fn div(quo: *Int, rem: *Int, a: Int, b: Int) !void {847 fn div(quo: *Int, rem: *Int, a: Int, b: Int) !void {
848 quo.assertWritable();
849 rem.assertWritable();
850
766 if (b.eqZero()) {851 if (b.eqZero()) {
767 @panic("division by zero");852 @panic("division by zero");
768 }853 }
...@@ -773,36 +858,67 @@ pub const Int = struct {...@@ -773,36 +858,67 @@ pub const Int = struct {
773 if (a.cmpAbs(b) < 0) {858 if (a.cmpAbs(b) < 0) {
774 // quo may alias a so handle rem first859 // quo may alias a so handle rem first
775 try rem.copy(a);860 try rem.copy(a);
776 rem.positive = a.positive == b.positive;861 rem.setSign(a.isPositive() == b.isPositive());
777862
778 quo.positive = true;863 quo.metadata = 1;
779 quo.len = 1;
780 quo.limbs[0] = 0;864 quo.limbs[0] = 0;
781 return;865 return;
782 }866 }
783867
784 if (b.len == 1) {868 // Handle trailing zero-words of divisor/dividend. These are not handled in the following
785 try quo.ensureCapacity(a.len);869 // algorithms.
870 const a_zero_limb_count = blk: {
871 var i: usize = 0;
872 while (i < a.len()) : (i += 1) {
873 if (a.limbs[i] != 0) break;
874 }
875 break :blk i;
876 };
877 const b_zero_limb_count = blk: {
878 var i: usize = 0;
879 while (i < b.len()) : (i += 1) {
880 if (b.limbs[i] != 0) break;
881 }
882 break :blk i;
883 };
786884
787 lldiv1(quo.limbs[0..], &rem.limbs[0], a.limbs[0..a.len], b.limbs[0]);885 const ab_zero_limb_count = std.math.min(a_zero_limb_count, b_zero_limb_count);
788 quo.norm1(a.len);
789 quo.positive = a.positive == b.positive;
790886
791 rem.len = 1;887 if (b.len() - ab_zero_limb_count == 1) {
792 rem.positive = true;888 try quo.ensureCapacity(a.len());
889
890 lldiv1(quo.limbs[0..], &rem.limbs[0], a.limbs[ab_zero_limb_count..a.len()], b.limbs[b.len() - 1]);
891 quo.normalize(a.len() - ab_zero_limb_count);
892 quo.setSign(a.isPositive() == b.isPositive());
893
894 rem.metadata = 1;
793 } else {895 } else {
794 // x and y are modified during division896 // x and y are modified during division
795 var x = try a.clone();897 var x = try Int.initCapacity(quo.allocator.?, a.len());
796 defer x.deinit();898 defer x.deinit();
899 try x.copy(a);
797900
798 var y = try b.clone();901 var y = try Int.initCapacity(quo.allocator.?, b.len());
799 defer y.deinit();902 defer y.deinit();
903 try y.copy(b);
800904
801 // x may grow one limb during normalization905 // x may grow one limb during normalization
802 try quo.ensureCapacity(a.len + y.len);906 try quo.ensureCapacity(a.len() + y.len());
803 try divN(quo.allocator, quo, rem, &x, &y);907
908 // Shrink x, y such that the trailing zero limbs shared between are removed.
909 if (ab_zero_limb_count != 0) {
910 std.mem.copy(Limb, x.limbs[0..], x.limbs[ab_zero_limb_count..]);
911 std.mem.copy(Limb, y.limbs[0..], y.limbs[ab_zero_limb_count..]);
912 x.metadata -= ab_zero_limb_count;
913 y.metadata -= ab_zero_limb_count;
914 }
804915
805 quo.positive = a.positive == b.positive;916 try divN(quo.allocator.?, quo, rem, &x, &y);
917 quo.setSign(a.isPositive() == b.isPositive());
918 }
919
920 if (ab_zero_limb_count != 0) {
921 try rem.shiftLeft(rem.*, ab_zero_limb_count * Limb.bit_count);
806 }922 }
807 }923 }
808924
...@@ -837,25 +953,28 @@ pub const Int = struct {...@@ -837,25 +953,28 @@ pub const Int = struct {
837 //953 //
838 // x = qy + r where 0 <= r < y954 // x = qy + r where 0 <= r < y
839 fn divN(allocator: *Allocator, q: *Int, r: *Int, x: *Int, y: *Int) !void {955 fn divN(allocator: *Allocator, q: *Int, r: *Int, x: *Int, y: *Int) !void {
840 debug.assert(y.len >= 2);956 debug.assert(y.len() >= 2);
841 debug.assert(x.len >= y.len);957 debug.assert(x.len() >= y.len());
842 debug.assert(q.limbs.len >= x.len + y.len - 1);958 debug.assert(q.limbs.len >= x.len() + y.len() - 1);
843 debug.assert(default_capacity >= 3); // see 3.2959 debug.assert(default_capacity >= 3); // see 3.2
844960
845 var tmp = try Int.init(allocator);961 var tmp = try Int.init(allocator);
846 defer tmp.deinit();962 defer tmp.deinit();
847963
848 // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set)964 // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) and even
849 const norm_shift = @clz(y.limbs[y.len - 1]);965 var norm_shift = @clz(y.limbs[y.len() - 1]);
966 if (norm_shift == 0 and y.isOdd()) {
967 norm_shift = Limb.bit_count;
968 }
850 try x.shiftLeft(x.*, norm_shift);969 try x.shiftLeft(x.*, norm_shift);
851 try y.shiftLeft(y.*, norm_shift);970 try y.shiftLeft(y.*, norm_shift);
852971
853 const n = x.len - 1;972 const n = x.len() - 1;
854 const t = y.len - 1;973 const t = y.len() - 1;
855974
856 // 1.975 // 1.
857 q.len = n - t + 1;976 q.metadata = n - t + 1;
858 mem.set(Limb, q.limbs[0..q.len], 0);977 mem.set(Limb, q.limbs[0..q.len()], 0);
859978
860 // 2.979 // 2.
861 try tmp.shiftLeft(y.*, Limb.bit_count * (n - t));980 try tmp.shiftLeft(y.*, Limb.bit_count * (n - t));
...@@ -880,7 +999,7 @@ pub const Int = struct {...@@ -880,7 +999,7 @@ pub const Int = struct {
880 tmp.limbs[0] = if (i >= 2) x.limbs[i - 2] else 0;999 tmp.limbs[0] = if (i >= 2) x.limbs[i - 2] else 0;
881 tmp.limbs[1] = if (i >= 1) x.limbs[i - 1] else 0;1000 tmp.limbs[1] = if (i >= 1) x.limbs[i - 1] else 0;
882 tmp.limbs[2] = x.limbs[i];1001 tmp.limbs[2] = x.limbs[i];
883 tmp.normN(3);1002 tmp.normalize(3);
8841003
885 while (true) {1004 while (true) {
886 // 2x1 limb multiplication unrolled against single-limb q[i-t-1]1005 // 2x1 limb multiplication unrolled against single-limb q[i-t-1]
...@@ -888,7 +1007,7 @@ pub const Int = struct {...@@ -888,7 +1007,7 @@ pub const Int = struct {
888 r.limbs[0] = addMulLimbWithCarry(0, if (t >= 1) y.limbs[t - 1] else 0, q.limbs[i - t - 1], &carry);1007 r.limbs[0] = addMulLimbWithCarry(0, if (t >= 1) y.limbs[t - 1] else 0, q.limbs[i - t - 1], &carry);
889 r.limbs[1] = addMulLimbWithCarry(0, y.limbs[t], q.limbs[i - t - 1], &carry);1008 r.limbs[1] = addMulLimbWithCarry(0, y.limbs[t], q.limbs[i - t - 1], &carry);
890 r.limbs[2] = carry;1009 r.limbs[2] = carry;
891 r.normN(3);1010 r.normalize(3);
8921011
893 if (r.cmpAbs(tmp) <= 0) {1012 if (r.cmpAbs(tmp) <= 0) {
894 break;1013 break;
...@@ -903,7 +1022,7 @@ pub const Int = struct {...@@ -903,7 +1022,7 @@ pub const Int = struct {
903 try tmp.shiftLeft(tmp, Limb.bit_count * (i - t - 1));1022 try tmp.shiftLeft(tmp, Limb.bit_count * (i - t - 1));
904 try x.sub(x.*, tmp);1023 try x.sub(x.*, tmp);
9051024
906 if (!x.positive) {1025 if (!x.isPositive()) {
907 try tmp.shiftLeft(y.*, Limb.bit_count * (i - t - 1));1026 try tmp.shiftLeft(y.*, Limb.bit_count * (i - t - 1));
908 try x.add(x.*, tmp);1027 try x.add(x.*, tmp);
909 q.limbs[i - t - 1] -= 1;1028 q.limbs[i - t - 1] -= 1;
...@@ -911,18 +1030,20 @@ pub const Int = struct {...@@ -911,18 +1030,20 @@ pub const Int = struct {
911 }1030 }
9121031
913 // Denormalize1032 // Denormalize
914 q.normN(q.len);1033 q.normalize(q.len());
9151034
916 try r.shiftRight(x.*, norm_shift);1035 try r.shiftRight(x.*, norm_shift);
917 r.normN(r.len);1036 r.normalize(r.len());
918 }1037 }
9191038
920 // r = a << shift, in other words, r = a * 2^shift1039 /// r = a << shift, in other words, r = a * 2^shift
921 pub fn shiftLeft(r: *Int, a: Int, shift: usize) !void {1040 pub fn shiftLeft(r: *Int, a: Int, shift: usize) !void {
922 try r.ensureCapacity(a.len + (shift / Limb.bit_count) + 1);1041 r.assertWritable();
923 llshl(r.limbs[0..], a.limbs[0..a.len], shift);1042
924 r.norm1(a.len + (shift / Limb.bit_count) + 1);1043 try r.ensureCapacity(a.len() + (shift / Limb.bit_count) + 1);
925 r.positive = a.positive;1044 llshl(r.limbs[0..], a.limbs[0..a.len()], shift);
1045 r.normalize(a.len() + (shift / Limb.bit_count) + 1);
1046 r.setSign(a.isPositive());
926 }1047 }
9271048
928 fn llshl(r: []Limb, a: []const Limb, shift: usize) void {1049 fn llshl(r: []Limb, a: []const Limb, shift: usize) void {
...@@ -948,19 +1069,20 @@ pub const Int = struct {...@@ -948,19 +1069,20 @@ pub const Int = struct {
948 mem.set(Limb, r[0 .. limb_shift - 1], 0);1069 mem.set(Limb, r[0 .. limb_shift - 1], 0);
949 }1070 }
9501071
951 // r = a >> shift1072 /// r = a >> shift
952 pub fn shiftRight(r: *Int, a: Int, shift: usize) !void {1073 pub fn shiftRight(r: *Int, a: Int, shift: usize) !void {
953 if (a.len <= shift / Limb.bit_count) {1074 r.assertWritable();
954 r.len = 1;1075
1076 if (a.len() <= shift / Limb.bit_count) {
1077 r.metadata = 1;
955 r.limbs[0] = 0;1078 r.limbs[0] = 0;
956 r.positive = true;
957 return;1079 return;
958 }1080 }
9591081
960 try r.ensureCapacity(a.len - (shift / Limb.bit_count));1082 try r.ensureCapacity(a.len() - (shift / Limb.bit_count));
961 const r_len = llshr(r.limbs[0..], a.limbs[0..a.len], shift);1083 const r_len = llshr(r.limbs[0..], a.limbs[0..a.len()], shift);
962 r.len = a.len - (shift / Limb.bit_count);1084 r.metadata = a.len() - (shift / Limb.bit_count);
963 r.positive = a.positive;1085 r.setSign(a.isPositive());
964 }1086 }
9651087
966 fn llshr(r: []Limb, a: []const Limb, shift: usize) void {1088 fn llshr(r: []Limb, a: []const Limb, shift: usize) void {
...@@ -983,16 +1105,20 @@ pub const Int = struct {...@@ -983,16 +1105,20 @@ pub const Int = struct {
983 }1105 }
984 }1106 }
9851107
986 // r = a | b1108 /// r = a | b
1109 ///
1110 /// a and b are zero-extended to the longer of a or b.
987 pub fn bitOr(r: *Int, a: Int, b: Int) !void {1111 pub fn bitOr(r: *Int, a: Int, b: Int) !void {
988 if (a.len > b.len) {1112 r.assertWritable();
989 try r.ensureCapacity(a.len);1113
990 llor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);1114 if (a.len() > b.len()) {
991 r.len = a.len;1115 try r.ensureCapacity(a.len());
1116 llor(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
1117 r.setLen(a.len());
992 } else {1118 } else {
993 try r.ensureCapacity(b.len);1119 try r.ensureCapacity(b.len());
994 llor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);1120 llor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
995 r.len = b.len;1121 r.setLen(b.len());
996 }1122 }
997 }1123 }
9981124
...@@ -1010,16 +1136,18 @@ pub const Int = struct {...@@ -1010,16 +1136,18 @@ pub const Int = struct {
1010 }1136 }
1011 }1137 }
10121138
1013 // r = a & b1139 /// r = a & b
1014 pub fn bitAnd(r: *Int, a: Int, b: Int) !void {1140 pub fn bitAnd(r: *Int, a: Int, b: Int) !void {
1015 if (a.len > b.len) {1141 r.assertWritable();
1016 try r.ensureCapacity(b.len);1142
1017 lland(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);1143 if (a.len() > b.len()) {
1018 r.normN(b.len);1144 try r.ensureCapacity(b.len());
1145 lland(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
1146 r.normalize(b.len());
1019 } else {1147 } else {
1020 try r.ensureCapacity(a.len);1148 try r.ensureCapacity(a.len());
1021 lland(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);1149 lland(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
1022 r.normN(a.len);1150 r.normalize(a.len());
1023 }1151 }
1024 }1152 }
10251153
...@@ -1034,16 +1162,18 @@ pub const Int = struct {...@@ -1034,16 +1162,18 @@ pub const Int = struct {
1034 }1162 }
1035 }1163 }
10361164
1037 // r = a ^ b1165 /// r = a ^ b
1038 pub fn bitXor(r: *Int, a: Int, b: Int) !void {1166 pub fn bitXor(r: *Int, a: Int, b: Int) !void {
1039 if (a.len > b.len) {1167 r.assertWritable();
1040 try r.ensureCapacity(a.len);1168
1041 llxor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);1169 if (a.len() > b.len()) {
1042 r.normN(a.len);1170 try r.ensureCapacity(a.len());
1171 llxor(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]);
1172 r.normalize(a.len());
1043 } else {1173 } else {
1044 try r.ensureCapacity(b.len);1174 try r.ensureCapacity(b.len());
1045 llxor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]);1175 llxor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]);
1046 r.normN(b.len);1176 r.normalize(b.len());
1047 }1177 }
1048 }1178 }
10491179
...@@ -1067,7 +1197,9 @@ pub const Int = struct {...@@ -1067,7 +1197,9 @@ pub const Int = struct {
1067// They will still run on larger than this and should pass, but the multi-limb code-paths1197// They will still run on larger than this and should pass, but the multi-limb code-paths
1068// may be untested in some cases.1198// may be untested in some cases.
10691199
1070const al = debug.global_allocator;1200var buffer: [64 * 8192]u8 = undefined;
1201var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
1202const al = &fixed.allocator;
10711203
1072test "big.int comptime_int set" {1204test "big.int comptime_int set" {
1073 comptime var s = 0xefffffff00000001eeeeeeefaaaaaaab;1205 comptime var s = 0xefffffff00000001eeeeeeefaaaaaaab;
...@@ -1088,14 +1220,14 @@ test "big.int comptime_int set negative" {...@@ -1088,14 +1220,14 @@ test "big.int comptime_int set negative" {
1088 var a = try Int.initSet(al, -10);1220 var a = try Int.initSet(al, -10);
10891221
1090 testing.expect(a.limbs[0] == 10);1222 testing.expect(a.limbs[0] == 10);
1091 testing.expect(a.positive == false);1223 testing.expect(a.isPositive() == false);
1092}1224}
10931225
1094test "big.int int set unaligned small" {1226test "big.int int set unaligned small" {
1095 var a = try Int.initSet(al, u7(45));1227 var a = try Int.initSet(al, u7(45));
10961228
1097 testing.expect(a.limbs[0] == 45);1229 testing.expect(a.limbs[0] == 45);
1098 testing.expect(a.positive == true);1230 testing.expect(a.isPositive() == true);
1099}1231}
11001232
1101test "big.int comptime_int to" {1233test "big.int comptime_int to" {
...@@ -1116,7 +1248,7 @@ test "big.int to target too small error" {...@@ -1116,7 +1248,7 @@ test "big.int to target too small error" {
1116 testing.expectError(error.TargetTooSmall, a.to(u8));1248 testing.expectError(error.TargetTooSmall, a.to(u8));
1117}1249}
11181250
1119test "big.int norm1" {1251test "big.int normalize" {
1120 var a = try Int.init(al);1252 var a = try Int.init(al);
1121 try a.ensureCapacity(8);1253 try a.ensureCapacity(8);
11221254
...@@ -1124,26 +1256,26 @@ test "big.int norm1" {...@@ -1124,26 +1256,26 @@ test "big.int norm1" {
1124 a.limbs[1] = 2;1256 a.limbs[1] = 2;
1125 a.limbs[2] = 3;1257 a.limbs[2] = 3;
1126 a.limbs[3] = 0;1258 a.limbs[3] = 0;
1127 a.norm1(4);1259 a.normalize(4);
1128 testing.expect(a.len == 3);1260 testing.expect(a.len() == 3);
11291261
1130 a.limbs[0] = 1;1262 a.limbs[0] = 1;
1131 a.limbs[1] = 2;1263 a.limbs[1] = 2;
1132 a.limbs[2] = 3;1264 a.limbs[2] = 3;
1133 a.norm1(3);1265 a.normalize(3);
1134 testing.expect(a.len == 3);1266 testing.expect(a.len() == 3);
11351267
1136 a.limbs[0] = 0;1268 a.limbs[0] = 0;
1137 a.limbs[1] = 0;1269 a.limbs[1] = 0;
1138 a.norm1(2);1270 a.normalize(2);
1139 testing.expect(a.len == 1);1271 testing.expect(a.len() == 1);
11401272
1141 a.limbs[0] = 0;1273 a.limbs[0] = 0;
1142 a.norm1(1);1274 a.normalize(1);
1143 testing.expect(a.len == 1);1275 testing.expect(a.len() == 1);
1144}1276}
11451277
1146test "big.int normN" {1278test "big.int normalize multi" {
1147 var a = try Int.init(al);1279 var a = try Int.init(al);
1148 try a.ensureCapacity(8);1280 try a.ensureCapacity(8);
11491281
...@@ -1151,25 +1283,25 @@ test "big.int normN" {...@@ -1151,25 +1283,25 @@ test "big.int normN" {
1151 a.limbs[1] = 2;1283 a.limbs[1] = 2;
1152 a.limbs[2] = 0;1284 a.limbs[2] = 0;
1153 a.limbs[3] = 0;1285 a.limbs[3] = 0;
1154 a.normN(4);1286 a.normalize(4);
1155 testing.expect(a.len == 2);1287 testing.expect(a.len() == 2);
11561288
1157 a.limbs[0] = 1;1289 a.limbs[0] = 1;
1158 a.limbs[1] = 2;1290 a.limbs[1] = 2;
1159 a.limbs[2] = 3;1291 a.limbs[2] = 3;
1160 a.normN(3);1292 a.normalize(3);
1161 testing.expect(a.len == 3);1293 testing.expect(a.len() == 3);
11621294
1163 a.limbs[0] = 0;1295 a.limbs[0] = 0;
1164 a.limbs[1] = 0;1296 a.limbs[1] = 0;
1165 a.limbs[2] = 0;1297 a.limbs[2] = 0;
1166 a.limbs[3] = 0;1298 a.limbs[3] = 0;
1167 a.normN(4);1299 a.normalize(4);
1168 testing.expect(a.len == 1);1300 testing.expect(a.len() == 1);
11691301
1170 a.limbs[0] = 0;1302 a.limbs[0] = 0;
1171 a.normN(1);1303 a.normalize(1);
1172 testing.expect(a.len == 1);1304 testing.expect(a.len() == 1);
1173}1305}
11741306
1175test "big.int parity" {1307test "big.int parity" {
...@@ -1204,7 +1336,7 @@ test "big.int bitcount + sizeInBase" {...@@ -1204,7 +1336,7 @@ test "big.int bitcount + sizeInBase" {
1204 try a.shiftLeft(a, 5000);1336 try a.shiftLeft(a, 5000);
1205 testing.expect(a.bitCountAbs() == 5032);1337 testing.expect(a.bitCountAbs() == 5032);
1206 testing.expect(a.sizeInBase(2) >= 5032);1338 testing.expect(a.sizeInBase(2) >= 5032);
1207 a.positive = false;1339 a.setSign(false);
12081340
1209 testing.expect(a.bitCountAbs() == 5032);1341 testing.expect(a.bitCountAbs() == 5032);
1210 testing.expect(a.sizeInBase(2) >= 5033);1342 testing.expect(a.sizeInBase(2) >= 5033);
...@@ -1216,10 +1348,8 @@ test "big.int bitcount/to" {...@@ -1216,10 +1348,8 @@ test "big.int bitcount/to" {
1216 try a.set(0);1348 try a.set(0);
1217 testing.expect(a.bitCountTwosComp() == 0);1349 testing.expect(a.bitCountTwosComp() == 0);
12181350
1219 // TODO: stack smashing1351 testing.expect((try a.to(u0)) == 0);
1220 // testing.expect((try a.to(u0)) == 0);1352 testing.expect((try a.to(i0)) == 0);
1221 // TODO: sigsegv
1222 // testing.expect((try a.to(i0)) == 0);
12231353
1224 try a.set(-1);1354 try a.set(-1);
1225 testing.expect(a.bitCountTwosComp() == 1);1355 testing.expect(a.bitCountTwosComp() == 1);
...@@ -1980,6 +2110,98 @@ test "big.int div multi-multi (3.1/3.3 branch)" {...@@ -1980,6 +2110,98 @@ test "big.int div multi-multi (3.1/3.3 branch)" {
1980 testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);2110 testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);
1981}2111}
19822112
2113test "big.int div multi-single zero-limb trailing" {
2114 var a = try Int.initSet(al, 0x60000000000000000000000000000000000000000000000000000000000000000);
2115 var b = try Int.initSet(al, 0x10000000000000000);
2116
2117 var q = try Int.init(al);
2118 var r = try Int.init(al);
2119 try Int.divTrunc(&q, &r, a, b);
2120
2121 var expected = try Int.initSet(al, 0x6000000000000000000000000000000000000000000000000);
2122 testing.expect(q.eq(expected));
2123 testing.expect(r.eqZero());
2124}
2125
2126test "big.int div multi-multi zero-limb trailing (with rem)" {
2127 var a = try Int.initSet(al, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
2128 var b = try Int.initSet(al, 0x8666666655555555444444443333333300000000000000000000000000000000);
2129
2130 var q = try Int.init(al);
2131 var r = try Int.init(al);
2132 try Int.divTrunc(&q, &r, a, b);
2133
2134 testing.expect((try q.to(u128)) == 0x10000000000000000);
2135
2136 const rs = try r.toString(al, 16);
2137 testing.expect(std.mem.eql(u8, rs, "4444444344444443111111111111111100000000000000000000000000000000"));
2138}
2139
2140test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" {
2141 var a = try Int.initSet(al, 0x8666666655555555888888877777777611111111111111110000000000000000);
2142 var b = try Int.initSet(al, 0x8666666655555555444444443333333300000000000000000000000000000000);
2143
2144 var q = try Int.init(al);
2145 var r = try Int.init(al);
2146 try Int.divTrunc(&q, &r, a, b);
2147
2148 testing.expect((try q.to(u128)) == 0x1);
2149
2150 const rs = try r.toString(al, 16);
2151 testing.expect(std.mem.eql(u8, rs, "444444434444444311111111111111110000000000000000"));
2152}
2153
2154test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" {
2155 var a = try Int.initSet(al, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
2156 var b = try Int.initSet(al, 0x866666665555555544444444333333330000000000000000);
2157
2158 var q = try Int.init(al);
2159 var r = try Int.init(al);
2160 try Int.divTrunc(&q, &r, a, b);
2161
2162 const qs = try q.toString(al, 16);
2163 testing.expect(std.mem.eql(u8, qs, "10000000000000000820820803105186f"));
2164
2165 const rs = try r.toString(al, 16);
2166 testing.expect(std.mem.eql(u8, rs, "4e11f2baa5896a321d463b543d0104e30000000000000000"));
2167}
2168
2169test "big.int div multi-multi fuzz case #1" {
2170 var a = try Int.init(al);
2171 var b = try Int.init(al);
2172
2173 try a.setString(16, "ffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
2174 try b.setString(16, "3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000007fffffffffff");
2175
2176 var q = try Int.init(al);
2177 var r = try Int.init(al);
2178 try Int.divTrunc(&q, &r, a, b);
2179
2180 const qs = try q.toString(al, 16);
2181 testing.expect(std.mem.eql(u8, qs, "3ffffffffffffffffffffffffffff0000000000000000000000000000000000001ffffffffffffffffffffffffffff7fffffffe000000000000000000000000000180000000000000000000003fffffbfffffffdfffffffffffffeffff800000100101000000100000000020003fffffdfbfffffe3ffffffffffffeffff7fffc00800a100000017ffe000002000400007efbfff7fe9f00000037ffff3fff7fffa004006100000009ffe00000190038200bf7d2ff7fefe80400060000f7d7f8fbf9401fe38e0403ffc0bdffffa51102c300d7be5ef9df4e5060007b0127ad3fa69f97d0f820b6605ff617ddf7f32ad7a05c0d03f2e7bc78a6000e087a8bbcdc59e07a5a079128a7861f553ddebed7e8e56701756f9ead39b48cd1b0831889ea6ec1fddf643d0565b075ff07e6caea4e2854ec9227fd635ed60a2f5eef2893052ffd54718fa08604acbf6a15e78a467c4a3c53c0278af06c4416573f925491b195e8fd79302cb1aaf7caf4ecfc9aec1254cc969786363ac729f914c6ddcc26738d6b0facd54eba026580aba2eb6482a088b0d224a8852420b91ec1"));
2182
2183 const rs = try r.toString(al, 16);
2184 testing.expect(std.mem.eql(u8, rs, "310d1d4c414426b4836c2635bad1df3a424e50cbdd167ffccb4dfff57d36b4aae0d6ca0910698220171a0f3373c1060a046c2812f0027e321f72979daa5e7973214170d49e885de0c0ecc167837d44502430674a82522e5df6a0759548052420b91ec1"));
2185}
2186
2187test "big.int div multi-multi fuzz case #2" {
2188 var a = try Int.init(al);
2189 var b = try Int.init(al);
2190
2191 try a.setString(16, "3ffffffffe00000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000001fffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffc000000000000000000000000000000000000000000000000000000000000000");
2192 try b.setString(16, "ffc0000000000000000000000000000000000000000000000000");
2193
2194 var q = try Int.init(al);
2195 var r = try Int.init(al);
2196 try Int.divTrunc(&q, &r, a, b);
2197
2198 const qs = try q.toString(al, 16);
2199 testing.expect(std.mem.eql(u8, qs, "40100400fe3f8fe3f8fe3f8fe3f8fe3f8fe4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f91e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4992649926499264991e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4792e4b92e4b92e4b92e4b92a4a92a4a92a4"));
2200
2201 const rs = try r.toString(al, 16);
2202 testing.expect(std.mem.eql(u8, rs, "a900000000000000000000000000000000000000000000000000"));
2203}
2204
1983test "big.int shift-right single" {2205test "big.int shift-right single" {
1984 var a = try Int.initSet(al, 0xffff0000);2206 var a = try Int.initSet(al, 0xffff0000);
1985 try a.shiftRight(a, 16);2207 try a.shiftRight(a, 16);
std/math/big/rational.zig created+938
...@@ -0,0 +1,938 @@
1const std = @import("../../std.zig");
2const builtin = @import("builtin");
3const debug = std.debug;
4const math = std.math;
5const mem = std.mem;
6const testing = std.testing;
7const Allocator = mem.Allocator;
8const ArrayList = std.ArrayList;
9
10const TypeId = builtin.TypeId;
11
12const bn = @import("int.zig");
13const Limb = bn.Limb;
14const DoubleLimb = bn.DoubleLimb;
15const Int = bn.Int;
16
17/// An arbitrary-precision rational number.
18///
19/// Memory is allocated as needed for operations to ensure full precision is kept. The precision
20/// of a Rational is only bounded by memory.
21///
22/// Rational's are always normalized. That is, for a Rational r = p/q where p and q are integers,
23/// gcd(p, q) = 1 always.
24pub const Rational = struct {
25 /// Numerator. Determines the sign of the Rational.
26 p: Int,
27
28 /// Denominator. Sign is ignored.
29 q: Int,
30
31 /// Create a new Rational. A small amount of memory will be allocated on initialization.
32 /// This will be 2 * Int.default_capacity.
33 pub fn init(a: *Allocator) !Rational {
34 return Rational{
35 .p = try Int.init(a),
36 .q = try Int.initSet(a, 1),
37 };
38 }
39
40 /// Frees all memory associated with a Rational.
41 pub fn deinit(self: *Rational) void {
42 self.p.deinit();
43 self.q.deinit();
44 }
45
46 /// Set a Rational from a primitive integer type.
47 pub fn setInt(self: *Rational, a: var) !void {
48 try self.p.set(a);
49 try self.q.set(1);
50 }
51
52 /// Set a Rational from a string of the form `A/B` where A and B are base-10 integers.
53 pub fn setFloatString(self: *Rational, str: []const u8) !void {
54 // TODO: Accept a/b fractions and exponent form
55 if (str.len == 0) {
56 return error.InvalidFloatString;
57 }
58
59 const State = enum {
60 Integer,
61 Fractional,
62 };
63
64 var state = State.Integer;
65 var point: ?usize = null;
66
67 var start: usize = 0;
68 if (str[0] == '-') {
69 start += 1;
70 }
71
72 for (str) |c, i| {
73 switch (state) {
74 State.Integer => {
75 switch (c) {
76 '.' => {
77 state = State.Fractional;
78 point = i;
79 },
80 '0'...'9' => {
81 // okay
82 },
83 else => {
84 return error.InvalidFloatString;
85 },
86 }
87 },
88 State.Fractional => {
89 switch (c) {
90 '0'...'9' => {
91 // okay
92 },
93 else => {
94 return error.InvalidFloatString;
95 },
96 }
97 },
98 }
99 }
100
101 // TODO: batch the multiplies by 10
102 if (point) |i| {
103 try self.p.setString(10, str[0..i]);
104
105 const base = Int.initFixed(([]Limb{10})[0..]);
106
107 var j: usize = start;
108 while (j < str.len - i - 1) : (j += 1) {
109 try self.p.mul(self.p, base);
110 }
111
112 try self.q.setString(10, str[i + 1 ..]);
113 try self.p.add(self.p, self.q);
114
115 try self.q.set(1);
116 var k: usize = i + 1;
117 while (k < str.len) : (k += 1) {
118 try self.q.mul(self.q, base);
119 }
120
121 try self.reduce();
122 } else {
123 try self.p.setString(10, str[0..]);
124 try self.q.set(1);
125 }
126 }
127
128 /// Set a Rational from a floating-point value. The rational will have enough precision to
129 /// completely represent the provided float.
130 pub fn setFloat(self: *Rational, comptime T: type, f: T) !void {
131 // Translated from golang.go/src/math/big/rat.go.
132 debug.assert(@typeId(T) == builtin.TypeId.Float);
133
134 const UnsignedIntType = @IntType(false, T.bit_count);
135 const f_bits = @bitCast(UnsignedIntType, f);
136
137 const exponent_bits = math.floatExponentBits(T);
138 const exponent_bias = (1 << (exponent_bits - 1)) - 1;
139 const mantissa_bits = math.floatMantissaBits(T);
140
141 const exponent_mask = (1 << exponent_bits) - 1;
142 const mantissa_mask = (1 << mantissa_bits) - 1;
143
144 var exponent = @intCast(i16, (f_bits >> mantissa_bits) & exponent_mask);
145 var mantissa = f_bits & mantissa_mask;
146
147 switch (exponent) {
148 exponent_mask => {
149 return error.NonFiniteFloat;
150 },
151 0 => {
152 // denormal
153 exponent -= exponent_bias - 1;
154 },
155 else => {
156 // normal
157 mantissa |= 1 << mantissa_bits;
158 exponent -= exponent_bias;
159 },
160 }
161
162 var shift: i16 = mantissa_bits - exponent;
163
164 // factor out powers of two early from rational
165 while (mantissa & 1 == 0 and shift > 0) {
166 mantissa >>= 1;
167 shift -= 1;
168 }
169
170 try self.p.set(mantissa);
171 self.p.setSign(f >= 0);
172
173 try self.q.set(1);
174 if (shift >= 0) {
175 try self.q.shiftLeft(self.q, @intCast(usize, shift));
176 } else {
177 try self.p.shiftLeft(self.p, @intCast(usize, -shift));
178 }
179
180 try self.reduce();
181 }
182
183 /// Return a floating-point value that is the closest value to a Rational.
184 ///
185 /// The result may not be exact if the Rational is too precise or too large for the
186 /// target type.
187 pub fn toFloat(self: Rational, comptime T: type) !T {
188 // Translated from golang.go/src/math/big/rat.go.
189 // TODO: Indicate whether the result is not exact.
190 debug.assert(@typeId(T) == builtin.TypeId.Float);
191
192 const fsize = T.bit_count;
193 const BitReprType = @IntType(false, T.bit_count);
194
195 const msize = math.floatMantissaBits(T);
196 const msize1 = msize + 1;
197 const msize2 = msize1 + 1;
198
199 const esize = math.floatExponentBits(T);
200 const ebias = (1 << (esize - 1)) - 1;
201 const emin = 1 - ebias;
202 const emax = ebias;
203
204 if (self.p.eqZero()) {
205 return 0;
206 }
207
208 // 1. left-shift a or sub so that a/b is in [1 << msize1, 1 << (msize2 + 1)]
209 var exp = @intCast(isize, self.p.bitCountTwosComp()) - @intCast(isize, self.q.bitCountTwosComp());
210
211 var a2 = try self.p.clone();
212 defer a2.deinit();
213
214 var b2 = try self.q.clone();
215 defer b2.deinit();
216
217 const shift = msize2 - exp;
218 if (shift >= 0) {
219 try a2.shiftLeft(a2, @intCast(usize, shift));
220 } else {
221 try b2.shiftLeft(b2, @intCast(usize, -shift));
222 }
223
224 // 2. compute quotient and remainder
225 var q = try Int.init(self.p.allocator.?);
226 defer q.deinit();
227
228 // unused
229 var r = try Int.init(self.p.allocator.?);
230 defer r.deinit();
231
232 try Int.divTrunc(&q, &r, a2, b2);
233
234 var mantissa = extractLowBits(q, BitReprType);
235 var have_rem = r.len() > 0;
236
237 // 3. q didn't fit in msize2 bits, redo division b2 << 1
238 if (mantissa >> msize2 == 1) {
239 if (mantissa & 1 == 1) {
240 have_rem = true;
241 }
242 mantissa >>= 1;
243 exp += 1;
244 }
245 if (mantissa >> msize1 != 1) {
246 // NOTE: This can be hit if the limb size is small (u8/16).
247 @panic("unexpected bits in result");
248 }
249
250 // 4. Rounding
251 if (emin - msize <= exp and exp <= emin) {
252 // denormal
253 const shift1 = @intCast(math.Log2Int(BitReprType), emin - (exp - 1));
254 const lost_bits = mantissa & ((@intCast(BitReprType, 1) << shift1) - 1);
255 have_rem = have_rem or lost_bits != 0;
256 mantissa >>= shift1;
257 exp = 2 - ebias;
258 }
259
260 // round q using round-half-to-even
261 var exact = !have_rem;
262 if (mantissa & 1 != 0) {
263 exact = false;
264 if (have_rem or (mantissa & 2 != 0)) {
265 mantissa += 1;
266 if (mantissa >= 1 << msize2) {
267 // 11...1 => 100...0
268 mantissa >>= 1;
269 exp += 1;
270 }
271 }
272 }
273 mantissa >>= 1;
274
275 const f = math.scalbn(@intToFloat(T, mantissa), @intCast(i32, exp - msize1));
276 if (math.isInf(f)) {
277 exact = false;
278 }
279
280 return if (self.p.isPositive()) f else -f;
281 }
282
283 /// Set a rational from an integer ratio.
284 pub fn setRatio(self: *Rational, p: var, q: var) !void {
285 try self.p.set(p);
286 try self.q.set(q);
287
288 self.p.setSign(@boolToInt(self.p.isPositive()) ^ @boolToInt(self.q.isPositive()) == 0);
289 self.q.setSign(true);
290
291 try self.reduce();
292
293 if (self.q.eqZero()) {
294 @panic("cannot set rational with denominator = 0");
295 }
296 }
297
298 /// Set a Rational directly from an Int.
299 pub fn copyInt(self: *Rational, a: Int) !void {
300 try self.p.copy(a);
301 try self.q.set(1);
302 }
303
304 /// Set a Rational directly from a ratio of two Int's.
305 pub fn copyRatio(self: *Rational, a: Int, b: Int) !void {
306 try self.p.copy(a);
307 try self.q.copy(b);
308
309 self.p.setSign(@boolToInt(self.p.isPositive()) ^ @boolToInt(self.q.isPositive()) == 0);
310 self.q.setSign(true);
311
312 try self.reduce();
313 }
314
315 /// Make a Rational positive.
316 pub fn abs(r: *Rational) void {
317 r.p.abs();
318 }
319
320 /// Negate the sign of a Rational.
321 pub fn negate(r: *Rational) void {
322 r.p.negate();
323 }
324
325 /// Efficiently swap a Rational with another. This swaps the limb pointers and a full copy is not
326 /// performed. The address of the limbs field will not be the same after this function.
327 pub fn swap(r: *Rational, other: *Rational) void {
328 r.p.swap(&other.p);
329 r.q.swap(&other.q);
330 }
331
332 /// Returns -1, 0, 1 if a < b, a == b or a > b respectively.
333 pub fn cmp(a: Rational, b: Rational) !i8 {
334 return cmpInternal(a, b, true);
335 }
336
337 /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
338 pub fn cmpAbs(a: Rational, b: Rational) !i8 {
339 return cmpInternal(a, b, false);
340 }
341
342 // p/q > x/y iff p*y > x*q
343 fn cmpInternal(a: Rational, b: Rational, is_abs: bool) !i8 {
344 // TODO: Would a div compare algorithm of sorts be viable and quicker? Can we avoid
345 // the memory allocations here?
346 var q = try Int.init(a.p.allocator.?);
347 defer q.deinit();
348
349 var p = try Int.init(b.p.allocator.?);
350 defer p.deinit();
351
352 try q.mul(a.p, b.q);
353 try p.mul(b.p, a.q);
354
355 return if (is_abs) q.cmpAbs(p) else q.cmp(p);
356 }
357
358 /// rma = a + b.
359 ///
360 /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
361 ///
362 /// Returns an error if memory could not be allocated.
363 pub fn add(rma: *Rational, a: Rational, b: Rational) !void {
364 var r = rma;
365 var aliased = rma.p.limbs.ptr == a.p.limbs.ptr or rma.p.limbs.ptr == b.p.limbs.ptr;
366
367 var sr: Rational = undefined;
368 if (aliased) {
369 sr = try Rational.init(rma.p.allocator.?);
370 r = &sr;
371 aliased = true;
372 }
373 defer if (aliased) {
374 rma.swap(r);
375 r.deinit();
376 };
377
378 try r.p.mul(a.p, b.q);
379 try r.q.mul(b.p, a.q);
380 try r.p.add(r.p, r.q);
381
382 try r.q.mul(a.q, b.q);
383 try r.reduce();
384 }
385
386 /// rma = a - b.
387 ///
388 /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
389 ///
390 /// Returns an error if memory could not be allocated.
391 pub fn sub(rma: *Rational, a: Rational, b: Rational) !void {
392 var r = rma;
393 var aliased = rma.p.limbs.ptr == a.p.limbs.ptr or rma.p.limbs.ptr == b.p.limbs.ptr;
394
395 var sr: Rational = undefined;
396 if (aliased) {
397 sr = try Rational.init(rma.p.allocator.?);
398 r = &sr;
399 aliased = true;
400 }
401 defer if (aliased) {
402 rma.swap(r);
403 r.deinit();
404 };
405
406 try r.p.mul(a.p, b.q);
407 try r.q.mul(b.p, a.q);
408 try r.p.sub(r.p, r.q);
409
410 try r.q.mul(a.q, b.q);
411 try r.reduce();
412 }
413
414 /// rma = a * b.
415 ///
416 /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
417 ///
418 /// Returns an error if memory could not be allocated.
419 pub fn mul(r: *Rational, a: Rational, b: Rational) !void {
420 try r.p.mul(a.p, b.p);
421 try r.q.mul(a.q, b.q);
422 try r.reduce();
423 }
424
425 /// rma = a / b.
426 ///
427 /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
428 ///
429 /// Returns an error if memory could not be allocated.
430 pub fn div(r: *Rational, a: Rational, b: Rational) !void {
431 if (b.p.eqZero()) {
432 @panic("division by zero");
433 }
434
435 try r.p.mul(a.p, b.q);
436 try r.q.mul(b.p, a.q);
437 try r.reduce();
438 }
439
440 /// Invert the numerator and denominator fields of a Rational. p/q => q/p.
441 pub fn invert(r: *Rational) void {
442 Int.swap(&r.p, &r.q);
443 }
444
445 // reduce r/q such that gcd(r, q) = 1
446 fn reduce(r: *Rational) !void {
447 var a = try Int.init(r.p.allocator.?);
448 defer a.deinit();
449
450 const sign = r.p.isPositive();
451 r.p.abs();
452 try gcd(&a, r.p, r.q);
453 r.p.setSign(sign);
454
455 const one = Int.initFixed(([]Limb{1})[0..]);
456 if (a.cmp(one) != 0) {
457 var unused = try Int.init(r.p.allocator.?);
458 defer unused.deinit();
459
460 // TODO: divexact would be useful here
461 // TODO: don't copy r.q for div
462 try Int.divTrunc(&r.p, &unused, r.p, a);
463 try Int.divTrunc(&r.q, &unused, r.q, a);
464 }
465 }
466};
467
468const SignedDoubleLimb = @IntType(true, DoubleLimb.bit_count);
469
470fn gcd(rma: *Int, x: Int, y: Int) !void {
471 rma.assertWritable();
472 var r = rma;
473 var aliased = rma.limbs.ptr == x.limbs.ptr or rma.limbs.ptr == y.limbs.ptr;
474
475 var sr: Int = undefined;
476 if (aliased) {
477 sr = try Int.initCapacity(rma.allocator.?, math.max(x.len(), y.len()));
478 r = &sr;
479 aliased = true;
480 }
481 defer if (aliased) {
482 rma.swap(r);
483 r.deinit();
484 };
485
486 try gcdLehmer(r, x, y);
487}
488
489// Storage must live for the lifetime of the returned value
490fn FixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Int {
491 std.debug.assert(storage.len >= 2);
492
493 var A_is_positive = A >= 0;
494 const Au = @intCast(DoubleLimb, if (A < 0) -A else A);
495 storage[0] = @truncate(Limb, Au);
496 storage[1] = @truncate(Limb, Au >> Limb.bit_count);
497 var Ap = Int.initFixed(storage[0..2]);
498 Ap.setSign(A_is_positive);
499 return Ap;
500}
501
502fn gcdLehmer(r: *Int, xa: Int, ya: Int) !void {
503 var x = try xa.clone();
504 x.abs();
505 defer x.deinit();
506
507 var y = try ya.clone();
508 y.abs();
509 defer y.deinit();
510
511 if (x.cmp(y) < 0) {
512 x.swap(&y);
513 }
514
515 var T = try Int.init(r.allocator.?);
516 defer T.deinit();
517
518 while (y.len() > 1) {
519 debug.assert(x.isPositive() and y.isPositive());
520 debug.assert(x.len() >= y.len());
521
522 var xh: SignedDoubleLimb = x.limbs[x.len() - 1];
523 var yh: SignedDoubleLimb = if (x.len() > y.len()) 0 else y.limbs[x.len() - 1];
524
525 var A: SignedDoubleLimb = 1;
526 var B: SignedDoubleLimb = 0;
527 var C: SignedDoubleLimb = 0;
528 var D: SignedDoubleLimb = 1;
529
530 while (yh + C != 0 and yh + D != 0) {
531 const q = @divFloor(xh + A, yh + C);
532 const qp = @divFloor(xh + B, yh + D);
533 if (q != qp) {
534 break;
535 }
536
537 var t = A - q * C;
538 A = C;
539 C = t;
540 t = B - q * D;
541 B = D;
542 D = t;
543
544 t = xh - q * yh;
545 xh = yh;
546 yh = t;
547 }
548
549 if (B == 0) {
550 // T = x % y, r is unused
551 try Int.divTrunc(r, &T, x, y);
552 debug.assert(T.isPositive());
553
554 x.swap(&y);
555 y.swap(&T);
556 } else {
557 var storage: [8]Limb = undefined;
558 const Ap = FixedIntFromSignedDoubleLimb(A, storage[0..2]);
559 const Bp = FixedIntFromSignedDoubleLimb(B, storage[2..4]);
560 const Cp = FixedIntFromSignedDoubleLimb(C, storage[4..6]);
561 const Dp = FixedIntFromSignedDoubleLimb(D, storage[6..8]);
562
563 // T = Ax + By
564 try r.mul(x, Ap);
565 try T.mul(y, Bp);
566 try T.add(r.*, T);
567
568 // u = Cx + Dy, r as u
569 try x.mul(x, Cp);
570 try r.mul(y, Dp);
571 try r.add(x, r.*);
572
573 x.swap(&T);
574 y.swap(r);
575 }
576 }
577
578 // euclidean algorithm
579 debug.assert(x.cmp(y) >= 0);
580
581 while (!y.eqZero()) {
582 try Int.divTrunc(&T, r, x, y);
583 x.swap(&y);
584 y.swap(r);
585 }
586
587 r.swap(&x);
588}
589
590var buffer: [64 * 8192]u8 = undefined;
591var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
592var al = &fixed.allocator;
593
594test "big.rational gcd non-one small" {
595 var a = try Int.initSet(al, 17);
596 var b = try Int.initSet(al, 97);
597 var r = try Int.init(al);
598
599 try gcd(&r, a, b);
600
601 testing.expect((try r.to(u32)) == 1);
602}
603
604test "big.rational gcd non-one small" {
605 var a = try Int.initSet(al, 4864);
606 var b = try Int.initSet(al, 3458);
607 var r = try Int.init(al);
608
609 try gcd(&r, a, b);
610
611 testing.expect((try r.to(u32)) == 38);
612}
613
614test "big.rational gcd non-one large" {
615 var a = try Int.initSet(al, 0xffffffffffffffff);
616 var b = try Int.initSet(al, 0xffffffffffffffff7777);
617 var r = try Int.init(al);
618
619 try gcd(&r, a, b);
620
621 testing.expect((try r.to(u32)) == 4369);
622}
623
624test "big.rational gcd large multi-limb result" {
625 var a = try Int.initSet(al, 0x12345678123456781234567812345678123456781234567812345678);
626 var b = try Int.initSet(al, 0x12345671234567123456712345671234567123456712345671234567);
627 var r = try Int.init(al);
628
629 try gcd(&r, a, b);
630
631 testing.expect((try r.to(u256)) == 0xf000000ff00000fff0000ffff000fffff00ffffff1);
632}
633
634test "big.rational gcd one large" {
635 var a = try Int.initSet(al, 1897056385327307);
636 var b = try Int.initSet(al, 2251799813685248);
637 var r = try Int.init(al);
638
639 try gcd(&r, a, b);
640
641 testing.expect((try r.to(u64)) == 1);
642}
643
644fn extractLowBits(a: Int, comptime T: type) T {
645 testing.expect(@typeId(T) == builtin.TypeId.Int);
646
647 if (T.bit_count <= Limb.bit_count) {
648 return @truncate(T, a.limbs[0]);
649 } else {
650 var r: T = 0;
651 comptime var i: usize = 0;
652
653 // Remainder is always 0 since if T.bit_count >= Limb.bit_count -> Limb | T and both
654 // are powers of two.
655 inline while (i < T.bit_count / Limb.bit_count) : (i += 1) {
656 r |= math.shl(T, a.limbs[i], i * Limb.bit_count);
657 }
658
659 return r;
660 }
661}
662
663test "big.rational extractLowBits" {
664 var a = try Int.initSet(al, 0x11112222333344441234567887654321);
665
666 const a1 = extractLowBits(a, u8);
667 testing.expect(a1 == 0x21);
668
669 const a2 = extractLowBits(a, u16);
670 testing.expect(a2 == 0x4321);
671
672 const a3 = extractLowBits(a, u32);
673 testing.expect(a3 == 0x87654321);
674
675 const a4 = extractLowBits(a, u64);
676 testing.expect(a4 == 0x1234567887654321);
677
678 const a5 = extractLowBits(a, u128);
679 testing.expect(a5 == 0x11112222333344441234567887654321);
680}
681
682test "big.rational set" {
683 var a = try Rational.init(al);
684
685 try a.setInt(5);
686 testing.expect((try a.p.to(u32)) == 5);
687 testing.expect((try a.q.to(u32)) == 1);
688
689 try a.setRatio(7, 3);
690 testing.expect((try a.p.to(u32)) == 7);
691 testing.expect((try a.q.to(u32)) == 3);
692
693 try a.setRatio(9, 3);
694 testing.expect((try a.p.to(i32)) == 3);
695 testing.expect((try a.q.to(i32)) == 1);
696
697 try a.setRatio(-9, 3);
698 testing.expect((try a.p.to(i32)) == -3);
699 testing.expect((try a.q.to(i32)) == 1);
700
701 try a.setRatio(9, -3);
702 testing.expect((try a.p.to(i32)) == -3);
703 testing.expect((try a.q.to(i32)) == 1);
704
705 try a.setRatio(-9, -3);
706 testing.expect((try a.p.to(i32)) == 3);
707 testing.expect((try a.q.to(i32)) == 1);
708}
709
710test "big.rational setFloat" {
711 var a = try Rational.init(al);
712
713 try a.setFloat(f64, 2.5);
714 testing.expect((try a.p.to(i32)) == 5);
715 testing.expect((try a.q.to(i32)) == 2);
716
717 try a.setFloat(f32, -2.5);
718 testing.expect((try a.p.to(i32)) == -5);
719 testing.expect((try a.q.to(i32)) == 2);
720
721 try a.setFloat(f32, 3.141593);
722
723 // = 3.14159297943115234375
724 testing.expect((try a.p.to(u32)) == 3294199);
725 testing.expect((try a.q.to(u32)) == 1048576);
726
727 try a.setFloat(f64, 72.141593120712409172417410926841290461290467124);
728
729 // = 72.1415931207124145885245525278151035308837890625
730 testing.expect((try a.p.to(u128)) == 5076513310880537);
731 testing.expect((try a.q.to(u128)) == 70368744177664);
732}
733
734test "big.rational setFloatString" {
735 var a = try Rational.init(al);
736
737 try a.setFloatString("72.14159312071241458852455252781510353");
738
739 // = 72.1415931207124145885245525278151035308837890625
740 testing.expect((try a.p.to(u128)) == 7214159312071241458852455252781510353);
741 testing.expect((try a.q.to(u128)) == 100000000000000000000000000000000000);
742}
743
744test "big.rational toFloat" {
745 var a = try Rational.init(al);
746
747 // = 3.14159297943115234375
748 try a.setRatio(3294199, 1048576);
749 testing.expect((try a.toFloat(f64)) == 3.14159297943115234375);
750
751 // = 72.1415931207124145885245525278151035308837890625
752 try a.setRatio(5076513310880537, 70368744177664);
753 testing.expect((try a.toFloat(f64)) == 72.141593120712409172417410926841290461290467124);
754}
755
756test "big.rational set/to Float round-trip" {
757 var a = try Rational.init(al);
758 var prng = std.rand.DefaultPrng.init(0x5EED);
759 var i: usize = 0;
760 while (i < 512) : (i += 1) {
761 const r = prng.random.float(f64);
762 try a.setFloat(f64, r);
763 testing.expect((try a.toFloat(f64)) == r);
764 }
765}
766
767test "big.rational copy" {
768 var a = try Rational.init(al);
769
770 const b = try Int.initSet(al, 5);
771
772 try a.copyInt(b);
773 testing.expect((try a.p.to(u32)) == 5);
774 testing.expect((try a.q.to(u32)) == 1);
775
776 const c = try Int.initSet(al, 7);
777 const d = try Int.initSet(al, 3);
778
779 try a.copyRatio(c, d);
780 testing.expect((try a.p.to(u32)) == 7);
781 testing.expect((try a.q.to(u32)) == 3);
782
783 const e = try Int.initSet(al, 9);
784 const f = try Int.initSet(al, 3);
785
786 try a.copyRatio(e, f);
787 testing.expect((try a.p.to(u32)) == 3);
788 testing.expect((try a.q.to(u32)) == 1);
789}
790
791test "big.rational negate" {
792 var a = try Rational.init(al);
793
794 try a.setInt(-50);
795 testing.expect((try a.p.to(i32)) == -50);
796 testing.expect((try a.q.to(i32)) == 1);
797
798 a.negate();
799 testing.expect((try a.p.to(i32)) == 50);
800 testing.expect((try a.q.to(i32)) == 1);
801
802 a.negate();
803 testing.expect((try a.p.to(i32)) == -50);
804 testing.expect((try a.q.to(i32)) == 1);
805}
806
807test "big.rational abs" {
808 var a = try Rational.init(al);
809
810 try a.setInt(-50);
811 testing.expect((try a.p.to(i32)) == -50);
812 testing.expect((try a.q.to(i32)) == 1);
813
814 a.abs();
815 testing.expect((try a.p.to(i32)) == 50);
816 testing.expect((try a.q.to(i32)) == 1);
817
818 a.abs();
819 testing.expect((try a.p.to(i32)) == 50);
820 testing.expect((try a.q.to(i32)) == 1);
821}
822
823test "big.rational swap" {
824 var a = try Rational.init(al);
825 var b = try Rational.init(al);
826
827 try a.setRatio(50, 23);
828 try b.setRatio(17, 3);
829
830 testing.expect((try a.p.to(u32)) == 50);
831 testing.expect((try a.q.to(u32)) == 23);
832
833 testing.expect((try b.p.to(u32)) == 17);
834 testing.expect((try b.q.to(u32)) == 3);
835
836 a.swap(&b);
837
838 testing.expect((try a.p.to(u32)) == 17);
839 testing.expect((try a.q.to(u32)) == 3);
840
841 testing.expect((try b.p.to(u32)) == 50);
842 testing.expect((try b.q.to(u32)) == 23);
843}
844
845test "big.rational cmp" {
846 var a = try Rational.init(al);
847 var b = try Rational.init(al);
848
849 try a.setRatio(500, 231);
850 try b.setRatio(18903, 8584);
851 testing.expect((try a.cmp(b)) < 0);
852
853 try a.setRatio(890, 10);
854 try b.setRatio(89, 1);
855 testing.expect((try a.cmp(b)) == 0);
856}
857
858test "big.rational add single-limb" {
859 var a = try Rational.init(al);
860 var b = try Rational.init(al);
861
862 try a.setRatio(500, 231);
863 try b.setRatio(18903, 8584);
864 testing.expect((try a.cmp(b)) < 0);
865
866 try a.setRatio(890, 10);
867 try b.setRatio(89, 1);
868 testing.expect((try a.cmp(b)) == 0);
869}
870
871test "big.rational add" {
872 var a = try Rational.init(al);
873 var b = try Rational.init(al);
874 var r = try Rational.init(al);
875
876 try a.setRatio(78923, 23341);
877 try b.setRatio(123097, 12441414);
878 try a.add(a, b);
879
880 try r.setRatio(984786924199, 290395044174);
881 testing.expect((try a.cmp(r)) == 0);
882}
883
884test "big.rational sub" {
885 var a = try Rational.init(al);
886 var b = try Rational.init(al);
887 var r = try Rational.init(al);
888
889 try a.setRatio(78923, 23341);
890 try b.setRatio(123097, 12441414);
891 try a.sub(a, b);
892
893 try r.setRatio(979040510045, 290395044174);
894 testing.expect((try a.cmp(r)) == 0);
895}
896
897test "big.rational mul" {
898 var a = try Rational.init(al);
899 var b = try Rational.init(al);
900 var r = try Rational.init(al);
901
902 try a.setRatio(78923, 23341);
903 try b.setRatio(123097, 12441414);
904 try a.mul(a, b);
905
906 try r.setRatio(571481443, 17082061422);
907 testing.expect((try a.cmp(r)) == 0);
908}
909
910test "big.rational div" {
911 var a = try Rational.init(al);
912 var b = try Rational.init(al);
913 var r = try Rational.init(al);
914
915 try a.setRatio(78923, 23341);
916 try b.setRatio(123097, 12441414);
917 try a.div(a, b);
918
919 try r.setRatio(75531824394, 221015929);
920 testing.expect((try a.cmp(r)) == 0);
921}
922
923test "big.rational div" {
924 var a = try Rational.init(al);
925 var r = try Rational.init(al);
926
927 try a.setRatio(78923, 23341);
928 a.invert();
929
930 try r.setRatio(23341, 78923);
931 testing.expect((try a.cmp(r)) == 0);
932
933 try a.setRatio(-78923, 23341);
934 a.invert();
935
936 try r.setRatio(-23341, 78923);
937 testing.expect((try a.cmp(r)) == 0);
938}
std/math/cbrt.zig+10-4
...@@ -1,13 +1,19 @@...@@ -1,13 +1,19 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - cbrt(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/cbrtf.c
4// - cbrt(+-inf) = +-inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/cbrt.c
5// - cbrt(nan) = nan
66
7const std = @import("../std.zig");7const std = @import("../std.zig");
8const math = std.math;8const math = std.math;
9const expect = std.testing.expect;9const expect = std.testing.expect;
1010
11/// Returns the cube root of x.
12///
13/// Special Cases:
14/// - cbrt(+-0) = +-0
15/// - cbrt(+-inf) = +-inf
16/// - cbrt(nan) = nan
11pub fn cbrt(x: var) @typeOf(x) {17pub fn cbrt(x: var) @typeOf(x) {
12 const T = @typeOf(x);18 const T = @typeOf(x);
13 return switch (T) {19 return switch (T) {
std/math/ceil.zig+10-4
...@@ -1,14 +1,20 @@...@@ -1,14 +1,20 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - ceil(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c
4// - ceil(+-inf) = +-inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c
5// - ceil(nan) = nan
66
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../std.zig");8const std = @import("../std.zig");
9const math = std.math;9const math = std.math;
10const expect = std.testing.expect;10const expect = std.testing.expect;
1111
12/// Returns the least integer value greater than of equal to x.
13///
14/// Special Cases:
15/// - ceil(+-0) = +-0
16/// - ceil(+-inf) = +-inf
17/// - ceil(nan) = nan
12pub fn ceil(x: var) @typeOf(x) {18pub fn ceil(x: var) @typeOf(x) {
13 const T = @typeOf(x);19 const T = @typeOf(x);
14 return switch (T) {20 return switch (T) {
std/math/complex.zig+12
...@@ -23,13 +23,18 @@ pub const sqrt = @import("complex/sqrt.zig").sqrt;...@@ -23,13 +23,18 @@ pub const sqrt = @import("complex/sqrt.zig").sqrt;
23pub const tanh = @import("complex/tanh.zig").tanh;23pub const tanh = @import("complex/tanh.zig").tanh;
24pub const tan = @import("complex/tan.zig").tan;24pub const tan = @import("complex/tan.zig").tan;
2525
26/// A complex number consisting of a real an imaginary part. T must be a floating-point value.
26pub fn Complex(comptime T: type) type {27pub fn Complex(comptime T: type) type {
27 return struct {28 return struct {
28 const Self = @This();29 const Self = @This();
2930
31 /// Real part.
30 re: T,32 re: T,
33
34 /// Imaginary part.
31 im: T,35 im: T,
3236
37 /// Create a new Complex number from the given real and imaginary parts.
33 pub fn new(re: T, im: T) Self {38 pub fn new(re: T, im: T) Self {
34 return Self{39 return Self{
35 .re = re,40 .re = re,
...@@ -37,6 +42,7 @@ pub fn Complex(comptime T: type) type {...@@ -37,6 +42,7 @@ pub fn Complex(comptime T: type) type {
37 };42 };
38 }43 }
3944
45 /// Returns the sum of two complex numbers.
40 pub fn add(self: Self, other: Self) Self {46 pub fn add(self: Self, other: Self) Self {
41 return Self{47 return Self{
42 .re = self.re + other.re,48 .re = self.re + other.re,
...@@ -44,6 +50,7 @@ pub fn Complex(comptime T: type) type {...@@ -44,6 +50,7 @@ pub fn Complex(comptime T: type) type {
44 };50 };
45 }51 }
4652
53 /// Returns the subtraction of two complex numbers.
47 pub fn sub(self: Self, other: Self) Self {54 pub fn sub(self: Self, other: Self) Self {
48 return Self{55 return Self{
49 .re = self.re - other.re,56 .re = self.re - other.re,
...@@ -51,6 +58,7 @@ pub fn Complex(comptime T: type) type {...@@ -51,6 +58,7 @@ pub fn Complex(comptime T: type) type {
51 };58 };
52 }59 }
5360
61 /// Returns the product of two complex numbers.
54 pub fn mul(self: Self, other: Self) Self {62 pub fn mul(self: Self, other: Self) Self {
55 return Self{63 return Self{
56 .re = self.re * other.re - self.im * other.im,64 .re = self.re * other.re - self.im * other.im,
...@@ -58,6 +66,7 @@ pub fn Complex(comptime T: type) type {...@@ -58,6 +66,7 @@ pub fn Complex(comptime T: type) type {
58 };66 };
59 }67 }
6068
69 /// Returns the quotient of two complex numbers.
61 pub fn div(self: Self, other: Self) Self {70 pub fn div(self: Self, other: Self) Self {
62 const re_num = self.re * other.re + self.im * other.im;71 const re_num = self.re * other.re + self.im * other.im;
63 const im_num = self.im * other.re - self.re * other.im;72 const im_num = self.im * other.re - self.re * other.im;
...@@ -69,6 +78,7 @@ pub fn Complex(comptime T: type) type {...@@ -69,6 +78,7 @@ pub fn Complex(comptime T: type) type {
69 };78 };
70 }79 }
7180
81 /// Returns the complex conjugate of a number.
72 pub fn conjugate(self: Self) Self {82 pub fn conjugate(self: Self) Self {
73 return Self{83 return Self{
74 .re = self.re,84 .re = self.re,
...@@ -76,6 +86,7 @@ pub fn Complex(comptime T: type) type {...@@ -76,6 +86,7 @@ pub fn Complex(comptime T: type) type {
76 };86 };
77 }87 }
7888
89 /// Returns the reciprocal of a complex number.
79 pub fn reciprocal(self: Self) Self {90 pub fn reciprocal(self: Self) Self {
80 const m = self.re * self.re + self.im * self.im;91 const m = self.re * self.re + self.im * self.im;
81 return Self{92 return Self{
...@@ -84,6 +95,7 @@ pub fn Complex(comptime T: type) type {...@@ -84,6 +95,7 @@ pub fn Complex(comptime T: type) type {
84 };95 };
85 }96 }
8697
98 /// Returns the magnitude of a complex number.
87 pub fn magnitude(self: Self) T {99 pub fn magnitude(self: Self) T {
88 return math.sqrt(self.re * self.re + self.im * self.im);100 return math.sqrt(self.re * self.re + self.im * self.im);
89 }101 }
std/math/complex/abs.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the absolute value (modulus) of z.
7pub fn abs(z: var) @typeOf(z.re) {8pub fn abs(z: var) @typeOf(z.re) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 return math.hypot(T, z.re, z.im);10 return math.hypot(T, z.re, z.im);
std/math/complex/acos.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the arc-cosine of z.
7pub fn acos(z: var) Complex(@typeOf(z.re)) {8pub fn acos(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 const q = cmath.asin(z);10 const q = cmath.asin(z);
std/math/complex/acosh.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the hyperbolic arc-cosine of z.
7pub fn acosh(z: var) Complex(@typeOf(z.re)) {8pub fn acosh(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 const q = cmath.acos(z);10 const q = cmath.acos(z);
std/math/complex/arg.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the angular component (in radians) of z.
7pub fn arg(z: var) @typeOf(z.re) {8pub fn arg(z: var) @typeOf(z.re) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 return math.atan2(T, z.im, z.re);10 return math.atan2(T, z.im, z.re);
std/math/complex/asin.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7// Returns the arc-sine of z.
7pub fn asin(z: var) Complex(@typeOf(z.re)) {8pub fn asin(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 const x = z.re;10 const x = z.re;
std/math/complex/asinh.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the hyperbolic arc-sine of z.
7pub fn asinh(z: var) Complex(@typeOf(z.re)) {8pub fn asinh(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 const q = Complex(T).new(-z.im, z.re);10 const q = Complex(T).new(-z.im, z.re);
std/math/complex/atan.zig+7
...@@ -1,9 +1,16 @@...@@ -1,9 +1,16 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/complex/catanf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/complex/catan.c
6
1const std = @import("../../std.zig");7const std = @import("../../std.zig");
2const testing = std.testing;8const testing = std.testing;
3const math = std.math;9const math = std.math;
4const cmath = math.complex;10const cmath = math.complex;
5const Complex = cmath.Complex;11const Complex = cmath.Complex;
612
13/// Returns the arc-tangent of z.
7pub fn atan(z: var) @typeOf(z) {14pub fn atan(z: var) @typeOf(z) {
8 const T = @typeOf(z.re);15 const T = @typeOf(z.re);
9 return switch (T) {16 return switch (T) {
std/math/complex/atanh.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the hyperbolic arc-tangent of z.
7pub fn atanh(z: var) Complex(@typeOf(z.re)) {8pub fn atanh(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 const q = Complex(T).new(-z.im, z.re);10 const q = Complex(T).new(-z.im, z.re);
std/math/complex/conj.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the complex conjugate of z.
7pub fn conj(z: var) Complex(@typeOf(z.re)) {8pub fn conj(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 return Complex(T).new(z.re, -z.im);10 return Complex(T).new(z.re, -z.im);
std/math/complex/cos.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the cosine of z.
7pub fn cos(z: var) Complex(@typeOf(z.re)) {8pub fn cos(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 const p = Complex(T).new(-z.im, z.re);10 const p = Complex(T).new(-z.im, z.re);
std/math/complex/cosh.zig+7
...@@ -1,3 +1,9 @@...@@ -1,3 +1,9 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccoshf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccosh.c
6
1const std = @import("../../std.zig");7const std = @import("../../std.zig");
2const testing = std.testing;8const testing = std.testing;
3const math = std.math;9const math = std.math;
...@@ -6,6 +12,7 @@ const Complex = cmath.Complex;...@@ -6,6 +12,7 @@ const Complex = cmath.Complex;
612
7const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;13const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
814
15/// Returns the hyperbolic arc-cosine of z.
9pub fn cosh(z: var) Complex(@typeOf(z.re)) {16pub fn cosh(z: var) Complex(@typeOf(z.re)) {
10 const T = @typeOf(z.re);17 const T = @typeOf(z.re);
11 return switch (T) {18 return switch (T) {
std/math/complex/exp.zig+7
...@@ -1,3 +1,9 @@...@@ -1,3 +1,9 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexpf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexp.c
6
1const std = @import("../../std.zig");7const std = @import("../../std.zig");
2const testing = std.testing;8const testing = std.testing;
3const math = std.math;9const math = std.math;
...@@ -6,6 +12,7 @@ const Complex = cmath.Complex;...@@ -6,6 +12,7 @@ const Complex = cmath.Complex;
612
7const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;13const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
814
15/// Returns e raised to the power of z (e^z).
9pub fn exp(z: var) @typeOf(z) {16pub fn exp(z: var) @typeOf(z) {
10 const T = @typeOf(z.re);17 const T = @typeOf(z.re);
1118
std/math/complex/ldexp.zig+7
...@@ -1,9 +1,16 @@...@@ -1,9 +1,16 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/complex/__cexpf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/complex/__cexp.c
6
1const std = @import("../../std.zig");7const std = @import("../../std.zig");
2const debug = std.debug;8const debug = std.debug;
3const math = std.math;9const math = std.math;
4const cmath = math.complex;10const cmath = math.complex;
5const Complex = cmath.Complex;11const Complex = cmath.Complex;
612
13/// Returns exp(z) scaled to avoid overflow.
7pub fn ldexp_cexp(z: var, expt: i32) @typeOf(z) {14pub fn ldexp_cexp(z: var, expt: i32) @typeOf(z) {
8 const T = @typeOf(z.re);15 const T = @typeOf(z.re);
916
std/math/complex/log.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the natural logarithm of z.
7pub fn log(z: var) Complex(@typeOf(z.re)) {8pub fn log(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 const r = cmath.abs(z);10 const r = cmath.abs(z);
std/math/complex/pow.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns z raised to the complex power of c.
7pub fn pow(comptime T: type, z: T, c: T) T {8pub fn pow(comptime T: type, z: T, c: T) T {
8 const p = cmath.log(z);9 const p = cmath.log(z);
9 const q = c.mul(p);10 const q = c.mul(p);
std/math/complex/proj.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the projection of z onto the riemann sphere.
7pub fn proj(z: var) Complex(@typeOf(z.re)) {8pub fn proj(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
910
std/math/complex/sin.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the sine of z.
7pub fn sin(z: var) Complex(@typeOf(z.re)) {8pub fn sin(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 const p = Complex(T).new(-z.im, z.re);10 const p = Complex(T).new(-z.im, z.re);
std/math/complex/sinh.zig+7
...@@ -1,3 +1,9 @@...@@ -1,3 +1,9 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinhf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinh.c
6
1const std = @import("../../std.zig");7const std = @import("../../std.zig");
2const testing = std.testing;8const testing = std.testing;
3const math = std.math;9const math = std.math;
...@@ -6,6 +12,7 @@ const Complex = cmath.Complex;...@@ -6,6 +12,7 @@ const Complex = cmath.Complex;
612
7const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;13const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
814
15/// Returns the hyperbolic sine of z.
9pub fn sinh(z: var) @typeOf(z) {16pub fn sinh(z: var) @typeOf(z) {
10 const T = @typeOf(z.re);17 const T = @typeOf(z.re);
11 return switch (T) {18 return switch (T) {
std/math/complex/sqrt.zig+8
...@@ -1,9 +1,17 @@...@@ -1,9 +1,17 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/complex/csqrtf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/complex/csqrt.c
6
1const std = @import("../../std.zig");7const std = @import("../../std.zig");
2const testing = std.testing;8const testing = std.testing;
3const math = std.math;9const math = std.math;
4const cmath = math.complex;10const cmath = math.complex;
5const Complex = cmath.Complex;11const Complex = cmath.Complex;
612
13/// Returns the square root of z. The real and imaginary parts of the result have the same sign
14/// as the imaginary part of z.
7pub fn sqrt(z: var) @typeOf(z) {15pub fn sqrt(z: var) @typeOf(z) {
8 const T = @typeOf(z.re);16 const T = @typeOf(z.re);
917
std/math/complex/tan.zig+1
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
66
7/// Returns the tanget of z.
7pub fn tan(z: var) Complex(@typeOf(z.re)) {8pub fn tan(z: var) Complex(@typeOf(z.re)) {
8 const T = @typeOf(z.re);9 const T = @typeOf(z.re);
9 const q = Complex(T).new(-z.im, z.re);10 const q = Complex(T).new(-z.im, z.re);
std/math/complex/tanh.zig+7
...@@ -1,9 +1,16 @@...@@ -1,9 +1,16 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanhf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanh.c
6
1const std = @import("../../std.zig");7const std = @import("../../std.zig");
2const testing = std.testing;8const testing = std.testing;
3const math = std.math;9const math = std.math;
4const cmath = math.complex;10const cmath = math.complex;
5const Complex = cmath.Complex;11const Complex = cmath.Complex;
612
13/// Returns the hyperbolic tangent of z.
7pub fn tanh(z: var) @typeOf(z) {14pub fn tanh(z: var) @typeOf(z) {
8 const T = @typeOf(z.re);15 const T = @typeOf(z.re);
9 return switch (T) {16 return switch (T) {
std/math/copysign.zig+7
...@@ -1,8 +1,15 @@...@@ -1,8 +1,15 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/math/copysignf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/math/copysign.c
6
1const std = @import("../std.zig");7const std = @import("../std.zig");
2const math = std.math;8const math = std.math;
3const expect = std.testing.expect;9const expect = std.testing.expect;
4const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
511
12/// Returns a value with the magnitude of x and the sign of y.
6pub fn copysign(comptime T: type, x: T, y: T) T {13pub fn copysign(comptime T: type, x: T, y: T) T {
7 return switch (T) {14 return switch (T) {
8 f16 => copysign16(x, y),15 f16 => copysign16(x, y),
std/math/cos.zig+46-100
...@@ -1,18 +1,23 @@...@@ -1,18 +1,23 @@
1// Special Cases:1// Ported from go, which is licensed under a BSD-3 license.
2// https://golang.org/LICENSE
2//3//
3// - cos(+-inf) = nan4// https://golang.org/src/math/sin.go
4// - cos(nan) = nan
55
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const std = @import("../std.zig");7const std = @import("../std.zig");
8const math = std.math;8const math = std.math;
9const expect = std.testing.expect;9const expect = std.testing.expect;
1010
11/// Returns the cosine of the radian value x.
12///
13/// Special Cases:
14/// - cos(+-inf) = nan
15/// - cos(nan) = nan
11pub fn cos(x: var) @typeOf(x) {16pub fn cos(x: var) @typeOf(x) {
12 const T = @typeOf(x);17 const T = @typeOf(x);
13 return switch (T) {18 return switch (T) {
14 f32 => cos32(x),19 f32 => cos_(f32, x),
15 f64 => cos64(x),20 f64 => cos_(f64, x),
16 else => @compileError("cos not implemented for " ++ @typeName(T)),21 else => @compileError("cos not implemented for " ++ @typeName(T)),
17 };22 };
18}23}
...@@ -33,78 +38,24 @@ const C3 = 2.48015872888517045348E-5;...@@ -33,78 +38,24 @@ const C3 = 2.48015872888517045348E-5;
33const C4 = -1.38888888888730564116E-3;38const C4 = -1.38888888888730564116E-3;
34const C5 = 4.16666666666665929218E-2;39const C5 = 4.16666666666665929218E-2;
3540
36// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.41const pi4a = 7.85398125648498535156e-1;
37//42const pi4b = 3.77489470793079817668E-8;
38// This may have slight differences on some edge cases and may need to replaced if so.43const pi4c = 2.69515142907905952645E-15;
39fn cos32(x_: f32) f32 {44const m4pi = 1.273239544735162542821171882678754627704620361328125;
40 const pi4a = 7.85398125648498535156e-1;
41 const pi4b = 3.77489470793079817668E-8;
42 const pi4c = 2.69515142907905952645E-15;
43 const m4pi = 1.273239544735162542821171882678754627704620361328125;
44
45 var x = x_;
46 if (math.isNan(x) or math.isInf(x)) {
47 return math.nan(f32);
48 }
49
50 var sign = false;
51 if (x < 0) {
52 x = -x;
53 }
54
55 var y = math.floor(x * m4pi);
56 var j = @floatToInt(i64, y);
5745
58 if (j & 1 == 1) {46fn cos_(comptime T: type, x_: T) T {
59 j += 1;47 const I = @IntType(true, T.bit_count);
60 y += 1;
61 }
62
63 j &= 7;
64 if (j > 3) {
65 j -= 4;
66 sign = !sign;
67 }
68 if (j > 1) {
69 sign = !sign;
70 }
71
72 const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
73 const w = z * z;
74
75 const r = r: {
76 if (j == 1 or j == 2) {
77 break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
78 } else {
79 break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
80 }
81 };
82
83 if (sign) {
84 return -r;
85 } else {
86 return r;
87 }
88}
89
90fn cos64(x_: f64) f64 {
91 const pi4a = 7.85398125648498535156e-1;
92 const pi4b = 3.77489470793079817668E-8;
93 const pi4c = 2.69515142907905952645E-15;
94 const m4pi = 1.273239544735162542821171882678754627704620361328125;
9548
96 var x = x_;49 var x = x_;
97 if (math.isNan(x) or math.isInf(x)) {50 if (math.isNan(x) or math.isInf(x)) {
98 return math.nan(f64);51 return math.nan(T);
99 }52 }
10053
101 var sign = false;54 var sign = false;
102 if (x < 0) {55 x = math.fabs(x);
103 x = -x;
104 }
10556
106 var y = math.floor(x * m4pi);57 var y = math.floor(x * m4pi);
107 var j = @floatToInt(i64, y);58 var j = @floatToInt(I, y);
10859
109 if (j & 1 == 1) {60 if (j & 1 == 1) {
110 j += 1;61 j += 1;
...@@ -123,56 +74,51 @@ fn cos64(x_: f64) f64 {...@@ -123,56 +74,51 @@ fn cos64(x_: f64) f64 {
123 const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;74 const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
124 const w = z * z;75 const w = z * z;
12576
126 const r = r: {77 const r = if (j == 1 or j == 2)
127 if (j == 1 or j == 2) {78 z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))))
128 break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));79 else
129 } else {80 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
130 break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
131 }
132 };
13381
134 if (sign) {82 return if (sign) -r else r;
135 return -r;
136 } else {
137 return r;
138 }
139}83}
14084
141test "math.cos" {85test "math.cos" {
142 expect(cos(f32(0.0)) == cos32(0.0));86 expect(cos(f32(0.0)) == cos_(f32, 0.0));
143 expect(cos(f64(0.0)) == cos64(0.0));87 expect(cos(f64(0.0)) == cos_(f64, 0.0));
144}88}
14589
146test "math.cos32" {90test "math.cos32" {
147 const epsilon = 0.000001;91 const epsilon = 0.000001;
14892
149 expect(math.approxEq(f32, cos32(0.0), 1.0, epsilon));93 expect(math.approxEq(f32, cos_(f32, 0.0), 1.0, epsilon));
150 expect(math.approxEq(f32, cos32(0.2), 0.980067, epsilon));94 expect(math.approxEq(f32, cos_(f32, 0.2), 0.980067, epsilon));
151 expect(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon));95 expect(math.approxEq(f32, cos_(f32, 0.8923), 0.627623, epsilon));
152 expect(math.approxEq(f32, cos32(1.5), 0.070737, epsilon));96 expect(math.approxEq(f32, cos_(f32, 1.5), 0.070737, epsilon));
153 expect(math.approxEq(f32, cos32(37.45), 0.969132, epsilon));97 expect(math.approxEq(f32, cos_(f32, -1.5), 0.070737, epsilon));
154 expect(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));98 expect(math.approxEq(f32, cos_(f32, 37.45), 0.969132, epsilon));
99 expect(math.approxEq(f32, cos_(f32, 89.123), 0.400798, epsilon));
155}100}
156101
157test "math.cos64" {102test "math.cos64" {
158 const epsilon = 0.000001;103 const epsilon = 0.000001;
159104
160 expect(math.approxEq(f64, cos64(0.0), 1.0, epsilon));105 expect(math.approxEq(f64, cos_(f64, 0.0), 1.0, epsilon));
161 expect(math.approxEq(f64, cos64(0.2), 0.980067, epsilon));106 expect(math.approxEq(f64, cos_(f64, 0.2), 0.980067, epsilon));
162 expect(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon));107 expect(math.approxEq(f64, cos_(f64, 0.8923), 0.627623, epsilon));
163 expect(math.approxEq(f64, cos64(1.5), 0.070737, epsilon));108 expect(math.approxEq(f64, cos_(f64, 1.5), 0.070737, epsilon));
164 expect(math.approxEq(f64, cos64(37.45), 0.969132, epsilon));109 expect(math.approxEq(f64, cos_(f64, -1.5), 0.070737, epsilon));
165 expect(math.approxEq(f64, cos64(89.123), 0.40080, epsilon));110 expect(math.approxEq(f64, cos_(f64, 37.45), 0.969132, epsilon));
111 expect(math.approxEq(f64, cos_(f64, 89.123), 0.40080, epsilon));
166}112}
167113
168test "math.cos32.special" {114test "math.cos32.special" {
169 expect(math.isNan(cos32(math.inf(f32))));115 expect(math.isNan(cos_(f32, math.inf(f32))));
170 expect(math.isNan(cos32(-math.inf(f32))));116 expect(math.isNan(cos_(f32, -math.inf(f32))));
171 expect(math.isNan(cos32(math.nan(f32))));117 expect(math.isNan(cos_(f32, math.nan(f32))));
172}118}
173119
174test "math.cos64.special" {120test "math.cos64.special" {
175 expect(math.isNan(cos64(math.inf(f64))));121 expect(math.isNan(cos_(f64, math.inf(f64))));
176 expect(math.isNan(cos64(-math.inf(f64))));122 expect(math.isNan(cos_(f64, -math.inf(f64))));
177 expect(math.isNan(cos64(math.nan(f64))));123 expect(math.isNan(cos_(f64, math.nan(f64))));
178}124}
std/math/cosh.zig+10-4
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - cosh(+-0) = 14// https://git.musl-libc.org/cgit/musl/tree/src/math/coshf.c
4// - cosh(+-inf) = +inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/cosh.c
5// - cosh(nan) = nan
66
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../std.zig");8const std = @import("../std.zig");
...@@ -11,6 +11,12 @@ const expo2 = @import("expo2.zig").expo2;...@@ -11,6 +11,12 @@ const expo2 = @import("expo2.zig").expo2;
11const expect = std.testing.expect;11const expect = std.testing.expect;
12const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
1313
14/// Returns the hyperbolic cosine of x.
15///
16/// Special Cases:
17/// - cosh(+-0) = 1
18/// - cosh(+-inf) = +inf
19/// - cosh(nan) = nan
14pub fn cosh(x: var) @typeOf(x) {20pub fn cosh(x: var) @typeOf(x) {
15 const T = @typeOf(x);21 const T = @typeOf(x);
16 return switch (T) {22 return switch (T) {
std/math/exp.zig+9-3
...@@ -1,13 +1,19 @@...@@ -1,13 +1,19 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - exp(+inf) = +inf4// https://git.musl-libc.org/cgit/musl/tree/src/math/expf.c
4// - exp(nan) = nan5// https://git.musl-libc.org/cgit/musl/tree/src/math/exp.c
56
6const std = @import("../std.zig");7const std = @import("../std.zig");
7const math = std.math;8const math = std.math;
8const assert = std.debug.assert;9const assert = std.debug.assert;
9const builtin = @import("builtin");10const builtin = @import("builtin");
1011
12/// Returns e raised to the power of x (e^x).
13///
14/// Special Cases:
15/// - exp(+inf) = +inf
16/// - exp(nan) = nan
11pub fn exp(x: var) @typeOf(x) {17pub fn exp(x: var) @typeOf(x) {
12 const T = @typeOf(x);18 const T = @typeOf(x);
13 return switch (T) {19 return switch (T) {
std/math/exp2.zig+9-3
...@@ -1,12 +1,18 @@...@@ -1,12 +1,18 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - exp2(+inf) = +inf4// https://git.musl-libc.org/cgit/musl/tree/src/math/exp2f.c
4// - exp2(nan) = nan5// https://git.musl-libc.org/cgit/musl/tree/src/math/exp2.c
56
6const std = @import("../std.zig");7const std = @import("../std.zig");
7const math = std.math;8const math = std.math;
8const expect = std.testing.expect;9const expect = std.testing.expect;
910
11/// Returns 2 raised to the power of x (2^x).
12///
13/// Special Cases:
14/// - exp2(+inf) = +inf
15/// - exp2(nan) = nan
10pub fn exp2(x: var) @typeOf(x) {16pub fn exp2(x: var) @typeOf(x) {
11 const T = @typeOf(x);17 const T = @typeOf(x);
12 return switch (T) {18 return switch (T) {
std/math/expm1.zig+13-4
...@@ -1,14 +1,23 @@...@@ -1,14 +1,23 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - expm1(+inf) = +inf4// https://git.musl-libc.org/cgit/musl/tree/src/math/expmf.c
4// - expm1(-inf) = -15// https://git.musl-libc.org/cgit/musl/tree/src/math/expm.c
5// - expm1(nan) = nan6
7// TODO: Updated recently.
68
7const builtin = @import("builtin");9const builtin = @import("builtin");
8const std = @import("../std.zig");10const std = @import("../std.zig");
9const math = std.math;11const math = std.math;
10const expect = std.testing.expect;12const expect = std.testing.expect;
1113
14/// Returns e raised to the power of x, minus 1 (e^x - 1). This is more accurate than exp(e, x) - 1
15/// when x is near 0.
16///
17/// Special Cases:
18/// - expm1(+inf) = +inf
19/// - expm1(-inf) = -1
20/// - expm1(nan) = nan
12pub fn expm1(x: var) @typeOf(x) {21pub fn expm1(x: var) @typeOf(x) {
13 const T = @typeOf(x);22 const T = @typeOf(x);
14 return switch (T) {23 return switch (T) {
std/math/expo2.zig+7
...@@ -1,5 +1,12 @@...@@ -1,5 +1,12 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/math/__expo2f.c
5// https://git.musl-libc.org/cgit/musl/tree/src/math/__expo2.c
6
1const math = @import("../math.zig");7const math = @import("../math.zig");
28
9/// Returns exp(x) / 2 for x >= log(maxFloat(T)).
3pub fn expo2(x: var) @typeOf(x) {10pub fn expo2(x: var) @typeOf(x) {
4 const T = @typeOf(x);11 const T = @typeOf(x);
5 return switch (T) {12 return switch (T) {
std/math/fabs.zig+9-3
...@@ -1,13 +1,19 @@...@@ -1,13 +1,19 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - fabs(+-inf) = +inf4// https://git.musl-libc.org/cgit/musl/tree/src/math/fabsf.c
4// - fabs(nan) = nan5// https://git.musl-libc.org/cgit/musl/tree/src/math/fabs.c
56
6const std = @import("../std.zig");7const std = @import("../std.zig");
7const math = std.math;8const math = std.math;
8const expect = std.testing.expect;9const expect = std.testing.expect;
9const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
1011
12/// Returns the absolute value of x.
13///
14/// Special Cases:
15/// - fabs(+-inf) = +inf
16/// - fabs(nan) = nan
11pub fn fabs(x: var) @typeOf(x) {17pub fn fabs(x: var) @typeOf(x) {
12 const T = @typeOf(x);18 const T = @typeOf(x);
13 return switch (T) {19 return switch (T) {
std/math/floor.zig+10-4
...@@ -1,14 +1,20 @@...@@ -1,14 +1,20 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - floor(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c
4// - floor(+-inf) = +-inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c
5// - floor(nan) = nan
66
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const expect = std.testing.expect;8const expect = std.testing.expect;
9const std = @import("../std.zig");9const std = @import("../std.zig");
10const math = std.math;10const math = std.math;
1111
12/// Returns the greatest integer value less than or equal to x.
13///
14/// Special Cases:
15/// - floor(+-0) = +-0
16/// - floor(+-inf) = +-inf
17/// - floor(nan) = nan
12pub fn floor(x: var) @typeOf(x) {18pub fn floor(x: var) @typeOf(x) {
13 const T = @typeOf(x);19 const T = @typeOf(x);
14 return switch (T) {20 return switch (T) {
std/math/fma.zig+9-1
...@@ -1,7 +1,14 @@...@@ -1,7 +1,14 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/math/fmaf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/math/fma.c
6
1const std = @import("../std.zig");7const std = @import("../std.zig");
2const math = std.math;8const math = std.math;
3const expect = std.testing.expect;9const expect = std.testing.expect;
410
11/// Returns x * y + z with a single rounding error.
5pub fn fma(comptime T: type, x: T, y: T, z: T) T {12pub fn fma(comptime T: type, x: T, y: T, z: T) T {
6 return switch (T) {13 return switch (T) {
7 f32 => fma32(x, y, z),14 f32 => fma32(x, y, z),
...@@ -16,7 +23,7 @@ fn fma32(x: f32, y: f32, z: f32) f32 {...@@ -16,7 +23,7 @@ fn fma32(x: f32, y: f32, z: f32) f32 {
16 const u = @bitCast(u64, xy_z);23 const u = @bitCast(u64, xy_z);
17 const e = (u >> 52) & 0x7FF;24 const e = (u >> 52) & 0x7FF;
1825
19 if ((u & 0x1FFFFFFF) != 0x10000000 or e == 0x7FF or xy_z - xy == z) {26 if ((u & 0x1FFFFFFF) != 0x10000000 or e == 0x7FF or (xy_z - xy == z and xy_z - z == xy)) {
20 return @floatCast(f32, xy_z);27 return @floatCast(f32, xy_z);
21 } else {28 } else {
22 // TODO: Handle inexact case with double-rounding29 // TODO: Handle inexact case with double-rounding
...@@ -24,6 +31,7 @@ fn fma32(x: f32, y: f32, z: f32) f32 {...@@ -24,6 +31,7 @@ fn fma32(x: f32, y: f32, z: f32) f32 {
24 }31 }
25}32}
2633
34// NOTE: Upstream fma.c has been rewritten completely to raise fp exceptions more accurately.
27fn fma64(x: f64, y: f64, z: f64) f64 {35fn fma64(x: f64, y: f64, z: f64) f64 {
28 if (!math.isFinite(x) or !math.isFinite(y)) {36 if (!math.isFinite(x) or !math.isFinite(y)) {
29 return x * y + z;37 return x * y + z;
std/math/frexp.zig+11-4
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - frexp(+-0) = +-0, 04// https://git.musl-libc.org/cgit/musl/tree/src/math/frexpf.c
4// - frexp(+-inf) = +-inf, 05// https://git.musl-libc.org/cgit/musl/tree/src/math/frexp.c
5// - frexp(nan) = nan, undefined
66
7const std = @import("../std.zig");7const std = @import("../std.zig");
8const math = std.math;8const math = std.math;
...@@ -17,6 +17,13 @@ fn frexp_result(comptime T: type) type {...@@ -17,6 +17,13 @@ fn frexp_result(comptime T: type) type {
17pub const frexp32_result = frexp_result(f32);17pub const frexp32_result = frexp_result(f32);
18pub const frexp64_result = frexp_result(f64);18pub const frexp64_result = frexp_result(f64);
1919
20/// Breaks x into a normalized fraction and an integral power of two.
21/// f == frac * 2^exp, with |frac| in the interval [0.5, 1).
22///
23/// Special Cases:
24/// - frexp(+-0) = +-0, 0
25/// - frexp(+-inf) = +-inf, 0
26/// - frexp(nan) = nan, undefined
20pub fn frexp(x: var) frexp_result(@typeOf(x)) {27pub fn frexp(x: var) frexp_result(@typeOf(x)) {
21 const T = @typeOf(x);28 const T = @typeOf(x);
22 return switch (T) {29 return switch (T) {
std/math/hypot.zig+11-5
...@@ -1,15 +1,21 @@...@@ -1,15 +1,21 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - hypot(+-inf, y) = +inf4// https://git.musl-libc.org/cgit/musl/tree/src/math/hypotf.c
4// - hypot(x, +-inf) = +inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/hypot.c
5// - hypot(nan, y) = nan
6// - hypot(x, nan) = nan
76
8const std = @import("../std.zig");7const std = @import("../std.zig");
9const math = std.math;8const math = std.math;
10const expect = std.testing.expect;9const expect = std.testing.expect;
11const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
1211
12/// Returns sqrt(x * x + y * y), avoiding unncessary overflow and underflow.
13///
14/// Special Cases:
15/// - hypot(+-inf, y) = +inf
16/// - hypot(x, +-inf) = +inf
17/// - hypot(nan, y) = nan
18/// - hypot(x, nan) = nan
13pub fn hypot(comptime T: type, x: T, y: T) T {19pub fn hypot(comptime T: type, x: T, y: T) T {
14 return switch (T) {20 return switch (T) {
15 f32 => hypot32(x, y),21 f32 => hypot32(x, y),
std/math/ilogb.zig+10-4
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - ilogb(+-inf) = maxInt(i32)4// https://git.musl-libc.org/cgit/musl/tree/src/math/ilogbf.c
4// - ilogb(0) = maxInt(i32)5// https://git.musl-libc.org/cgit/musl/tree/src/math/ilogb.c
5// - ilogb(nan) = maxInt(i32)
66
7const std = @import("../std.zig");7const std = @import("../std.zig");
8const math = std.math;8const math = std.math;
...@@ -10,6 +10,12 @@ const expect = std.testing.expect;...@@ -10,6 +10,12 @@ const expect = std.testing.expect;
10const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
11const minInt = std.math.minInt;11const minInt = std.math.minInt;
1212
13/// Returns the binary exponent of x as an integer.
14///
15/// Special Cases:
16/// - ilogb(+-inf) = maxInt(i32)
17/// - ilogb(0) = maxInt(i32)
18/// - ilogb(nan) = maxInt(i32)
13pub fn ilogb(x: var) i32 {19pub fn ilogb(x: var) i32 {
14 const T = @typeOf(x);20 const T = @typeOf(x);
15 return switch (T) {21 return switch (T) {
std/math/inf.zig+1
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const math = std.math;2const math = std.math;
33
4/// Returns value inf for the type T.
4pub fn inf(comptime T: type) T {5pub fn inf(comptime T: type) T {
5 return switch (T) {6 return switch (T) {
6 f16 => math.inf_f16,7 f16 => math.inf_f16,
std/math/isfinite.zig+1
...@@ -3,6 +3,7 @@ const math = std.math;...@@ -3,6 +3,7 @@ const math = std.math;
3const expect = std.testing.expect;3const expect = std.testing.expect;
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
55
6/// Returns whether x is a finite value.
6pub fn isFinite(x: var) bool {7pub fn isFinite(x: var) bool {
7 const T = @typeOf(x);8 const T = @typeOf(x);
8 switch (T) {9 switch (T) {
std/math/isinf.zig+3
...@@ -3,6 +3,7 @@ const math = std.math;...@@ -3,6 +3,7 @@ const math = std.math;
3const expect = std.testing.expect;3const expect = std.testing.expect;
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
55
6/// Returns whether x is an infinity, ignoring sign.
6pub fn isInf(x: var) bool {7pub fn isInf(x: var) bool {
7 const T = @typeOf(x);8 const T = @typeOf(x);
8 switch (T) {9 switch (T) {
...@@ -28,6 +29,7 @@ pub fn isInf(x: var) bool {...@@ -28,6 +29,7 @@ pub fn isInf(x: var) bool {
28 }29 }
29}30}
3031
32/// Returns whether x is an infinity with a positive sign.
31pub fn isPositiveInf(x: var) bool {33pub fn isPositiveInf(x: var) bool {
32 const T = @typeOf(x);34 const T = @typeOf(x);
33 switch (T) {35 switch (T) {
...@@ -49,6 +51,7 @@ pub fn isPositiveInf(x: var) bool {...@@ -49,6 +51,7 @@ pub fn isPositiveInf(x: var) bool {
49 }51 }
50}52}
5153
54/// Returns whether x is an infinity with a negative sign.
52pub fn isNegativeInf(x: var) bool {55pub fn isNegativeInf(x: var) bool {
53 const T = @typeOf(x);56 const T = @typeOf(x);
54 switch (T) {57 switch (T) {
std/math/isnan.zig+4-2
...@@ -3,13 +3,15 @@ const math = std.math;...@@ -3,13 +3,15 @@ const math = std.math;
3const expect = std.testing.expect;3const expect = std.testing.expect;
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
55
6/// Returns whether x is a nan.
6pub fn isNan(x: var) bool {7pub fn isNan(x: var) bool {
7 return x != x;8 return x != x;
8}9}
910
10/// Note: A signalling nan is identical to a standard nan right now but may have a different bit11/// Returns whether x is a signalling nan.
11/// representation in the future when required.
12pub fn isSignalNan(x: var) bool {12pub fn isSignalNan(x: var) bool {
13 // Note: A signalling nan is identical to a standard nan right now but may have a different bit
14 // representation in the future when required.
13 return isNan(x);15 return isNan(x);
14}16}
1517
std/math/isnormal.zig+1
...@@ -3,6 +3,7 @@ const math = std.math;...@@ -3,6 +3,7 @@ const math = std.math;
3const expect = std.testing.expect;3const expect = std.testing.expect;
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
55
6// Returns whether x has a normalized representation (i.e. integer part of mantissa is 1).
6pub fn isNormal(x: var) bool {7pub fn isNormal(x: var) bool {
7 const T = @typeOf(x);8 const T = @typeOf(x);
8 switch (T) {9 switch (T) {
std/math/ln.zig+11-5
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - ln(+inf) = +inf4// https://git.musl-libc.org/cgit/musl/tree/src/math/lnf.c
4// - ln(0) = -inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/ln.c
5// - ln(x) = nan if x < 0
6// - ln(nan) = nan
76
8const std = @import("../std.zig");7const std = @import("../std.zig");
9const math = std.math;8const math = std.math;
...@@ -11,6 +10,13 @@ const expect = std.testing.expect;...@@ -11,6 +10,13 @@ const expect = std.testing.expect;
11const builtin = @import("builtin");10const builtin = @import("builtin");
12const TypeId = builtin.TypeId;11const TypeId = builtin.TypeId;
1312
13/// Returns the natural logarithm of x.
14///
15/// Special Cases:
16/// - ln(+inf) = +inf
17/// - ln(0) = -inf
18/// - ln(x) = nan if x < 0
19/// - ln(nan) = nan
14pub fn ln(x: var) @typeOf(x) {20pub fn ln(x: var) @typeOf(x) {
15 const T = @typeOf(x);21 const T = @typeOf(x);
16 switch (@typeId(T)) {22 switch (@typeId(T)) {
std/math/log.zig+7
...@@ -1,9 +1,16 @@...@@ -1,9 +1,16 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/math/logf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/math/log.c
6
1const std = @import("../std.zig");7const std = @import("../std.zig");
2const math = std.math;8const math = std.math;
3const builtin = @import("builtin");9const builtin = @import("builtin");
4const TypeId = builtin.TypeId;10const TypeId = builtin.TypeId;
5const expect = std.testing.expect;11const expect = std.testing.expect;
612
13/// Returns the logarithm of x for the provided base.
7pub fn log(comptime T: type, base: T, x: T) T {14pub fn log(comptime T: type, base: T, x: T) T {
8 if (base == 2) {15 if (base == 2) {
9 return math.log2(x);16 return math.log2(x);
std/math/log10.zig+11-5
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - log10(+inf) = +inf4// https://git.musl-libc.org/cgit/musl/tree/src/math/log10f.c
4// - log10(0) = -inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/log10.c
5// - log10(x) = nan if x < 0
6// - log10(nan) = nan
76
8const std = @import("../std.zig");7const std = @import("../std.zig");
9const math = std.math;8const math = std.math;
...@@ -12,6 +11,13 @@ const builtin = @import("builtin");...@@ -12,6 +11,13 @@ const builtin = @import("builtin");
12const TypeId = builtin.TypeId;11const TypeId = builtin.TypeId;
13const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
1413
14/// Returns the base-10 logarithm of x.
15///
16/// Special Cases:
17/// - log10(+inf) = +inf
18/// - log10(0) = -inf
19/// - log10(x) = nan if x < 0
20/// - log10(nan) = nan
15pub fn log10(x: var) @typeOf(x) {21pub fn log10(x: var) @typeOf(x) {
16 const T = @typeOf(x);22 const T = @typeOf(x);
17 switch (@typeId(T)) {23 switch (@typeId(T)) {
std/math/log1p.zig+12-6
...@@ -1,16 +1,22 @@...@@ -1,16 +1,22 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - log1p(+inf) = +inf4// https://git.musl-libc.org/cgit/musl/tree/src/math/log1pf.c
4// - log1p(+-0) = +-05// https://git.musl-libc.org/cgit/musl/tree/src/math/log1p.c
5// - log1p(-1) = -inf
6// - log1p(x) = nan if x < -1
7// - log1p(nan) = nan
86
9const builtin = @import("builtin");7const builtin = @import("builtin");
10const std = @import("../std.zig");8const std = @import("../std.zig");
11const math = std.math;9const math = std.math;
12const expect = std.testing.expect;10const expect = std.testing.expect;
1311
12/// Returns the natural logarithm of 1 + x with greater accuracy when x is near zero.
13///
14/// Special Cases:
15/// - log1p(+inf) = +inf
16/// - log1p(+-0) = +-0
17/// - log1p(-1) = -inf
18/// - log1p(x) = nan if x < -1
19/// - log1p(nan) = nan
14pub fn log1p(x: var) @typeOf(x) {20pub fn log1p(x: var) @typeOf(x) {
15 const T = @typeOf(x);21 const T = @typeOf(x);
16 return switch (T) {22 return switch (T) {
std/math/log2.zig+11-5
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - log2(+inf) = +inf4// https://git.musl-libc.org/cgit/musl/tree/src/math/log2f.c
4// - log2(0) = -inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/log2.c
5// - log2(x) = nan if x < 0
6// - log2(nan) = nan
76
8const std = @import("../std.zig");7const std = @import("../std.zig");
9const math = std.math;8const math = std.math;
...@@ -12,6 +11,13 @@ const builtin = @import("builtin");...@@ -12,6 +11,13 @@ const builtin = @import("builtin");
12const TypeId = builtin.TypeId;11const TypeId = builtin.TypeId;
13const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
1413
14/// Returns the base-2 logarithm of x.
15///
16/// Special Cases:
17/// - log2(+inf) = +inf
18/// - log2(0) = -inf
19/// - log2(x) = nan if x < 0
20/// - log2(nan) = nan
15pub fn log2(x: var) @typeOf(x) {21pub fn log2(x: var) @typeOf(x) {
16 const T = @typeOf(x);22 const T = @typeOf(x);
17 switch (@typeId(T)) {23 switch (@typeId(T)) {
std/math/modf.zig+10-3
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - modf(+-inf) = +-inf, nan4// https://git.musl-libc.org/cgit/musl/tree/src/math/modff.c
4// - modf(nan) = nan, nan5// https://git.musl-libc.org/cgit/musl/tree/src/math/modf.c
56
6const std = @import("../std.zig");7const std = @import("../std.zig");
7const math = std.math;8const math = std.math;
...@@ -17,6 +18,12 @@ fn modf_result(comptime T: type) type {...@@ -17,6 +18,12 @@ fn modf_result(comptime T: type) type {
17pub const modf32_result = modf_result(f32);18pub const modf32_result = modf_result(f32);
18pub const modf64_result = modf_result(f64);19pub const modf64_result = modf_result(f64);
1920
21/// Returns the integer and fractional floating-point numbers that sum to x. The sign of each
22/// result is the same as the sign of x.
23///
24/// Special Cases:
25/// - modf(+-inf) = +-inf, nan
26/// - modf(nan) = nan, nan
20pub fn modf(x: var) modf_result(@typeOf(x)) {27pub fn modf(x: var) modf_result(@typeOf(x)) {
21 const T = @typeOf(x);28 const T = @typeOf(x);
22 return switch (T) {29 return switch (T) {
std/math/nan.zig+4-2
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const math = @import("../math.zig");1const math = @import("../math.zig");
22
3/// Returns the nan representation for type T.
3pub fn nan(comptime T: type) T {4pub fn nan(comptime T: type) T {
4 return switch (T) {5 return switch (T) {
5 f16 => math.nan_f16,6 f16 => math.nan_f16,
...@@ -10,9 +11,10 @@ pub fn nan(comptime T: type) T {...@@ -10,9 +11,10 @@ pub fn nan(comptime T: type) T {
10 };11 };
11}12}
1213
13// Note: A signalling nan is identical to a standard right now by may have a different bit14/// Returns the signalling nan representation for type T.
14// representation in the future when required.
15pub fn snan(comptime T: type) T {15pub fn snan(comptime T: type) T {
16 // Note: A signalling nan is identical to a standard right now by may have a different bit
17 // representation in the future when required.
16 return switch (T) {18 return switch (T) {
17 f16 => @bitCast(f16, math.nan_u16),19 f16 => @bitCast(f16, math.nan_u16),
18 f32 => @bitCast(f32, math.nan_u32),20 f32 => @bitCast(f32, math.nan_u32),
std/math/pow.zig+57-39
...@@ -1,32 +1,36 @@...@@ -1,32 +1,36 @@
1// Special Cases:1// Ported from go, which is licensed under a BSD-3 license.
2// https://golang.org/LICENSE
2//3//
3// pow(x, +-0) = 1 for any x4// https://golang.org/src/math/pow.go
4// pow(1, y) = 1 for any y
5// pow(x, 1) = x for any x
6// pow(nan, y) = nan
7// pow(x, nan) = nan
8// pow(+-0, y) = +-inf for y an odd integer < 0
9// pow(+-0, -inf) = +inf
10// pow(+-0, +inf) = +0
11// pow(+-0, y) = +inf for finite y < 0 and not an odd integer
12// pow(+-0, y) = +-0 for y an odd integer > 0
13// pow(+-0, y) = +0 for finite y > 0 and not an odd integer
14// pow(-1, +-inf) = 1
15// pow(x, +inf) = +inf for |x| > 1
16// pow(x, -inf) = +0 for |x| > 1
17// pow(x, +inf) = +0 for |x| < 1
18// pow(x, -inf) = +inf for |x| < 1
19// pow(+inf, y) = +inf for y > 0
20// pow(+inf, y) = +0 for y < 0
21// pow(-inf, y) = pow(-0, -y)
22// pow(x, y) = nan for finite x < 0 and finite non-integer y
235
24const builtin = @import("builtin");6const builtin = @import("builtin");
25const std = @import("../std.zig");7const std = @import("../std.zig");
26const math = std.math;8const math = std.math;
27const expect = std.testing.expect;9const expect = std.testing.expect;
2810
29// This implementation is taken from the go stlib, musl is a bit more complex.11/// Returns x raised to the power of y (x^y).
12///
13/// Special Cases:
14/// - pow(x, +-0) = 1 for any x
15/// - pow(1, y) = 1 for any y
16/// - pow(x, 1) = x for any x
17/// - pow(nan, y) = nan
18/// - pow(x, nan) = nan
19/// - pow(+-0, y) = +-inf for y an odd integer < 0
20/// - pow(+-0, -inf) = +inf
21/// - pow(+-0, +inf) = +0
22/// - pow(+-0, y) = +inf for finite y < 0 and not an odd integer
23/// - pow(+-0, y) = +-0 for y an odd integer > 0
24/// - pow(+-0, y) = +0 for finite y > 0 and not an odd integer
25/// - pow(-1, +-inf) = 1
26/// - pow(x, +inf) = +inf for |x| > 1
27/// - pow(x, -inf) = +0 for |x| > 1
28/// - pow(x, +inf) = +0 for |x| < 1
29/// - pow(x, -inf) = +inf for |x| < 1
30/// - pow(+inf, y) = +inf for y > 0
31/// - pow(+inf, y) = +0 for y < 0
32/// - pow(-inf, y) = pow(-0, -y)
33/// - pow(x, y) = nan for finite x < 0 and finite non-integer y
30pub fn pow(comptime T: type, x: T, y: T) T {34pub fn pow(comptime T: type, x: T, y: T) T {
31 if (@typeInfo(T) == builtin.TypeId.Int) {35 if (@typeInfo(T) == builtin.TypeId.Int) {
32 return math.powi(T, x, y) catch unreachable;36 return math.powi(T, x, y) catch unreachable;
...@@ -53,15 +57,6 @@ pub fn pow(comptime T: type, x: T, y: T) T {...@@ -53,15 +57,6 @@ pub fn pow(comptime T: type, x: T, y: T) T {
53 return x;57 return x;
54 }58 }
5559
56 // special case sqrt
57 if (y == 0.5) {
58 return math.sqrt(x);
59 }
60
61 if (y == -0.5) {
62 return 1 / math.sqrt(x);
63 }
64
65 if (x == 0) {60 if (x == 0) {
66 if (y < 0) {61 if (y < 0) {
67 // pow(+-0, y) = +- 0 for y an odd integer62 // pow(+-0, y) = +- 0 for y an odd integer
...@@ -112,14 +107,16 @@ pub fn pow(comptime T: type, x: T, y: T) T {...@@ -112,14 +107,16 @@ pub fn pow(comptime T: type, x: T, y: T) T {
112 }107 }
113 }108 }
114109
115 var ay = y;110 // special case sqrt
116 var flip = false;111 if (y == 0.5) {
117 if (ay < 0) {112 return math.sqrt(x);
118 ay = -ay;113 }
119 flip = true;114
115 if (y == -0.5) {
116 return 1 / math.sqrt(x);
120 }117 }
121118
122 const r1 = math.modf(ay);119 const r1 = math.modf(math.fabs(y));
123 var yi = r1.ipart;120 var yi = r1.ipart;
124 var yf = r1.fpart;121 var yf = r1.fpart;
125122
...@@ -148,8 +145,18 @@ pub fn pow(comptime T: type, x: T, y: T) T {...@@ -148,8 +145,18 @@ pub fn pow(comptime T: type, x: T, y: T) T {
148 var xe = r2.exponent;145 var xe = r2.exponent;
149 var x1 = r2.significand;146 var x1 = r2.significand;
150147
151 var i = @floatToInt(i32, yi);148 var i = @floatToInt(@IntType(true, T.bit_count), yi);
152 while (i != 0) : (i >>= 1) {149 while (i != 0) : (i >>= 1) {
150 const overflow_shift = math.floatExponentBits(T) + 1;
151 if (xe < -(1 << overflow_shift) or (1 << overflow_shift) < xe) {
152 // catch xe before it overflows the left shift below
153 // Since i != 0 it has at least one bit still set, so ae will accumulate xe
154 // on at least one more iteration, ae += xe is a lower bound on ae
155 // the lower bound on ae exceeds the size of a float exp
156 // so the final call to Ldexp will produce under/overflow (0/Inf)
157 ae += xe;
158 break;
159 }
153 if (i & 1 == 1) {160 if (i & 1 == 1) {
154 a1 *= x1;161 a1 *= x1;
155 ae += xe;162 ae += xe;
...@@ -163,7 +170,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {...@@ -163,7 +170,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
163 }170 }
164171
165 // a *= a1 * 2^ae172 // a *= a1 * 2^ae
166 if (flip) {173 if (y < 0) {
167 a1 = 1 / a1;174 a1 = 1 / a1;
168 ae = -ae;175 ae = -ae;
169 }176 }
...@@ -202,6 +209,9 @@ test "math.pow.special" {...@@ -202,6 +209,9 @@ test "math.pow.special" {
202 expect(pow(f32, 45, 1.0) == 45);209 expect(pow(f32, 45, 1.0) == 45);
203 expect(pow(f32, -45, 1.0) == -45);210 expect(pow(f32, -45, 1.0) == -45);
204 expect(math.isNan(pow(f32, math.nan(f32), 5.0)));211 expect(math.isNan(pow(f32, math.nan(f32), 5.0)));
212 expect(math.isPositiveInf(pow(f32, -math.inf(f32), 0.5)));
213 expect(math.isPositiveInf(pow(f32, -0, -0.5)));
214 expect(pow(f32, -0, 0.5) == 0);
205 expect(math.isNan(pow(f32, 5.0, math.nan(f32))));215 expect(math.isNan(pow(f32, 5.0, math.nan(f32))));
206 expect(math.isPositiveInf(pow(f32, 0.0, -1.0)));216 expect(math.isPositiveInf(pow(f32, 0.0, -1.0)));
207 //expect(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?217 //expect(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?
...@@ -232,3 +242,11 @@ test "math.pow.special" {...@@ -232,3 +242,11 @@ test "math.pow.special" {
232 expect(math.isNan(pow(f32, -1.0, 1.2)));242 expect(math.isNan(pow(f32, -1.0, 1.2)));
233 expect(math.isNan(pow(f32, -12.4, 78.5)));243 expect(math.isNan(pow(f32, -12.4, 78.5)));
234}244}
245
246test "math.pow.overflow" {
247 expect(math.isPositiveInf(pow(f64, 2, 1 << 32)));
248 expect(pow(f64, 2, -(1 << 32)) == 0);
249 expect(math.isNegativeInf(pow(f64, -2, (1 << 32) + 1)));
250 expect(pow(f64, 0.5, 1 << 45) == 0);
251 expect(math.isPositiveInf(pow(f64, 0.5, -(1 << 45))));
252}
std/math/powi.zig+13-9
...@@ -1,12 +1,7 @@...@@ -1,12 +1,7 @@
1// Special Cases:1// Based on Rust, which is licensed under the MIT license.
2// https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/LICENSE-MIT
2//3//
3// powi(x, +-0) = 1 for any x4// https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/src/libcore/num/mod.rs#L3423
4// powi(0, y) = 0 for any y
5// powi(1, y) = 1 for any y
6// powi(-1, y) = -1 for for y an odd integer
7// powi(-1, y) = 1 for for y an even integer
8// powi(x, y) = Overflow for for y >= @sizeOf(x) - 1 y > 0
9// powi(x, y) = Underflow for for y > @sizeOf(x) - 1 y < 0
105
11const builtin = @import("builtin");6const builtin = @import("builtin");
12const std = @import("../std.zig");7const std = @import("../std.zig");
...@@ -14,7 +9,16 @@ const math = std.math;...@@ -14,7 +9,16 @@ const math = std.math;
14const assert = std.debug.assert;9const assert = std.debug.assert;
15const testing = std.testing;10const testing = std.testing;
1611
17// This implementation is based on that from the rust stlib12/// Returns the power of x raised by the integer y (x^y).
13///
14/// Special Cases:
15/// - powi(x, +-0) = 1 for any x
16/// - powi(0, y) = 0 for any y
17/// - powi(1, y) = 1 for any y
18/// - powi(-1, y) = -1 for y an odd integer
19/// - powi(-1, y) = 1 for y an even integer
20/// - powi(x, y) = Overflow for y >= @sizeOf(x) - 1 or y > 0
21/// - powi(x, y) = Underflow for y > @sizeOf(x) - 1 or y < 0
18pub fn powi(comptime T: type, x: T, y: T) (error{22pub fn powi(comptime T: type, x: T, y: T) (error{
19 Overflow,23 Overflow,
20 Underflow,24 Underflow,
std/math/round.zig+10-4
...@@ -1,14 +1,20 @@...@@ -1,14 +1,20 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - round(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/roundf.c
4// - round(+-inf) = +-inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/round.c
5// - round(nan) = nan
66
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const expect = std.testing.expect;8const expect = std.testing.expect;
9const std = @import("../std.zig");9const std = @import("../std.zig");
10const math = std.math;10const math = std.math;
1111
12/// Returns x rounded to the nearest integer, rounding half away from zero.
13///
14/// Special Cases:
15/// - round(+-0) = +-0
16/// - round(+-inf) = +-inf
17/// - round(nan) = nan
12pub fn round(x: var) @typeOf(x) {18pub fn round(x: var) @typeOf(x) {
13 const T = @typeOf(x);19 const T = @typeOf(x);
14 return switch (T) {20 return switch (T) {
std/math/scalbn.zig+7
...@@ -1,7 +1,14 @@...@@ -1,7 +1,14 @@
1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
3//
4// https://git.musl-libc.org/cgit/musl/tree/src/math/scalbnf.c
5// https://git.musl-libc.org/cgit/musl/tree/src/math/scalbn.c
6
1const std = @import("../std.zig");7const std = @import("../std.zig");
2const math = std.math;8const math = std.math;
3const expect = std.testing.expect;9const expect = std.testing.expect;
410
11/// Returns x * 2^n.
5pub fn scalbn(x: var, n: i32) @typeOf(x) {12pub fn scalbn(x: var, n: i32) @typeOf(x) {
6 const T = @typeOf(x);13 const T = @typeOf(x);
7 return switch (T) {14 return switch (T) {
std/math/signbit.zig+1
...@@ -2,6 +2,7 @@ const std = @import("../std.zig");...@@ -2,6 +2,7 @@ const std = @import("../std.zig");
2const math = std.math;2const math = std.math;
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5/// Returns whether x is negative or negative 0.
5pub fn signbit(x: var) bool {6pub fn signbit(x: var) bool {
6 const T = @typeOf(x);7 const T = @typeOf(x);
7 return switch (T) {8 return switch (T) {
std/math/sin.zig+52-108
...@@ -1,19 +1,24 @@...@@ -1,19 +1,24 @@
1// Special Cases:1// Ported from go, which is licensed under a BSD-3 license.
2// https://golang.org/LICENSE
2//3//
3// - sin(+-0) = +-04// https://golang.org/src/math/sin.go
4// - sin(+-inf) = nan
5// - sin(nan) = nan
65
7const builtin = @import("builtin");6const builtin = @import("builtin");
8const std = @import("../std.zig");7const std = @import("../std.zig");
9const math = std.math;8const math = std.math;
10const expect = std.testing.expect;9const expect = std.testing.expect;
1110
11/// Returns the sine of the radian value x.
12///
13/// Special Cases:
14/// - sin(+-0) = +-0
15/// - sin(+-inf) = nan
16/// - sin(nan) = nan
12pub fn sin(x: var) @typeOf(x) {17pub fn sin(x: var) @typeOf(x) {
13 const T = @typeOf(x);18 const T = @typeOf(x);
14 return switch (T) {19 return switch (T) {
15 f32 => sin32(x),20 f32 => sin_(T, x),
16 f64 => sin64(x),21 f64 => sin_(T, x),
17 else => @compileError("sin not implemented for " ++ @typeName(T)),22 else => @compileError("sin not implemented for " ++ @typeName(T)),
18 };23 };
19}24}
...@@ -34,83 +39,27 @@ const C3 = 2.48015872888517045348E-5;...@@ -34,83 +39,27 @@ const C3 = 2.48015872888517045348E-5;
34const C4 = -1.38888888888730564116E-3;39const C4 = -1.38888888888730564116E-3;
35const C5 = 4.16666666666665929218E-2;40const C5 = 4.16666666666665929218E-2;
3641
37// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.42const pi4a = 7.85398125648498535156e-1;
38//43const pi4b = 3.77489470793079817668E-8;
39// This may have slight differences on some edge cases and may need to replaced if so.44const pi4c = 2.69515142907905952645E-15;
40fn sin32(x_: f32) f32 {45const m4pi = 1.273239544735162542821171882678754627704620361328125;
41 const pi4a = 7.85398125648498535156e-1;
42 const pi4b = 3.77489470793079817668E-8;
43 const pi4c = 2.69515142907905952645E-15;
44 const m4pi = 1.273239544735162542821171882678754627704620361328125;
45
46 var x = x_;
47 if (x == 0 or math.isNan(x)) {
48 return x;
49 }
50 if (math.isInf(x)) {
51 return math.nan(f32);
52 }
53
54 var sign = false;
55 if (x < 0) {
56 x = -x;
57 sign = true;
58 }
59
60 var y = math.floor(x * m4pi);
61 var j = @floatToInt(i64, y);
62
63 if (j & 1 == 1) {
64 j += 1;
65 y += 1;
66 }
6746
68 j &= 7;47fn sin_(comptime T: type, x_: T) T {
69 if (j > 3) {48 const I = @IntType(true, T.bit_count);
70 j -= 4;
71 sign = !sign;
72 }
73
74 const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
75 const w = z * z;
76
77 const r = r: {
78 if (j == 1 or j == 2) {
79 break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
80 } else {
81 break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
82 }
83 };
84
85 if (sign) {
86 return -r;
87 } else {
88 return r;
89 }
90}
91
92fn sin64(x_: f64) f64 {
93 const pi4a = 7.85398125648498535156e-1;
94 const pi4b = 3.77489470793079817668E-8;
95 const pi4c = 2.69515142907905952645E-15;
96 const m4pi = 1.273239544735162542821171882678754627704620361328125;
9749
98 var x = x_;50 var x = x_;
99 if (x == 0 or math.isNan(x)) {51 if (x == 0 or math.isNan(x)) {
100 return x;52 return x;
101 }53 }
102 if (math.isInf(x)) {54 if (math.isInf(x)) {
103 return math.nan(f64);55 return math.nan(T);
104 }56 }
10557
106 var sign = false;58 var sign = x < 0;
107 if (x < 0) {59 x = math.fabs(x);
108 x = -x;
109 sign = true;
110 }
11160
112 var y = math.floor(x * m4pi);61 var y = math.floor(x * m4pi);
113 var j = @floatToInt(i64, y);62 var j = @floatToInt(I, y);
11463
115 if (j & 1 == 1) {64 if (j & 1 == 1) {
116 j += 1;65 j += 1;
...@@ -126,61 +75,56 @@ fn sin64(x_: f64) f64 {...@@ -126,61 +75,56 @@ fn sin64(x_: f64) f64 {
126 const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;75 const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
127 const w = z * z;76 const w = z * z;
12877
129 const r = r: {78 const r = if (j == 1 or j == 2)
130 if (j == 1 or j == 2) {79 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))))
131 break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));80 else
132 } else {81 z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
133 break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
134 }
135 };
13682
137 if (sign) {83 return if (sign) -r else r;
138 return -r;
139 } else {
140 return r;
141 }
142}84}
14385
144test "math.sin" {86test "math.sin" {
145 expect(sin(f32(0.0)) == sin32(0.0));87 expect(sin(f32(0.0)) == sin_(f32, 0.0));
146 expect(sin(f64(0.0)) == sin64(0.0));88 expect(sin(f64(0.0)) == sin_(f64, 0.0));
147 expect(comptime (math.sin(f64(2))) == math.sin(f64(2)));89 expect(comptime (math.sin(f64(2))) == math.sin(f64(2)));
148}90}
14991
150test "math.sin32" {92test "math.sin32" {
151 const epsilon = 0.000001;93 const epsilon = 0.000001;
15294
153 expect(math.approxEq(f32, sin32(0.0), 0.0, epsilon));95 expect(math.approxEq(f32, sin_(f32, 0.0), 0.0, epsilon));
154 expect(math.approxEq(f32, sin32(0.2), 0.198669, epsilon));96 expect(math.approxEq(f32, sin_(f32, 0.2), 0.198669, epsilon));
155 expect(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon));97 expect(math.approxEq(f32, sin_(f32, 0.8923), 0.778517, epsilon));
156 expect(math.approxEq(f32, sin32(1.5), 0.997495, epsilon));98 expect(math.approxEq(f32, sin_(f32, 1.5), 0.997495, epsilon));
157 expect(math.approxEq(f32, sin32(37.45), -0.246544, epsilon));99 expect(math.approxEq(f32, sin_(f32, -1.5), -0.997495, epsilon));
158 expect(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));100 expect(math.approxEq(f32, sin_(f32, 37.45), -0.246544, epsilon));
101 expect(math.approxEq(f32, sin_(f32, 89.123), 0.916166, epsilon));
159}102}
160103
161test "math.sin64" {104test "math.sin64" {
162 const epsilon = 0.000001;105 const epsilon = 0.000001;
163106
164 expect(math.approxEq(f64, sin64(0.0), 0.0, epsilon));107 expect(math.approxEq(f64, sin_(f64, 0.0), 0.0, epsilon));
165 expect(math.approxEq(f64, sin64(0.2), 0.198669, epsilon));108 expect(math.approxEq(f64, sin_(f64, 0.2), 0.198669, epsilon));
166 expect(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon));109 expect(math.approxEq(f64, sin_(f64, 0.8923), 0.778517, epsilon));
167 expect(math.approxEq(f64, sin64(1.5), 0.997495, epsilon));110 expect(math.approxEq(f64, sin_(f64, 1.5), 0.997495, epsilon));
168 expect(math.approxEq(f64, sin64(37.45), -0.246543, epsilon));111 expect(math.approxEq(f64, sin_(f64, -1.5), -0.997495, epsilon));
169 expect(math.approxEq(f64, sin64(89.123), 0.916166, epsilon));112 expect(math.approxEq(f64, sin_(f64, 37.45), -0.246543, epsilon));
113 expect(math.approxEq(f64, sin_(f64, 89.123), 0.916166, epsilon));
170}114}
171115
172test "math.sin32.special" {116test "math.sin32.special" {
173 expect(sin32(0.0) == 0.0);117 expect(sin_(f32, 0.0) == 0.0);
174 expect(sin32(-0.0) == -0.0);118 expect(sin_(f32, -0.0) == -0.0);
175 expect(math.isNan(sin32(math.inf(f32))));119 expect(math.isNan(sin_(f32, math.inf(f32))));
176 expect(math.isNan(sin32(-math.inf(f32))));120 expect(math.isNan(sin_(f32, -math.inf(f32))));
177 expect(math.isNan(sin32(math.nan(f32))));121 expect(math.isNan(sin_(f32, math.nan(f32))));
178}122}
179123
180test "math.sin64.special" {124test "math.sin64.special" {
181 expect(sin64(0.0) == 0.0);125 expect(sin_(f64, 0.0) == 0.0);
182 expect(sin64(-0.0) == -0.0);126 expect(sin_(f64, -0.0) == -0.0);
183 expect(math.isNan(sin64(math.inf(f64))));127 expect(math.isNan(sin_(f64, math.inf(f64))));
184 expect(math.isNan(sin64(-math.inf(f64))));128 expect(math.isNan(sin_(f64, -math.inf(f64))));
185 expect(math.isNan(sin64(math.nan(f64))));129 expect(math.isNan(sin_(f64, math.nan(f64))));
186}130}
std/math/sinh.zig+10-4
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - sinh(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/sinhf.c
4// - sinh(+-inf) = +-inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/sinh.c
5// - sinh(nan) = nan
66
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../std.zig");8const std = @import("../std.zig");
...@@ -11,6 +11,12 @@ const expect = std.testing.expect;...@@ -11,6 +11,12 @@ const expect = std.testing.expect;
11const expo2 = @import("expo2.zig").expo2;11const expo2 = @import("expo2.zig").expo2;
12const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
1313
14/// Returns the hyperbolic sine of x.
15///
16/// Special Cases:
17/// - sinh(+-0) = +-0
18/// - sinh(+-inf) = +-inf
19/// - sinh(nan) = nan
14pub fn sinh(x: var) @typeOf(x) {20pub fn sinh(x: var) @typeOf(x) {
15 const T = @typeOf(x);21 const T = @typeOf(x);
16 return switch (T) {22 return switch (T) {
std/math/sqrt.zig+7-7
...@@ -1,10 +1,3 @@...@@ -1,10 +1,3 @@
1// Special Cases:
2//
3// - sqrt(+inf) = +inf
4// - sqrt(+-0) = +-0
5// - sqrt(x) = nan if x < 0
6// - sqrt(nan) = nan
7
8const std = @import("../std.zig");1const std = @import("../std.zig");
9const math = std.math;2const math = std.math;
10const expect = std.testing.expect;3const expect = std.testing.expect;
...@@ -12,6 +5,13 @@ const builtin = @import("builtin");...@@ -12,6 +5,13 @@ const builtin = @import("builtin");
12const TypeId = builtin.TypeId;5const TypeId = builtin.TypeId;
13const maxInt = std.math.maxInt;6const maxInt = std.math.maxInt;
147
8/// Returns the square root of x.
9///
10/// Special Cases:
11/// - sqrt(+inf) = +inf
12/// - sqrt(+-0) = +-0
13/// - sqrt(x) = nan if x < 0
14/// - sqrt(nan) = nan
15pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) {15pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) {
16 const T = @typeOf(x);16 const T = @typeOf(x);
17 switch (@typeId(T)) {17 switch (@typeId(T)) {
std/math/tan.zig+50-104
...@@ -1,19 +1,24 @@...@@ -1,19 +1,24 @@
1// Special Cases:1// Ported from go, which is licensed under a BSD-3 license.
2// https://golang.org/LICENSE
2//3//
3// - tan(+-0) = +-04// https://golang.org/src/math/tan.go
4// - tan(+-inf) = nan
5// - tan(nan) = nan
65
7const builtin = @import("builtin");6const builtin = @import("builtin");
8const std = @import("../std.zig");7const std = @import("../std.zig");
9const math = std.math;8const math = std.math;
10const expect = std.testing.expect;9const expect = std.testing.expect;
1110
11/// Returns the tangent of the radian value x.
12///
13/// Special Cases:
14/// - tan(+-0) = +-0
15/// - tan(+-inf) = nan
16/// - tan(nan) = nan
12pub fn tan(x: var) @typeOf(x) {17pub fn tan(x: var) @typeOf(x) {
13 const T = @typeOf(x);18 const T = @typeOf(x);
14 return switch (T) {19 return switch (T) {
15 f32 => tan32(x),20 f32 => tan_(f32, x),
16 f64 => tan64(x),21 f64 => tan_(f64, x),
17 else => @compileError("tan not implemented for " ++ @typeName(T)),22 else => @compileError("tan not implemented for " ++ @typeName(T)),
18 };23 };
19}24}
...@@ -27,80 +32,27 @@ const Tq2 = -1.32089234440210967447E6;...@@ -27,80 +32,27 @@ const Tq2 = -1.32089234440210967447E6;
27const Tq3 = 2.50083801823357915839E7;32const Tq3 = 2.50083801823357915839E7;
28const Tq4 = -5.38695755929454629881E7;33const Tq4 = -5.38695755929454629881E7;
2934
30// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.35const pi4a = 7.85398125648498535156e-1;
31//36const pi4b = 3.77489470793079817668E-8;
32// This may have slight differences on some edge cases and may need to replaced if so.37const pi4c = 2.69515142907905952645E-15;
33fn tan32(x_: f32) f32 {38const m4pi = 1.273239544735162542821171882678754627704620361328125;
34 const pi4a = 7.85398125648498535156e-1;
35 const pi4b = 3.77489470793079817668E-8;
36 const pi4c = 2.69515142907905952645E-15;
37 const m4pi = 1.273239544735162542821171882678754627704620361328125;
38
39 var x = x_;
40 if (x == 0 or math.isNan(x)) {
41 return x;
42 }
43 if (math.isInf(x)) {
44 return math.nan(f32);
45 }
46
47 var sign = false;
48 if (x < 0) {
49 x = -x;
50 sign = true;
51 }
52
53 var y = math.floor(x * m4pi);
54 var j = @floatToInt(i64, y);
55
56 if (j & 1 == 1) {
57 j += 1;
58 y += 1;
59 }
60
61 const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
62 const w = z * z;
63
64 var r = r: {
65 if (w > 1e-14) {
66 break :r z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4));
67 } else {
68 break :r z;
69 }
70 };
71
72 if (j & 2 == 2) {
73 r = -1 / r;
74 }
75 if (sign) {
76 r = -r;
77 }
78
79 return r;
80}
8139
82fn tan64(x_: f64) f64 {40fn tan_(comptime T: type, x_: T) T {
83 const pi4a = 7.85398125648498535156e-1;41 const I = @IntType(true, T.bit_count);
84 const pi4b = 3.77489470793079817668E-8;
85 const pi4c = 2.69515142907905952645E-15;
86 const m4pi = 1.273239544735162542821171882678754627704620361328125;
8742
88 var x = x_;43 var x = x_;
89 if (x == 0 or math.isNan(x)) {44 if (x == 0 or math.isNan(x)) {
90 return x;45 return x;
91 }46 }
92 if (math.isInf(x)) {47 if (math.isInf(x)) {
93 return math.nan(f64);48 return math.nan(T);
94 }49 }
9550
96 var sign = false;51 var sign = x < 0;
97 if (x < 0) {52 x = math.fabs(x);
98 x = -x;
99 sign = true;
100 }
10153
102 var y = math.floor(x * m4pi);54 var y = math.floor(x * m4pi);
103 var j = @floatToInt(i64, y);55 var j = @floatToInt(I, y);
10456
105 if (j & 1 == 1) {57 if (j & 1 == 1) {
106 j += 1;58 j += 1;
...@@ -110,63 +62,57 @@ fn tan64(x_: f64) f64 {...@@ -110,63 +62,57 @@ fn tan64(x_: f64) f64 {
110 const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;62 const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
111 const w = z * z;63 const w = z * z;
11264
113 var r = r: {65 var r = if (w > 1e-14)
114 if (w > 1e-14) {66 z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4))
115 break :r z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4));67 else
116 } else {68 z;
117 break :r z;
118 }
119 };
12069
121 if (j & 2 == 2) {70 if (j & 2 == 2) {
122 r = -1 / r;71 r = -1 / r;
123 }72 }
124 if (sign) {
125 r = -r;
126 }
12773
128 return r;74 return if (sign) -r else r;
129}75}
13076
131test "math.tan" {77test "math.tan" {
132 expect(tan(f32(0.0)) == tan32(0.0));78 expect(tan(f32(0.0)) == tan_(f32, 0.0));
133 expect(tan(f64(0.0)) == tan64(0.0));79 expect(tan(f64(0.0)) == tan_(f64, 0.0));
134}80}
13581
136test "math.tan32" {82test "math.tan32" {
137 const epsilon = 0.000001;83 const epsilon = 0.000001;
13884
139 expect(math.approxEq(f32, tan32(0.0), 0.0, epsilon));85 expect(math.approxEq(f32, tan_(f32, 0.0), 0.0, epsilon));
140 expect(math.approxEq(f32, tan32(0.2), 0.202710, epsilon));86 expect(math.approxEq(f32, tan_(f32, 0.2), 0.202710, epsilon));
141 expect(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon));87 expect(math.approxEq(f32, tan_(f32, 0.8923), 1.240422, epsilon));
142 expect(math.approxEq(f32, tan32(1.5), 14.101420, epsilon));88 expect(math.approxEq(f32, tan_(f32, 1.5), 14.101420, epsilon));
143 expect(math.approxEq(f32, tan32(37.45), -0.254397, epsilon));89 expect(math.approxEq(f32, tan_(f32, 37.45), -0.254397, epsilon));
144 expect(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));90 expect(math.approxEq(f32, tan_(f32, 89.123), 2.285852, epsilon));
145}91}
14692
147test "math.tan64" {93test "math.tan64" {
148 const epsilon = 0.000001;94 const epsilon = 0.000001;
14995
150 expect(math.approxEq(f64, tan64(0.0), 0.0, epsilon));96 expect(math.approxEq(f64, tan_(f64, 0.0), 0.0, epsilon));
151 expect(math.approxEq(f64, tan64(0.2), 0.202710, epsilon));97 expect(math.approxEq(f64, tan_(f64, 0.2), 0.202710, epsilon));
152 expect(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon));98 expect(math.approxEq(f64, tan_(f64, 0.8923), 1.240422, epsilon));
153 expect(math.approxEq(f64, tan64(1.5), 14.101420, epsilon));99 expect(math.approxEq(f64, tan_(f64, 1.5), 14.101420, epsilon));
154 expect(math.approxEq(f64, tan64(37.45), -0.254397, epsilon));100 expect(math.approxEq(f64, tan_(f64, 37.45), -0.254397, epsilon));
155 expect(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon));101 expect(math.approxEq(f64, tan_(f64, 89.123), 2.2858376, epsilon));
156}102}
157103
158test "math.tan32.special" {104test "math.tan32.special" {
159 expect(tan32(0.0) == 0.0);105 expect(tan_(f32, 0.0) == 0.0);
160 expect(tan32(-0.0) == -0.0);106 expect(tan_(f32, -0.0) == -0.0);
161 expect(math.isNan(tan32(math.inf(f32))));107 expect(math.isNan(tan_(f32, math.inf(f32))));
162 expect(math.isNan(tan32(-math.inf(f32))));108 expect(math.isNan(tan_(f32, -math.inf(f32))));
163 expect(math.isNan(tan32(math.nan(f32))));109 expect(math.isNan(tan_(f32, math.nan(f32))));
164}110}
165111
166test "math.tan64.special" {112test "math.tan64.special" {
167 expect(tan64(0.0) == 0.0);113 expect(tan_(f64, 0.0) == 0.0);
168 expect(tan64(-0.0) == -0.0);114 expect(tan_(f64, -0.0) == -0.0);
169 expect(math.isNan(tan64(math.inf(f64))));115 expect(math.isNan(tan_(f64, math.inf(f64))));
170 expect(math.isNan(tan64(-math.inf(f64))));116 expect(math.isNan(tan_(f64, -math.inf(f64))));
171 expect(math.isNan(tan64(math.nan(f64))));117 expect(math.isNan(tan_(f64, math.nan(f64))));
172}118}
std/math/tanh.zig+10-4
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - sinh(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/tanhf.c
4// - sinh(+-inf) = +-15// https://git.musl-libc.org/cgit/musl/tree/src/math/tanh.c
5// - sinh(nan) = nan
66
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../std.zig");8const std = @import("../std.zig");
...@@ -11,6 +11,12 @@ const expect = std.testing.expect;...@@ -11,6 +11,12 @@ const expect = std.testing.expect;
11const expo2 = @import("expo2.zig").expo2;11const expo2 = @import("expo2.zig").expo2;
12const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
1313
14/// Returns the hyperbolic tangent of x.
15///
16/// Special Cases:
17/// - sinh(+-0) = +-0
18/// - sinh(+-inf) = +-1
19/// - sinh(nan) = nan
14pub fn tanh(x: var) @typeOf(x) {20pub fn tanh(x: var) @typeOf(x) {
15 const T = @typeOf(x);21 const T = @typeOf(x);
16 return switch (T) {22 return switch (T) {
std/math/trunc.zig+10-4
...@@ -1,14 +1,20 @@...@@ -1,14 +1,20 @@
1// Special Cases:1// Ported from musl, which is licensed under the MIT license:
2// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
2//3//
3// - trunc(+-0) = +-04// https://git.musl-libc.org/cgit/musl/tree/src/math/truncf.c
4// - trunc(+-inf) = +-inf5// https://git.musl-libc.org/cgit/musl/tree/src/math/trunc.c
5// - trunc(nan) = nan
66
7const std = @import("../std.zig");7const std = @import("../std.zig");
8const math = std.math;8const math = std.math;
9const expect = std.testing.expect;9const expect = std.testing.expect;
10const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
1111
12/// Returns the integer value of x.
13///
14/// Special Cases:
15/// - trunc(+-0) = +-0
16/// - trunc(+-inf) = +-inf
17/// - trunc(nan) = nan
12pub fn trunc(x: var) @typeOf(x) {18pub fn trunc(x: var) @typeOf(x) {
13 const T = @typeOf(x);19 const T = @typeOf(x);
14 return switch (T) {20 return switch (T) {
std/mem.zig+23-29
...@@ -34,39 +34,39 @@ pub const Allocator = struct {...@@ -34,39 +34,39 @@ pub const Allocator = struct {
34 /// The returned slice must have its pointer aligned at least to `new_alignment` bytes.34 /// The returned slice must have its pointer aligned at least to `new_alignment` bytes.
35 reallocFn: fn (35 reallocFn: fn (
36 self: *Allocator,36 self: *Allocator,
37 // Guaranteed to be the same as what was returned from most recent call to37 /// Guaranteed to be the same as what was returned from most recent call to
38 // `reallocFn` or `shrinkFn`.38 /// `reallocFn` or `shrinkFn`.
39 // If `old_mem.len == 0` then this is a new allocation and `new_byte_count`39 /// If `old_mem.len == 0` then this is a new allocation and `new_byte_count`
40 // is guaranteed to be >= 1.40 /// is guaranteed to be >= 1.
41 old_mem: []u8,41 old_mem: []u8,
42 // If `old_mem.len == 0` then this is `undefined`, otherwise:42 /// If `old_mem.len == 0` then this is `undefined`, otherwise:
43 // Guaranteed to be the same as what was returned from most recent call to43 /// Guaranteed to be the same as what was returned from most recent call to
44 // `reallocFn` or `shrinkFn`.44 /// `reallocFn` or `shrinkFn`.
45 // Guaranteed to be >= 1.45 /// Guaranteed to be >= 1.
46 // Guaranteed to be a power of 2.46 /// Guaranteed to be a power of 2.
47 old_alignment: u29,47 old_alignment: u29,
48 // If `new_byte_count` is 0 then this is a free and it is guaranteed that48 /// If `new_byte_count` is 0 then this is a free and it is guaranteed that
49 // `old_mem.len != 0`.49 /// `old_mem.len != 0`.
50 new_byte_count: usize,50 new_byte_count: usize,
51 // Guaranteed to be >= 1.51 /// Guaranteed to be >= 1.
52 // Guaranteed to be a power of 2.52 /// Guaranteed to be a power of 2.
53 // Returned slice's pointer must have this alignment.53 /// Returned slice's pointer must have this alignment.
54 new_alignment: u29,54 new_alignment: u29,
55 ) Error![]u8,55 ) Error![]u8,
5656
57 /// This function deallocates memory. It must succeed.57 /// This function deallocates memory. It must succeed.
58 shrinkFn: fn (58 shrinkFn: fn (
59 self: *Allocator,59 self: *Allocator,
60 // Guaranteed to be the same as what was returned from most recent call to60 /// Guaranteed to be the same as what was returned from most recent call to
61 // `reallocFn` or `shrinkFn`.61 /// `reallocFn` or `shrinkFn`.
62 old_mem: []u8,62 old_mem: []u8,
63 // Guaranteed to be the same as what was returned from most recent call to63 /// Guaranteed to be the same as what was returned from most recent call to
64 // `reallocFn` or `shrinkFn`.64 /// `reallocFn` or `shrinkFn`.
65 old_alignment: u29,65 old_alignment: u29,
66 // Guaranteed to be less than or equal to `old_mem.len`.66 /// Guaranteed to be less than or equal to `old_mem.len`.
67 new_byte_count: usize,67 new_byte_count: usize,
68 // If `new_byte_count == 0` then this is `undefined`, otherwise:68 /// If `new_byte_count == 0` then this is `undefined`, otherwise:
69 // Guaranteed to be less than or equal to `old_alignment`.69 /// Guaranteed to be less than or equal to `old_alignment`.
70 new_alignment: u29,70 new_alignment: u29,
71 ) []u8,71 ) []u8,
7272
...@@ -104,10 +104,7 @@ pub const Allocator = struct {...@@ -104,10 +104,7 @@ pub const Allocator = struct {
104 const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;104 const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;
105 const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, alignment);105 const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, alignment);
106 assert(byte_slice.len == byte_count);106 assert(byte_slice.len == byte_count);
107 // This loop gets optimized out in ReleaseFast mode107 @memset(byte_slice.ptr, undefined, byte_slice.len);
108 for (byte_slice) |*byte| {
109 byte.* = undefined;
110 }
111 return @bytesToSlice(T, @alignCast(alignment, byte_slice));108 return @bytesToSlice(T, @alignCast(alignment, byte_slice));
112 }109 }
113110
...@@ -153,10 +150,7 @@ pub const Allocator = struct {...@@ -153,10 +150,7 @@ pub const Allocator = struct {
153 const byte_slice = try self.reallocFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment);150 const byte_slice = try self.reallocFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment);
154 assert(byte_slice.len == byte_count);151 assert(byte_slice.len == byte_count);
155 if (new_n > old_mem.len) {152 if (new_n > old_mem.len) {
156 // This loop gets optimized out in ReleaseFast mode153 @memset(byte_slice.ptr + old_byte_slice.len, undefined, byte_slice.len - old_byte_slice.len);
157 for (byte_slice[old_byte_slice.len..]) |*byte| {
158 byte.* = undefined;
159 }
160 }154 }
161 return @bytesToSlice(T, @alignCast(new_alignment, byte_slice));155 return @bytesToSlice(T, @alignCast(new_alignment, byte_slice));
162 }156 }
std/os.zig+104-14
...@@ -23,6 +23,7 @@ test "std.os" {...@@ -23,6 +23,7 @@ test "std.os" {
23 _ = @import("os/time.zig");23 _ = @import("os/time.zig");
24 _ = @import("os/windows.zig");24 _ = @import("os/windows.zig");
25 _ = @import("os/uefi.zig");25 _ = @import("os/uefi.zig");
26 _ = @import("os/wasi.zig");
26 _ = @import("os/get_app_data_dir.zig");27 _ = @import("os/get_app_data_dir.zig");
27}28}
2829
...@@ -33,6 +34,7 @@ pub const freebsd = @import("os/freebsd.zig");...@@ -33,6 +34,7 @@ pub const freebsd = @import("os/freebsd.zig");
33pub const netbsd = @import("os/netbsd.zig");34pub const netbsd = @import("os/netbsd.zig");
34pub const zen = @import("os/zen.zig");35pub const zen = @import("os/zen.zig");
35pub const uefi = @import("os/uefi.zig");36pub const uefi = @import("os/uefi.zig");
37pub const wasi = @import("os/wasi.zig");
3638
37pub const posix = switch (builtin.os) {39pub const posix = switch (builtin.os) {
38 Os.linux => linux,40 Os.linux => linux,
...@@ -40,6 +42,7 @@ pub const posix = switch (builtin.os) {...@@ -40,6 +42,7 @@ pub const posix = switch (builtin.os) {
40 Os.freebsd => freebsd,42 Os.freebsd => freebsd,
41 Os.netbsd => netbsd,43 Os.netbsd => netbsd,
42 Os.zen => zen,44 Os.zen => zen,
45 Os.wasi => wasi,
43 else => @compileError("Unsupported OS"),46 else => @compileError("Unsupported OS"),
44};47};
4548
...@@ -50,7 +53,11 @@ pub const path = @import("os/path.zig");...@@ -50,7 +53,11 @@ pub const path = @import("os/path.zig");
50pub const File = @import("os/file.zig").File;53pub const File = @import("os/file.zig").File;
51pub const time = @import("os/time.zig");54pub const time = @import("os/time.zig");
5255
53pub const page_size = 4 * 1024;56pub const page_size = switch (builtin.arch) {
57 .wasm32, .wasm64 => 64 * 1024,
58 else => 4 * 1024,
59};
60
54pub const MAX_PATH_BYTES = switch (builtin.os) {61pub const MAX_PATH_BYTES = switch (builtin.os) {
55 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => posix.PATH_MAX,62 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => posix.PATH_MAX,
56 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.63 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
...@@ -139,6 +146,12 @@ pub fn getRandomBytes(buf: []u8) !void {...@@ -139,6 +146,12 @@ pub fn getRandomBytes(buf: []u8) !void {
139 };146 };
140 }147 }
141 },148 },
149 Os.wasi => {
150 const random_get_result = os.wasi.random_get(buf.ptr, buf.len);
151 if (random_get_result != os.wasi.ESUCCESS) {
152 return error.Unknown;
153 }
154 },
142 Os.zen => {155 Os.zen => {
143 const randomness = []u8{ 42, 1, 7, 12, 22, 17, 99, 16, 26, 87, 41, 45 };156 const randomness = []u8{ 42, 1, 7, 12, 22, 17, 99, 16, 26, 87, 41, 45 };
144 var i: usize = 0;157 var i: usize = 0;
...@@ -198,6 +211,12 @@ pub fn abort() noreturn {...@@ -198,6 +211,12 @@ pub fn abort() noreturn {
198 }211 }
199 windows.ExitProcess(3);212 windows.ExitProcess(3);
200 },213 },
214 Os.wasi => {
215 _ = wasi.proc_raise(wasi.SIGABRT);
216 // TODO: Is SIGKILL even necessary?
217 _ = wasi.proc_raise(wasi.SIGKILL);
218 while (true) {}
219 },
201 Os.uefi => {220 Os.uefi => {
202 // TODO there's gotta be a better thing to do here than loop forever221 // TODO there's gotta be a better thing to do here than loop forever
203 while (true) {}222 while (true) {}
...@@ -226,6 +245,9 @@ pub fn exit(status: u8) noreturn {...@@ -226,6 +245,9 @@ pub fn exit(status: u8) noreturn {
226 Os.windows => {245 Os.windows => {
227 windows.ExitProcess(status);246 windows.ExitProcess(status);
228 },247 },
248 Os.wasi => {
249 wasi.proc_exit(status);
250 },
229 else => @compileError("Unsupported OS"),251 else => @compileError("Unsupported OS"),
230 }252 }
231}253}
...@@ -749,6 +771,37 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -749,6 +771,37 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
749771
750 try result.setMove(key, value);772 try result.setMove(key, value);
751 }773 }
774 } else if (builtin.os == Os.wasi) {
775 var environ_count: usize = undefined;
776 var environ_buf_size: usize = undefined;
777
778 const environ_sizes_get_ret = std.os.wasi.environ_sizes_get(&environ_count, &environ_buf_size);
779 if (environ_sizes_get_ret != os.wasi.ESUCCESS) {
780 return unexpectedErrorPosix(environ_sizes_get_ret);
781 }
782
783 // TODO: Verify that the documentation is incorrect
784 // https://github.com/WebAssembly/WASI/issues/27
785 var environ = try allocator.alloc(?[*]u8, environ_count + 1);
786 defer allocator.free(environ);
787 var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size);
788 defer allocator.free(environ_buf);
789
790 const environ_get_ret = std.os.wasi.environ_get(environ.ptr, environ_buf.ptr);
791 if (environ_get_ret != os.wasi.ESUCCESS) {
792 return unexpectedErrorPosix(environ_get_ret);
793 }
794
795 for (environ) |env| {
796 if (env) |ptr| {
797 const pair = mem.toSlice(u8, ptr);
798 var parts = mem.separate(pair, "=");
799 const key = parts.next().?;
800 const value = parts.next().?;
801 try result.set(key, value);
802 }
803 }
804 return result;
752 } else {805 } else {
753 for (posix_environ_raw) |ptr| {806 for (posix_environ_raw) |ptr| {
754 var line_i: usize = 0;807 var line_i: usize = 0;
...@@ -1083,13 +1136,14 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {...@@ -1083,13 +1136,14 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
1083 defer in_file.close();1136 defer in_file.close();
10841137
1085 const mode = try in_file.mode();1138 const mode = try in_file.mode();
1139 const in_stream = &in_file.inStream().stream;
10861140
1087 var atomic_file = try AtomicFile.init(dest_path, mode);1141 var atomic_file = try AtomicFile.init(dest_path, mode);
1088 defer atomic_file.deinit();1142 defer atomic_file.deinit();
10891143
1090 var buf: [page_size]u8 = undefined;1144 var buf: [page_size]u8 = undefined;
1091 while (true) {1145 while (true) {
1092 const amt = try in_file.readFull(buf[0..]);1146 const amt = try in_stream.readFull(buf[0..]);
1093 try atomic_file.file.write(buf[0..amt]);1147 try atomic_file.file.write(buf[0..amt]);
1094 if (amt != buf.len) {1148 if (amt != buf.len) {
1095 return atomic_file.finish();1149 return atomic_file.finish();
...@@ -2127,6 +2181,11 @@ pub const ArgIterator = struct {...@@ -2127,6 +2181,11 @@ pub const ArgIterator = struct {
2127 inner: InnerType,2181 inner: InnerType,
21282182
2129 pub fn init() ArgIterator {2183 pub fn init() ArgIterator {
2184 if (builtin.os == Os.wasi) {
2185 // TODO: Figure out a compatible interface accomodating WASI
2186 @compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead.");
2187 }
2188
2130 return ArgIterator{ .inner = InnerType.init() };2189 return ArgIterator{ .inner = InnerType.init() };
2131 }2190 }
21322191
...@@ -2159,6 +2218,34 @@ pub fn args() ArgIterator {...@@ -2159,6 +2218,34 @@ pub fn args() ArgIterator {
21592218
2160/// Caller must call argsFree on result.2219/// Caller must call argsFree on result.
2161pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {2220pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
2221 if (builtin.os == Os.wasi) {
2222 var count: usize = undefined;
2223 var buf_size: usize = undefined;
2224
2225 const args_sizes_get_ret = os.wasi.args_sizes_get(&count, &buf_size);
2226 if (args_sizes_get_ret != os.wasi.ESUCCESS) {
2227 return unexpectedErrorPosix(args_sizes_get_ret);
2228 }
2229
2230 var argv = try allocator.alloc([*]u8, count);
2231 defer allocator.free(argv);
2232
2233 var argv_buf = try allocator.alloc(u8, buf_size);
2234 const args_get_ret = os.wasi.args_get(argv.ptr, argv_buf.ptr);
2235 if (args_get_ret != os.wasi.ESUCCESS) {
2236 return unexpectedErrorPosix(args_get_ret);
2237 }
2238
2239 var result_slice = try allocator.alloc([]u8, count);
2240
2241 var i: usize = 0;
2242 while (i < count) : (i += 1) {
2243 result_slice[i] = mem.toSlice(u8, argv[i]);
2244 }
2245
2246 return result_slice;
2247 }
2248
2162 // TODO refactor to only make 1 allocation.2249 // TODO refactor to only make 1 allocation.
2163 var it = args();2250 var it = args();
2164 var contents = try Buffer.initSize(allocator, 0);2251 var contents = try Buffer.initSize(allocator, 0);
...@@ -2196,6 +2283,16 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {...@@ -2196,6 +2283,16 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
2196}2283}
21972284
2198pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {2285pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
2286 if (builtin.os == Os.wasi) {
2287 const last_item = args_alloc[args_alloc.len - 1];
2288 const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated
2289 const first_item_ptr = args_alloc[0].ptr;
2290 const len = last_byte_addr - @ptrToInt(first_item_ptr);
2291 allocator.free(first_item_ptr[0..len]);
2292
2293 return allocator.free(args_alloc);
2294 }
2295
2199 var total_bytes: usize = 0;2296 var total_bytes: usize = 0;
2200 for (args_alloc) |arg| {2297 for (args_alloc) |arg| {
2201 total_bytes += @sizeOf([]u8) + arg.len;2298 total_bytes += @sizeOf([]u8) + arg.len;
...@@ -3030,9 +3127,6 @@ pub const SpawnThreadError = error{...@@ -3030,9 +3127,6 @@ pub const SpawnThreadError = error{
3030 Unexpected,3127 Unexpected,
3031};3128};
30323129
3033pub var linux_tls_phdr: ?*std.elf.Phdr = null;
3034pub var linux_tls_img_src: [*]const u8 = undefined; // defined if linux_tls_phdr is
3035
3036/// caller must call wait on the returned thread3130/// caller must call wait on the returned thread
3037/// fn startFn(@typeOf(context)) T3131/// fn startFn(@typeOf(context)) T
3038/// where T is u8, noreturn, void, or !void3132/// where T is u8, noreturn, void, or !void
...@@ -3142,12 +3236,10 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread...@@ -3142,12 +3236,10 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
3142 }3236 }
3143 // Finally, the Thread Local Storage, if any.3237 // Finally, the Thread Local Storage, if any.
3144 if (!Thread.use_pthreads) {3238 if (!Thread.use_pthreads) {
3145 if (linux_tls_phdr) |tls_phdr| {3239 if (linux.tls.tls_image) |tls_img| {
3146 l = mem.alignForward(l, tls_phdr.p_align);3240 l = mem.alignForward(l, @alignOf(usize));
3147 tls_start_offset = l;3241 tls_start_offset = l;
3148 l += tls_phdr.p_memsz;3242 l += tls_img.alloc_size;
3149 // the fs register address
3150 l += @sizeOf(usize);
3151 }3243 }
3152 }3244 }
3153 break :blk l;3245 break :blk l;
...@@ -3188,10 +3280,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread...@@ -3188,10 +3280,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
3188 posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID |3280 posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID |
3189 posix.CLONE_DETACHED;3281 posix.CLONE_DETACHED;
3190 var newtls: usize = undefined;3282 var newtls: usize = undefined;
3191 if (linux_tls_phdr) |tls_phdr| {3283 if (linux.tls.tls_image) |tls_img| {
3192 @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz);3284 newtls = linux.tls.copyTLS(mmap_addr + tls_start_offset);
3193 newtls = mmap_addr + mmap_len - @sizeOf(usize);
3194 @intToPtr(*usize, newtls).* = newtls;
3195 flags |= posix.CLONE_SETTLS;3285 flags |= posix.CLONE_SETTLS;
3196 }3286 }
3197 const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);3287 const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
std/os/darwin.zig+1-1
...@@ -812,7 +812,7 @@ pub fn sigaction(sig: u5, noalias act: *const Sigaction, noalias oact: ?*Sigacti...@@ -812,7 +812,7 @@ pub fn sigaction(sig: u5, noalias act: *const Sigaction, noalias oact: ?*Sigacti
812 .sa_mask = act.mask,812 .sa_mask = act.mask,
813 };813 };
814 var coact: c.Sigaction = undefined;814 var coact: c.Sigaction = undefined;
815 const result = errnoWrap(c.sigaction(sig, *cact, *coact));815 const result = errnoWrap(c.sigaction(sig, &cact, &coact));
816 if (result != 0) {816 if (result != 0) {
817 return result;817 return result;
818 }818 }
std/os/file.zig+12-16
...@@ -235,7 +235,7 @@ pub const File = struct {...@@ -235,7 +235,7 @@ pub const File = struct {
235 Unexpected,235 Unexpected,
236 };236 };
237237
238 pub fn seekForward(self: File, amount: isize) SeekError!void {238 pub fn seekForward(self: File, amount: i64) SeekError!void {
239 switch (builtin.os) {239 switch (builtin.os) {
240 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {240 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
241 const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);241 const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);
...@@ -266,7 +266,7 @@ pub const File = struct {...@@ -266,7 +266,7 @@ pub const File = struct {
266 }266 }
267 }267 }
268268
269 pub fn seekTo(self: File, pos: usize) SeekError!void {269 pub fn seekTo(self: File, pos: u64) SeekError!void {
270 switch (builtin.os) {270 switch (builtin.os) {
271 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {271 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
272 const ipos = try math.cast(isize, pos);272 const ipos = try math.cast(isize, pos);
...@@ -301,13 +301,12 @@ pub const File = struct {...@@ -301,13 +301,12 @@ pub const File = struct {
301 }301 }
302302
303 pub const GetSeekPosError = error{303 pub const GetSeekPosError = error{
304 Overflow,
305 SystemResources,304 SystemResources,
306 Unseekable,305 Unseekable,
307 Unexpected,306 Unexpected,
308 };307 };
309308
310 pub fn getPos(self: File) GetSeekPosError!usize {309 pub fn getPos(self: File) GetSeekPosError!u64 {
311 switch (builtin.os) {310 switch (builtin.os) {
312 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {311 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
313 const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);312 const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);
...@@ -324,7 +323,7 @@ pub const File = struct {...@@ -324,7 +323,7 @@ pub const File = struct {
324 else => os.unexpectedErrorPosix(err),323 else => os.unexpectedErrorPosix(err),
325 };324 };
326 }325 }
327 return result;326 return u64(result);
328 },327 },
329 Os.windows => {328 Os.windows => {
330 var pos: windows.LARGE_INTEGER = undefined;329 var pos: windows.LARGE_INTEGER = undefined;
...@@ -336,17 +335,16 @@ pub const File = struct {...@@ -336,17 +335,16 @@ pub const File = struct {
336 };335 };
337 }336 }
338337
339 assert(pos >= 0);338 return @intCast(u64, pos);
340 return math.cast(usize, pos);
341 },339 },
342 else => @compileError("unsupported OS"),340 else => @compileError("unsupported OS"),
343 }341 }
344 }342 }
345343
346 pub fn getEndPos(self: File) GetSeekPosError!usize {344 pub fn getEndPos(self: File) GetSeekPosError!u64 {
347 if (is_posix) {345 if (is_posix) {
348 const stat = try os.posixFStat(self.handle);346 const stat = try os.posixFStat(self.handle);
349 return @intCast(usize, stat.size);347 return @intCast(u64, stat.size);
350 } else if (is_windows) {348 } else if (is_windows) {
351 var file_size: windows.LARGE_INTEGER = undefined;349 var file_size: windows.LARGE_INTEGER = undefined;
352 if (windows.GetFileSizeEx(self.handle, &file_size) == 0) {350 if (windows.GetFileSizeEx(self.handle, &file_size) == 0) {
...@@ -355,9 +353,7 @@ pub const File = struct {...@@ -355,9 +353,7 @@ pub const File = struct {
355 else => os.unexpectedErrorWindows(err),353 else => os.unexpectedErrorWindows(err),
356 };354 };
357 }355 }
358 if (file_size < 0)356 return @intCast(u64, file_size);
359 return error.Overflow;
360 return math.cast(usize, @intCast(u64, file_size));
361 } else {357 } else {
362 @compileError("TODO support getEndPos on this OS");358 @compileError("TODO support getEndPos on this OS");
363 }359 }
...@@ -492,22 +488,22 @@ pub const File = struct {...@@ -492,22 +488,22 @@ pub const File = struct {
492488
493 pub const Stream = io.SeekableStream(SeekError, GetSeekPosError);489 pub const Stream = io.SeekableStream(SeekError, GetSeekPosError);
494490
495 pub fn seekToFn(seekable_stream: *Stream, pos: usize) SeekError!void {491 pub fn seekToFn(seekable_stream: *Stream, pos: u64) SeekError!void {
496 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);492 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
497 return self.file.seekTo(pos);493 return self.file.seekTo(pos);
498 }494 }
499495
500 pub fn seekForwardFn(seekable_stream: *Stream, amt: isize) SeekError!void {496 pub fn seekForwardFn(seekable_stream: *Stream, amt: i64) SeekError!void {
501 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);497 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
502 return self.file.seekForward(amt);498 return self.file.seekForward(amt);
503 }499 }
504500
505 pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!usize {501 pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!u64 {
506 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);502 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
507 return self.file.getEndPos();503 return self.file.getEndPos();
508 }504 }
509505
510 pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!usize {506 pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!u64 {
511 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);507 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
512 return self.file.getPos();508 return self.file.getPos();
513 }509 }
std/os/linux.zig+150-16
...@@ -2,7 +2,10 @@ const std = @import("../std.zig");...@@ -2,7 +2,10 @@ const std = @import("../std.zig");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const builtin = @import("builtin");3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
5const elf = std.elf;
6pub const tls = @import("linux/tls.zig");
5const vdso = @import("linux/vdso.zig");7const vdso = @import("linux/vdso.zig");
8const dl = @import("../dynamic_library.zig");
6pub use switch (builtin.arch) {9pub use switch (builtin.arch) {
7 builtin.Arch.x86_64 => @import("linux/x86_64.zig"),10 builtin.Arch.x86_64 => @import("linux/x86_64.zig"),
8 builtin.Arch.i386 => @import("linux/i386.zig"),11 builtin.Arch.i386 => @import("linux/i386.zig"),
...@@ -12,6 +15,7 @@ pub use switch (builtin.arch) {...@@ -12,6 +15,7 @@ pub use switch (builtin.arch) {
12pub use @import("linux/errno.zig");15pub use @import("linux/errno.zig");
1316
14pub const PATH_MAX = 4096;17pub const PATH_MAX = 4096;
18pub const IOV_MAX = 1024;
1519
16pub const STDIN_FILENO = 0;20pub const STDIN_FILENO = 0;
17pub const STDOUT_FILENO = 1;21pub const STDOUT_FILENO = 1;
...@@ -955,10 +959,13 @@ pub fn waitpid(pid: i32, status: *i32, options: i32) usize {...@@ -955,10 +959,13 @@ pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
955 return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);959 return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
956}960}
957961
962var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
963
958pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {964pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
959 if (VDSO_CGT_SYM.len != 0) {965 if (VDSO_CGT_SYM.len != 0) {
960 const f = @atomicLoad(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, builtin.AtomicOrder.Unordered);966 const ptr = @atomicLoad(?*const c_void, &vdso_clock_gettime, .Unordered);
961 if (@ptrToInt(f) != 0) {967 if (ptr) |fn_ptr| {
968 const f = @ptrCast(@typeOf(clock_gettime), fn_ptr);
962 const rc = f(clk_id, tp);969 const rc = f(clk_id, tp);
963 switch (rc) {970 switch (rc) {
964 0, @bitCast(usize, isize(-EINVAL)) => return rc,971 0, @bitCast(usize, isize(-EINVAL)) => return rc,
...@@ -968,13 +975,18 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {...@@ -968,13 +975,18 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
968 }975 }
969 return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));976 return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
970}977}
971var vdso_clock_gettime = init_vdso_clock_gettime;978
972extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize {979extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize {
973 const addr = vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM);980 const ptr = @intToPtr(?*const c_void, vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM));
974 var f = @intToPtr(@typeOf(init_vdso_clock_gettime), addr);981 // Note that we may not have a VDSO at all, update the stub address anyway
975 _ = @cmpxchgStrong(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, init_vdso_clock_gettime, f, builtin.AtomicOrder.Monotonic, builtin.AtomicOrder.Monotonic);982 // so that clock_gettime will fall back on the good old (and slow) syscall
976 if (@ptrToInt(f) == 0) return @bitCast(usize, isize(-ENOSYS));983 _ = @cmpxchgStrong(?*const c_void, &vdso_clock_gettime, &init_vdso_clock_gettime, ptr, .Monotonic, .Monotonic);
977 return f(clk, ts);984 // Call into the VDSO if available
985 if (ptr) |fn_ptr| {
986 const f = @ptrCast(@typeOf(clock_gettime), fn_ptr);
987 return f(clk, ts);
988 }
989 return @bitCast(usize, isize(-ENOSYS));
978}990}
979991
980pub fn clock_getres(clk_id: i32, tp: *timespec) usize {992pub 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...@@ -1100,8 +1112,8 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
11001112
1101const NSIG = 65;1113const NSIG = 65;
1102const sigset_t = [128 / @sizeOf(usize)]usize;1114const sigset_t = [128 / @sizeOf(usize)]usize;
1103const all_mask = []usize{maxInt(usize)};1115const all_mask = []u32{ 0xffffffff, 0xffffffff };
1104const app_mask = []usize{0xfffffffc7fffffff};1116const app_mask = []u32{ 0xfffffffc, 0x7fffffff };
11051117
1106const k_sigaction = extern struct {1118const k_sigaction = extern struct {
1107 handler: extern fn (i32) void,1119 handler: extern fn (i32) void,
...@@ -1193,6 +1205,16 @@ pub const iovec_const = extern struct {...@@ -1193,6 +1205,16 @@ pub const iovec_const = extern struct {
1193 iov_len: usize,1205 iov_len: usize,
1194};1206};
11951207
1208pub const mmsghdr = extern struct {
1209 msg_hdr: msghdr,
1210 msg_len: u32,
1211};
1212
1213pub const mmsghdr_const = extern struct {
1214 msg_hdr: msghdr_const,
1215 msg_len: u32,
1216};
1217
1196pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {1218pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
1197 return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));1219 return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
1198}1220}
...@@ -1213,10 +1235,50 @@ pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noal...@@ -1213,10 +1235,50 @@ pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noal
1213 return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));1235 return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
1214}1236}
12151237
1216pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize {1238pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize {
1217 return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);1239 return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
1218}1240}
12191241
1242pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize {
1243 if (@typeInfo(usize).Int.bits > @typeInfo(@typeOf(mmsghdr(undefined).msg_len)).Int.bits) {
1244 // workaround kernel brokenness:
1245 // if adding up all iov_len overflows a i32 then split into multiple calls
1246 // see https://www.openwall.com/lists/musl/2014/06/07/5
1247 const kvlen = if (vlen > IOV_MAX) IOV_MAX else vlen; // matches kernel
1248 var next_unsent: usize = 0;
1249 for (msgvec[0..kvlen]) |*msg, i| {
1250 var size: i32 = 0;
1251 const msg_iovlen = @intCast(usize, msg.msg_hdr.msg_iovlen); // kernel side this is treated as unsigned
1252 for (msg.msg_hdr.msg_iov[0..msg_iovlen]) |iov, j| {
1253 if (iov.iov_len > std.math.maxInt(i32) or @addWithOverflow(i32, size, @intCast(i32, iov.iov_len), &size)) {
1254 // batch-send all messages up to the current message
1255 if (next_unsent < i) {
1256 const batch_size = i - next_unsent;
1257 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
1258 if (getErrno(r) != 0) return next_unsent;
1259 if (r < batch_size) return next_unsent + r;
1260 }
1261 // send current message as own packet
1262 const r = sendmsg(fd, &msg.msg_hdr, flags);
1263 if (getErrno(r) != 0) return r;
1264 // Linux limits the total bytes sent by sendmsg to INT_MAX, so this cast is safe.
1265 msg.msg_len = @intCast(u32, r);
1266 next_unsent = i + 1;
1267 break;
1268 }
1269 }
1270 }
1271 if (next_unsent < kvlen or next_unsent == 0) { // want to make sure at least one syscall occurs (e.g. to trigger MSG_EOR)
1272 const batch_size = kvlen - next_unsent;
1273 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
1274 if (getErrno(r) != 0) return r;
1275 return next_unsent + r;
1276 }
1277 return kvlen;
1278 }
1279 return syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(msgvec), vlen, flags);
1280}
1281
1220pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {1282pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
1221 return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);1283 return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);
1222}1284}
...@@ -1339,17 +1401,25 @@ pub fn sched_getaffinity(pid: i32, set: []usize) usize {...@@ -1339,17 +1401,25 @@ pub fn sched_getaffinity(pid: i32, set: []usize) usize {
1339 return syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), set.len * @sizeOf(usize), @ptrToInt(set.ptr));1401 return syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), set.len * @sizeOf(usize), @ptrToInt(set.ptr));
1340}1402}
13411403
1342pub const epoll_data = packed union {1404pub const epoll_data = extern union {
1343 ptr: usize,1405 ptr: usize,
1344 fd: i32,1406 fd: i32,
1345 @"u32": u32,1407 @"u32": u32,
1346 @"u64": u64,1408 @"u64": u64,
1347};1409};
13481410
1349pub const epoll_event = packed struct {1411// On x86_64 the structure is packed so that it matches the definition of its
1350 events: u32,1412// 32bit counterpart
1351 data: epoll_data,1413pub const epoll_event = if (builtin.arch != .x86_64)
1352};1414 extern struct {
1415 events: u32,
1416 data: epoll_data,
1417 }
1418else
1419 packed struct {
1420 events: u32,
1421 data: epoll_data,
1422 };
13531423
1354pub fn epoll_create() usize {1424pub fn epoll_create() usize {
1355 return epoll_create1(0);1425 return epoll_create1(0);
...@@ -1534,6 +1604,70 @@ pub const dirent64 = extern struct {...@@ -1534,6 +1604,70 @@ pub const dirent64 = extern struct {
1534 d_name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/1731604 d_name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173
1535};1605};
15361606
1607pub const dl_phdr_info = extern struct {
1608 dlpi_addr: usize,
1609 dlpi_name: ?[*]const u8,
1610 dlpi_phdr: [*]elf.Phdr,
1611 dlpi_phnum: u16,
1612};
1613
1614// XXX: This should be weak
1615extern const __ehdr_start: elf.Ehdr = undefined;
1616
1617pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
1618 if (builtin.link_libc) {
1619 return std.c.dl_iterate_phdr(@ptrCast(std.c.dl_iterate_phdr_callback, callback), @ptrCast(?*c_void, data));
1620 }
1621
1622 const elf_base = @ptrToInt(&__ehdr_start);
1623 const n_phdr = __ehdr_start.e_phnum;
1624 const phdrs = (@intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff))[0..n_phdr];
1625
1626 var it = dl.linkmap_iterator(phdrs) catch return 0;
1627
1628 // The executable has no dynamic link segment, create a single entry for
1629 // the whole ELF image
1630 if (it.end()) {
1631 var info = dl_phdr_info{
1632 .dlpi_addr = elf_base,
1633 .dlpi_name = c"/proc/self/exe",
1634 .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
1635 .dlpi_phnum = __ehdr_start.e_phnum,
1636 };
1637
1638 return callback(&info, @sizeOf(dl_phdr_info), data);
1639 }
1640
1641 // Last return value from the callback function
1642 var last_r: isize = 0;
1643 while (it.next()) |entry| {
1644 var dlpi_phdr: usize = undefined;
1645 var dlpi_phnum: u16 = undefined;
1646
1647 if (entry.l_addr != 0) {
1648 const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
1649 dlpi_phdr = entry.l_addr + elf_header.e_phoff;
1650 dlpi_phnum = elf_header.e_phnum;
1651 } else {
1652 // This is the running ELF image
1653 dlpi_phdr = elf_base + __ehdr_start.e_phoff;
1654 dlpi_phnum = __ehdr_start.e_phnum;
1655 }
1656
1657 var info = dl_phdr_info{
1658 .dlpi_addr = entry.l_addr,
1659 .dlpi_name = entry.l_name,
1660 .dlpi_phdr = @intToPtr([*]elf.Phdr, dlpi_phdr),
1661 .dlpi_phnum = dlpi_phnum,
1662 };
1663
1664 last_r = callback(&info, @sizeOf(dl_phdr_info), data);
1665 if (last_r != 0) break;
1666 }
1667
1668 return last_r;
1669}
1670
1537test "import" {1671test "import" {
1538 if (builtin.os == builtin.Os.linux) {1672 if (builtin.os == builtin.Os.linux) {
1539 _ = @import("linux/test.zig");1673 _ = @import("linux/test.zig");
std/os/linux/arm64.zig+16-3
...@@ -2,6 +2,7 @@ const std = @import("../../std.zig");...@@ -2,6 +2,7 @@ const std = @import("../../std.zig");
2const linux = std.os.linux;2const linux = std.os.linux;
3const socklen_t = linux.socklen_t;3const socklen_t = linux.socklen_t;
4const iovec = linux.iovec;4const iovec = linux.iovec;
5const iovec_const = linux.iovec_const;
56
6pub const SYS_io_setup = 0;7pub const SYS_io_setup = 0;
7pub const SYS_io_destroy = 1;8pub const SYS_io_destroy = 1;
...@@ -415,12 +416,24 @@ pub fn syscall6(...@@ -415,12 +416,24 @@ pub fn syscall6(
415pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;416pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
416417
417pub const msghdr = extern struct {418pub const msghdr = extern struct {
418 msg_name: *u8,419 msg_name: ?*sockaddr,
419 msg_namelen: socklen_t,420 msg_namelen: socklen_t,
420 msg_iov: *iovec,421 msg_iov: [*]iovec,
421 msg_iovlen: i32,422 msg_iovlen: i32,
422 __pad1: i32,423 __pad1: i32,
423 msg_control: *u8,424 msg_control: ?*c_void,
425 msg_controllen: socklen_t,
426 __pad2: socklen_t,
427 msg_flags: i32,
428};
429
430pub const msghdr_const = extern struct {
431 msg_name: ?*const sockaddr,
432 msg_namelen: socklen_t,
433 msg_iov: [*]iovec_const,
434 msg_iovlen: i32,
435 __pad1: i32,
436 msg_control: ?*c_void,
424 msg_controllen: socklen_t,437 msg_controllen: socklen_t,
425 __pad2: socklen_t,438 __pad2: socklen_t,
426 msg_flags: i32,439 msg_flags: i32,
std/os/linux/test.zig+41
...@@ -1,6 +1,8 @@...@@ -1,6 +1,8 @@
1const std = @import("../../std.zig");1const std = @import("../../std.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const linux = std.os.linux;3const linux = std.os.linux;
4const mem = std.mem;
5const elf = std.elf;
4const expect = std.testing.expect;6const expect = std.testing.expect;
57
6test "getpid" {8test "getpid" {
...@@ -42,3 +44,42 @@ test "timer" {...@@ -42,3 +44,42 @@ test "timer" {
42 // TODO implicit cast from *[N]T to [*]T44 // TODO implicit cast from *[N]T to [*]T
43 err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);45 err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
44}46}
47
48export fn iter_fn(info: *linux.dl_phdr_info, size: usize, data: ?*usize) i32 {
49 var counter = data.?;
50 // Count how many libraries are loaded
51 counter.* += usize(1);
52
53 // The image should contain at least a PT_LOAD segment
54 if (info.dlpi_phnum < 1) return -1;
55
56 // Quick & dirty validation of the phdr pointers, make sure we're not
57 // pointing to some random gibberish
58 var i: usize = 0;
59 var found_load = false;
60 while (i < info.dlpi_phnum) : (i += 1) {
61 const phdr = info.dlpi_phdr[i];
62
63 if (phdr.p_type != elf.PT_LOAD) continue;
64
65 // Find the ELF header
66 const elf_header = @intToPtr(*elf.Ehdr, phdr.p_vaddr - phdr.p_offset);
67 // Validate the magic
68 if (!mem.eql(u8, elf_header.e_ident[0..], "\x7fELF")) return -1;
69 // Consistency check
70 if (elf_header.e_phnum != info.dlpi_phnum) return -1;
71
72 found_load = true;
73 break;
74 }
75
76 if (!found_load) return -1;
77
78 return 42;
79}
80
81test "dl_iterate_phdr" {
82 var counter: usize = 0;
83 expect(linux.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
84 expect(counter != 0);
85}
std/os/linux/tls.zig created+247
...@@ -0,0 +1,247 @@
1const std = @import("std");
2const mem = std.mem;
3const posix = std.os.posix;
4const elf = std.elf;
5const builtin = @import("builtin");
6const assert = std.debug.assert;
7
8// This file implements the two TLS variants [1] used by ELF-based systems.
9//
10// The variant I has the following layout in memory:
11// -------------------------------------------------------
12// | DTV | Zig | DTV | Alignment | TLS |
13// | storage | thread data | pointer | | block |
14// ------------------------^------------------------------
15// `-- The thread pointer register points here
16//
17// In this case we allocate additional space for our control structure that's
18// placed _before_ the DTV pointer together with the DTV.
19//
20// NOTE: Some systems such as power64 or mips use this variant with a twist: the
21// alignment is not present and the tp and DTV addresses are offset by a
22// constant.
23//
24// On the other hand the variant II has the following layout in memory:
25// ---------------------------------------
26// | TLS | TCB | Zig | DTV |
27// | block | | thread data | storage |
28// --------^------------------------------
29// `-- The thread pointer register points here
30//
31// The structure of the TCB is not defined by the ABI so we reserve enough space
32// for a single pointer as some architectures such as i386 and x86_64 need a
33// pointer to the TCB block itself at the address pointed by the tp.
34//
35// In this case the control structure and DTV are placed one after another right
36// after the TLS block data.
37//
38// At the moment the DTV is very simple since we only support static TLS, all we
39// need is a two word vector to hold the number of entries (1) and the address
40// of the first TLS block.
41//
42// [1] https://www.akkadia.org/drepper/tls.pdf
43
44const TLSVariant = enum {
45 VariantI,
46 VariantII,
47};
48
49const tls_variant = switch (builtin.arch) {
50 .arm, .armeb, .aarch64, .aarch64_be => TLSVariant.VariantI,
51 .x86_64, .i386 => TLSVariant.VariantII,
52 else => @compileError("undefined tls_variant for this architecture"),
53};
54
55// Controls how many bytes are reserved for the Thread Control Block
56const tls_tcb_size = switch (builtin.arch) {
57 // ARM EABI mandates enough space for two pointers: the first one points to
58 // the DTV while the second one is unspecified but reserved
59 .arm, .armeb, .aarch64, .aarch64_be => 2 * @sizeOf(usize),
60 .i386, .x86_64 => @sizeOf(usize),
61 else => 0,
62};
63
64// Controls if the TCB should be aligned according to the TLS segment p_align
65const tls_tcb_align_size = switch (builtin.arch) {
66 .arm, .armeb, .aarch64, .aarch64_be => true,
67 else => false,
68};
69
70// Check if the architecture-specific parameters look correct
71comptime {
72 if (tls_tcb_align_size and tls_variant != TLSVariant.VariantI) {
73 @compileError("tls_tcb_align_size is only meaningful for variant I TLS");
74 }
75}
76
77// Some architectures add some offset to the tp and dtv addresses in order to
78// make the generated code more efficient
79
80const tls_tp_offset = switch (builtin.arch) {
81 else => 0,
82};
83
84const tls_dtv_offset = switch (builtin.arch) {
85 else => 0,
86};
87
88// Per-thread storage for Zig's use
89const CustomData = packed struct {
90};
91
92// Dynamic Thread Vector
93const DTV = packed struct {
94 entries: usize,
95 tls_block: [1]usize,
96};
97
98// Holds all the information about the process TLS image
99const TLSImage = struct {
100 data_src: []u8,
101 alloc_size: usize,
102 tcb_offset: usize,
103 dtv_offset: usize,
104 data_offset: usize,
105};
106
107pub var tls_image: ?TLSImage = null;
108
109pub fn setThreadPointer(addr: usize) void {
110 switch (builtin.arch) {
111 .x86_64 => {
112 const rc = std.os.linux.syscall2(std.os.linux.SYS_arch_prctl,
113 std.os.linux.ARCH_SET_FS, addr);
114 assert(rc == 0);
115 },
116 .aarch64 => {
117 asm volatile (
118 \\ msr tpidr_el0, %[addr]
119 : : [addr] "r" (addr)
120 );
121 },
122 else => @compileError("Unsupported architecture"),
123 }
124}
125
126pub fn initTLS() void {
127 var tls_phdr: ?*elf.Phdr = null;
128 var img_base: usize = 0;
129
130 const auxv = std.os.linux_elf_aux_maybe.?;
131 var at_phent: usize = undefined;
132 var at_phnum: usize = undefined;
133 var at_phdr: usize = undefined;
134
135 var i: usize = 0;
136 while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
137 switch (auxv[i].a_type) {
138 elf.AT_PHENT => at_phent = auxv[i].a_un.a_val,
139 elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
140 elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
141 else => continue,
142 }
143 }
144
145 // Sanity check
146 assert(at_phent == @sizeOf(elf.Phdr));
147
148 // Search the TLS section
149 const phdrs = (@intToPtr([*]elf.Phdr, at_phdr))[0..at_phnum];
150
151 for (phdrs) |*phdr| {
152 switch (phdr.p_type) {
153 elf.PT_PHDR => img_base = at_phdr - phdr.p_vaddr,
154 elf.PT_TLS => tls_phdr = phdr,
155 else => continue,
156 }
157 }
158
159 if (tls_phdr) |phdr| {
160 // Offsets into the allocated TLS area
161 var tcb_offset: usize = undefined;
162 var dtv_offset: usize = undefined;
163 var data_offset: usize = undefined;
164 var thread_data_offset: usize = undefined;
165 // Compute the total size of the ABI-specific data plus our own control
166 // structures
167 const alloc_size = switch (tls_variant) {
168 .VariantI => blk: {
169 var l: usize = 0;
170 dtv_offset = l;
171 l += @sizeOf(DTV);
172 thread_data_offset = l;
173 l += @sizeOf(CustomData);
174 l = mem.alignForward(l, phdr.p_align);
175 tcb_offset = l;
176 if (tls_tcb_align_size) {
177 l += mem.alignForward(tls_tcb_size, phdr.p_align);
178 } else {
179 l += tls_tcb_size;
180 }
181 data_offset = l;
182 l += phdr.p_memsz;
183 break :blk l;
184 },
185 .VariantII => blk: {
186 var l: usize = 0;
187 data_offset = l;
188 l += phdr.p_memsz;
189 l = mem.alignForward(l, phdr.p_align);
190 tcb_offset = l;
191 l += tls_tcb_size;
192 thread_data_offset = l;
193 l += @sizeOf(CustomData);
194 dtv_offset = l;
195 l += @sizeOf(DTV);
196 break :blk l;
197 }
198 };
199
200 tls_image = TLSImage{
201 .data_src = @intToPtr([*]u8, phdr.p_vaddr + img_base)[0..phdr.p_filesz],
202 .alloc_size = alloc_size,
203 .tcb_offset = tcb_offset,
204 .dtv_offset = dtv_offset,
205 .data_offset = data_offset,
206 };
207 }
208}
209
210pub fn copyTLS(addr: usize) usize {
211 const tls_img = tls_image.?;
212
213 // Be paranoid, clear the area we're going to use
214 @memset(@intToPtr([*]u8, addr), 0, tls_img.alloc_size);
215 // Prepare the DTV
216 const dtv = @intToPtr(*DTV, addr + tls_img.dtv_offset);
217 dtv.entries = 1;
218 dtv.tls_block[0] = addr + tls_img.data_offset + tls_dtv_offset;
219 // Set-up the TCB
220 const tcb_ptr = @intToPtr(*usize, addr + tls_img.tcb_offset);
221 if (tls_variant == TLSVariant.VariantI) {
222 tcb_ptr.* = addr + tls_img.dtv_offset;
223 } else {
224 tcb_ptr.* = addr + tls_img.tcb_offset;
225 }
226 // Copy the data
227 @memcpy(@intToPtr([*]u8, addr + tls_img.data_offset), tls_img.data_src.ptr, tls_img.data_src.len);
228
229 // Return the corrected (if needed) value for the tp register
230 return addr + tls_img.tcb_offset + tls_tp_offset;
231}
232
233var main_thread_tls_buffer: [256]u8 align(32) = undefined;
234
235pub fn allocateTLS(size: usize) usize {
236 // Small TLS allocation, use our local buffer
237 if (size < main_thread_tls_buffer.len) {
238 return @ptrToInt(&main_thread_tls_buffer);
239 }
240
241 const addr = posix.mmap(null, size, posix.PROT_READ | posix.PROT_WRITE,
242 posix.MAP_PRIVATE | posix.MAP_ANONYMOUS, -1, 0);
243
244 if (posix.getErrno(addr) != 0) @panic("out of memory");
245
246 return addr;
247}
std/os/linux/x86_64.zig+22-3
...@@ -1,7 +1,9 @@...@@ -1,7 +1,9 @@
1const std = @import("../../std.zig");1const std = @import("../../std.zig");
2const linux = std.os.linux;2const linux = std.os.linux;
3const sockaddr = linux.sockaddr;
3const socklen_t = linux.socklen_t;4const socklen_t = linux.socklen_t;
4const iovec = linux.iovec;5const iovec = linux.iovec;
6const iovec_const = linux.iovec_const;
57
6pub const SYS_read = 0;8pub const SYS_read = 0;
7pub const SYS_write = 1;9pub const SYS_write = 1;
...@@ -386,6 +388,11 @@ pub const VDSO_CGT_VER = "LINUX_2.6";...@@ -386,6 +388,11 @@ pub const VDSO_CGT_VER = "LINUX_2.6";
386pub const VDSO_GETCPU_SYM = "__vdso_getcpu";388pub const VDSO_GETCPU_SYM = "__vdso_getcpu";
387pub const VDSO_GETCPU_VER = "LINUX_2.6";389pub const VDSO_GETCPU_VER = "LINUX_2.6";
388390
391pub const ARCH_SET_GS = 0x1001;
392pub const ARCH_SET_FS = 0x1002;
393pub const ARCH_GET_FS = 0x1003;
394pub const ARCH_GET_GS = 0x1004;
395
389pub fn syscall0(number: usize) usize {396pub fn syscall0(number: usize) usize {
390 return asm volatile ("syscall"397 return asm volatile ("syscall"
391 : [ret] "={rax}" (-> usize)398 : [ret] "={rax}" (-> usize)
...@@ -483,12 +490,24 @@ pub nakedcc fn restore_rt() void {...@@ -483,12 +490,24 @@ pub nakedcc fn restore_rt() void {
483}490}
484491
485pub const msghdr = extern struct {492pub const msghdr = extern struct {
486 msg_name: *u8,493 msg_name: ?*sockaddr,
494 msg_namelen: socklen_t,
495 msg_iov: [*]iovec,
496 msg_iovlen: i32,
497 __pad1: i32,
498 msg_control: ?*c_void,
499 msg_controllen: socklen_t,
500 __pad2: socklen_t,
501 msg_flags: i32,
502};
503
504pub const msghdr_const = extern struct {
505 msg_name: ?*const sockaddr,
487 msg_namelen: socklen_t,506 msg_namelen: socklen_t,
488 msg_iov: *iovec,507 msg_iov: [*]iovec_const,
489 msg_iovlen: i32,508 msg_iovlen: i32,
490 __pad1: i32,509 __pad1: i32,
491 msg_control: *u8,510 msg_control: ?*c_void,
492 msg_controllen: socklen_t,511 msg_controllen: socklen_t,
493 __pad2: socklen_t,512 __pad2: socklen_t,
494 msg_flags: i32,513 msg_flags: i32,
std/os/time.zig+23-7
...@@ -3,41 +3,44 @@ const builtin = @import("builtin");...@@ -3,41 +3,44 @@ const builtin = @import("builtin");
3const Os = builtin.Os;3const Os = builtin.Os;
4const debug = std.debug;4const debug = std.debug;
5const testing = std.testing;5const testing = std.testing;
6const math = std.math;
67
7const windows = std.os.windows;8const windows = std.os.windows;
8const linux = std.os.linux;9const linux = std.os.linux;
9const darwin = std.os.darwin;10const darwin = std.os.darwin;
11const wasi = std.os.wasi;
10const posix = std.os.posix;12const posix = std.os.posix;
1113
12pub const epoch = @import("epoch.zig");14pub const epoch = @import("epoch.zig");
1315
14/// Sleep for the specified duration16/// Spurious wakeups are possible and no precision of timing is guaranteed.
15pub fn sleep(nanoseconds: u64) void {17pub fn sleep(nanoseconds: u64) void {
16 switch (builtin.os) {18 switch (builtin.os) {
17 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {19 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
18 const s = nanoseconds / ns_per_s;20 const s = nanoseconds / ns_per_s;
19 const ns = nanoseconds % ns_per_s;21 const ns = nanoseconds % ns_per_s;
20 posixSleep(@intCast(u63, s), @intCast(u63, ns));22 posixSleep(s, ns);
21 },23 },
22 Os.windows => {24 Os.windows => {
23 const ns_per_ms = ns_per_s / ms_per_s;25 const ns_per_ms = ns_per_s / ms_per_s;
24 const milliseconds = nanoseconds / ns_per_ms;26 const milliseconds = nanoseconds / ns_per_ms;
25 windows.Sleep(@intCast(windows.DWORD, milliseconds));27 const ms_that_will_fit = std.math.cast(windows.DWORD, milliseconds) catch std.math.maxInt(windows.DWORD);
28 windows.Sleep(ms_that_will_fit);
26 },29 },
27 else => @compileError("Unsupported OS"),30 else => @compileError("Unsupported OS"),
28 }31 }
29}32}
3033
31pub fn posixSleep(seconds: u63, nanoseconds: u63) void {34/// Spurious wakeups are possible and no precision of timing is guaranteed.
35pub fn posixSleep(seconds: u64, nanoseconds: u64) void {
32 var req = posix.timespec{36 var req = posix.timespec{
33 .tv_sec = seconds,37 .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize),
34 .tv_nsec = nanoseconds,38 .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize),
35 };39 };
36 var rem: posix.timespec = undefined;40 var rem: posix.timespec = undefined;
37 while (true) {41 while (true) {
38 const ret_val = posix.nanosleep(&req, &rem);42 const ret_val = posix.nanosleep(&req, &rem);
39 const err = posix.getErrno(ret_val);43 const err = posix.getErrno(ret_val);
40 if (err == 0) return;
41 switch (err) {44 switch (err) {
42 posix.EFAULT => unreachable,45 posix.EFAULT => unreachable,
43 posix.EINVAL => {46 posix.EINVAL => {
...@@ -49,6 +52,7 @@ pub fn posixSleep(seconds: u63, nanoseconds: u63) void {...@@ -49,6 +52,7 @@ pub fn posixSleep(seconds: u63, nanoseconds: u63) void {
49 req = rem;52 req = rem;
50 continue;53 continue;
51 },54 },
55 // This prong handles success as well as unexpected errors.
52 else => return,56 else => return,
53 }57 }
54 }58 }
...@@ -64,9 +68,21 @@ pub const milliTimestamp = switch (builtin.os) {...@@ -64,9 +68,21 @@ pub const milliTimestamp = switch (builtin.os) {
64 Os.windows => milliTimestampWindows,68 Os.windows => milliTimestampWindows,
65 Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix,69 Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix,
66 Os.macosx, Os.ios => milliTimestampDarwin,70 Os.macosx, Os.ios => milliTimestampDarwin,
71 Os.wasi => milliTimestampWasi,
67 else => @compileError("Unsupported OS"),72 else => @compileError("Unsupported OS"),
68};73};
6974
75fn milliTimestampWasi() u64 {
76 var ns: wasi.timestamp_t = undefined;
77
78 // TODO: Verify that precision is ignored
79 const err = wasi.clock_time_get(wasi.CLOCK_REALTIME, 1, &ns);
80 debug.assert(err == wasi.ESUCCESS);
81
82 const ns_per_ms = 1000;
83 return @divFloor(ns, ns_per_ms);
84}
85
70fn milliTimestampWindows() u64 {86fn milliTimestampWindows() u64 {
71 //FileTime has a granularity of 100 nanoseconds87 //FileTime has a granularity of 100 nanoseconds
72 // and uses the NTFS/Windows epoch88 // and uses the NTFS/Windows epoch
std/os/wasi.zig created+42
...@@ -0,0 +1,42 @@
1pub use @import("wasi/core.zig");
2
3pub const STDIN_FILENO = 0;
4pub const STDOUT_FILENO = 1;
5pub const STDERR_FILENO = 2;
6
7pub fn getErrno(r: usize) usize {
8 const signed_r = @bitCast(isize, r);
9 return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0;
10}
11
12pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
13 var nwritten: usize = undefined;
14
15 const ciovs = ciovec_t{
16 .buf = buf,
17 .buf_len = count,
18 };
19
20 const err = fd_write(@bitCast(fd_t, isize(fd)), &ciovs, 1, &nwritten);
21 if (err == ESUCCESS) {
22 return nwritten;
23 } else {
24 return @bitCast(usize, -isize(err));
25 }
26}
27
28pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize {
29 var nread: usize = undefined;
30
31 const iovs = iovec_t{
32 .buf = buf,
33 .buf_len = nbyte,
34 };
35
36 const err = fd_read(@bitCast(fd_t, isize(fd)), &iovs, 1, &nread);
37 if (err == ESUCCESS) {
38 return nread;
39 } else {
40 return @bitCast(usize, -isize(err));
41 }
42}
std/os/wasi/core.zig created+374
...@@ -0,0 +1,374 @@
1// Based on https://github.com/CraneStation/wasi-sysroot/blob/wasi/libc-bottom-half/headers/public/wasi/core.h
2// and https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md
3
4pub const advice_t = u8;
5pub const ADVICE_NORMAL: advice_t = 0;
6pub const ADVICE_SEQUENTIAL: advice_t = 1;
7pub const ADVICE_RANDOM: advice_t = 2;
8pub const ADVICE_WILLNEED: advice_t = 3;
9pub const ADVICE_DONTNEED: advice_t = 4;
10pub const ADVICE_NOREUSE: advice_t = 5;
11
12pub const ciovec_t = extern struct {
13 buf: [*]const u8,
14 buf_len: usize,
15};
16
17pub const clockid_t = u32;
18pub const CLOCK_REALTIME: clockid_t = 0;
19pub const CLOCK_MONOTONIC: clockid_t = 1;
20pub const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2;
21pub const CLOCK_THREAD_CPUTIME_ID: clockid_t = 3;
22
23pub const device_t = u64;
24
25pub const dircookie_t = u64;
26pub const DIRCOOKIE_START: dircookie_t = 0;
27
28pub const dirent_t = extern struct {
29 d_next: dircookie_t,
30 d_ino: inode_t,
31 d_namlen: u32,
32 d_type: filetype_t,
33};
34
35pub const errno_t = u16;
36pub const ESUCCESS: errno_t = 0;
37pub const E2BIG: errno_t = 1;
38pub const EACCES: errno_t = 2;
39pub const EADDRINUSE: errno_t = 3;
40pub const EADDRNOTAVAIL: errno_t = 4;
41pub const EAFNOSUPPORT: errno_t = 5;
42pub const EAGAIN: errno_t = 6;
43pub const EALREADY: errno_t = 7;
44pub const EBADF: errno_t = 8;
45pub const EBADMSG: errno_t = 9;
46pub const EBUSY: errno_t = 10;
47pub const ECANCELED: errno_t = 11;
48pub const ECHILD: errno_t = 12;
49pub const ECONNABORTED: errno_t = 13;
50pub const ECONNREFUSED: errno_t = 14;
51pub const ECONNRESET: errno_t = 15;
52pub const EDEADLK: errno_t = 16;
53pub const EDESTADDRREQ: errno_t = 17;
54pub const EDOM: errno_t = 18;
55pub const EDQUOT: errno_t = 19;
56pub const EEXIST: errno_t = 20;
57pub const EFAULT: errno_t = 21;
58pub const EFBIG: errno_t = 22;
59pub const EHOSTUNREACH: errno_t = 23;
60pub const EIDRM: errno_t = 24;
61pub const EILSEQ: errno_t = 25;
62pub const EINPROGRESS: errno_t = 26;
63pub const EINTR: errno_t = 27;
64pub const EINVAL: errno_t = 28;
65pub const EIO: errno_t = 29;
66pub const EISCONN: errno_t = 30;
67pub const EISDIR: errno_t = 31;
68pub const ELOOP: errno_t = 32;
69pub const EMFILE: errno_t = 33;
70pub const EMLINK: errno_t = 34;
71pub const EMSGSIZE: errno_t = 35;
72pub const EMULTIHOP: errno_t = 36;
73pub const ENAMETOOLONG: errno_t = 37;
74pub const ENETDOWN: errno_t = 38;
75pub const ENETRESET: errno_t = 39;
76pub const ENETUNREACH: errno_t = 40;
77pub const ENFILE: errno_t = 41;
78pub const ENOBUFS: errno_t = 42;
79pub const ENODEV: errno_t = 43;
80pub const ENOENT: errno_t = 44;
81pub const ENOEXEC: errno_t = 45;
82pub const ENOLCK: errno_t = 46;
83pub const ENOLINK: errno_t = 47;
84pub const ENOMEM: errno_t = 48;
85pub const ENOMSG: errno_t = 49;
86pub const ENOPROTOOPT: errno_t = 50;
87pub const ENOSPC: errno_t = 51;
88pub const ENOSYS: errno_t = 52;
89pub const ENOTCONN: errno_t = 53;
90pub const ENOTDIR: errno_t = 54;
91pub const ENOTEMPTY: errno_t = 55;
92pub const ENOTRECOVERABLE: errno_t = 56;
93pub const ENOTSOCK: errno_t = 57;
94pub const ENOTSUP: errno_t = 58;
95pub const ENOTTY: errno_t = 59;
96pub const ENXIO: errno_t = 60;
97pub const EOVERFLOW: errno_t = 61;
98pub const EOWNERDEAD: errno_t = 62;
99pub const EPERM: errno_t = 63;
100pub const EPIPE: errno_t = 64;
101pub const EPROTO: errno_t = 65;
102pub const EPROTONOSUPPORT: errno_t = 66;
103pub const EPROTOTYPE: errno_t = 67;
104pub const ERANGE: errno_t = 68;
105pub const EROFS: errno_t = 69;
106pub const ESPIPE: errno_t = 70;
107pub const ESRCH: errno_t = 71;
108pub const ESTALE: errno_t = 72;
109pub const ETIMEDOUT: errno_t = 73;
110pub const ETXTBSY: errno_t = 74;
111pub const EXDEV: errno_t = 75;
112pub const ENOTCAPABLE: errno_t = 76;
113
114pub const event_t = extern struct {
115 userdata: userdata_t,
116 @"error": errno_t,
117 @"type": eventtype_t,
118 u: extern union {
119 fd_readwrite: extern struct {
120 nbytes: filesize_t,
121 flags: eventrwflags_t,
122 },
123 },
124};
125
126pub const eventrwflags_t = u16;
127pub const EVENT_FD_READWRITE_HANGUP: eventrwflags_t = 0x0001;
128
129pub const eventtype_t = u8;
130pub const EVENTTYPE_CLOCK: eventtype_t = 0;
131pub const EVENTTYPE_FD_READ: eventtype_t = 1;
132pub const EVENTTYPE_FD_WRITE: eventtype_t = 2;
133
134pub const exitcode_t = u32;
135
136pub const fd_t = u32;
137
138pub const fdflags_t = u16;
139pub const FDFLAG_APPEND: fdflags_t = 0x0001;
140pub const FDFLAG_DSYNC: fdflags_t = 0x0002;
141pub const FDFLAG_NONBLOCK: fdflags_t = 0x0004;
142pub const FDFLAG_RSYNC: fdflags_t = 0x0008;
143pub const FDFLAG_SYNC: fdflags_t = 0x0010;
144
145const fdstat_t = extern struct {
146 fs_filetype: filetype_t,
147 fs_flags: fdflags_t,
148 fs_rights_base: rights_t,
149 fs_rights_inheriting: rights_t,
150};
151
152pub const filedelta_t = i64;
153
154pub const filesize_t = u64;
155
156pub const filestat_t = extern struct {
157 st_dev: device_t,
158 st_ino: inode_t,
159 st_filetype: filetype_t,
160 st_nlink: linkcount_t,
161 st_size: filesize_t,
162 st_atim: timestamp_t,
163 st_mtim: timestamp_t,
164 st_ctim: timestamp_t,
165};
166
167pub const filetype_t = u8;
168pub const FILETYPE_UNKNOWN: filetype_t = 0;
169pub const FILETYPE_BLOCK_DEVICE: filetype_t = 1;
170pub const FILETYPE_CHARACTER_DEVICE: filetype_t = 2;
171pub const FILETYPE_DIRECTORY: filetype_t = 3;
172pub const FILETYPE_REGULAR_FILE: filetype_t = 4;
173pub const FILETYPE_SOCKET_DGRAM: filetype_t = 5;
174pub const FILETYPE_SOCKET_STREAM: filetype_t = 6;
175pub const FILETYPE_SYMBOLIC_LINK: filetype_t = 7;
176
177pub const fstflags_t = u16;
178pub const FILESTAT_SET_ATIM: fstflags_t = 0x0001;
179pub const FILESTAT_SET_ATIM_NOW: fstflags_t = 0x0002;
180pub const FILESTAT_SET_MTIM: fstflags_t = 0x0004;
181pub const FILESTAT_SET_MTIM_NOW: fstflags_t = 0x0008;
182
183pub const inode_t = u64;
184
185pub const iovec_t = extern struct {
186 buf: [*]u8,
187 buf_len: usize,
188};
189
190pub const linkcount_t = u32;
191
192pub const lookupflags_t = u32;
193pub const LOOKUP_SYMLINK_FOLLOW: lookupflags_t = 0x00000001;
194
195pub const oflags_t = u16;
196pub const O_CREAT: oflags_t = 0x0001;
197pub const O_DIRECTORY: oflags_t = 0x0002;
198pub const O_EXCL: oflags_t = 0x0004;
199pub const O_TRUNC: oflags_t = 0x0008;
200
201pub const preopentype_t = u8;
202pub const PREOPENTYPE_DIR: preopentype_t = 0;
203
204pub const prestat_t = extern struct {
205 pr_type: preopentype_t,
206 u: extern union {
207 dir: extern struct {
208 pr_name_len: usize,
209 },
210 },
211};
212
213pub const riflags_t = u16;
214pub const SOCK_RECV_PEEK: riflags_t = 0x0001;
215pub const SOCK_RECV_WAITALL: riflags_t = 0x0002;
216
217pub const rights_t = u64;
218pub const RIGHT_FD_DATASYNC: rights_t = 0x0000000000000001;
219pub const RIGHT_FD_READ: rights_t = 0x0000000000000002;
220pub const RIGHT_FD_SEEK: rights_t = 0x0000000000000004;
221pub const RIGHT_FD_FDSTAT_SET_FLAGS: rights_t = 0x0000000000000008;
222pub const RIGHT_FD_SYNC: rights_t = 0x0000000000000010;
223pub const RIGHT_FD_TELL: rights_t = 0x0000000000000020;
224pub const RIGHT_FD_WRITE: rights_t = 0x0000000000000040;
225pub const RIGHT_FD_ADVISE: rights_t = 0x0000000000000080;
226pub const RIGHT_FD_ALLOCATE: rights_t = 0x0000000000000100;
227pub const RIGHT_PATH_CREATE_DIRECTORY: rights_t = 0x0000000000000200;
228pub const RIGHT_PATH_CREATE_FILE: rights_t = 0x0000000000000400;
229pub const RIGHT_PATH_LINK_SOURCE: rights_t = 0x0000000000000800;
230pub const RIGHT_PATH_LINK_TARGET: rights_t = 0x0000000000001000;
231pub const RIGHT_PATH_OPEN: rights_t = 0x0000000000002000;
232pub const RIGHT_FD_READDIR: rights_t = 0x0000000000004000;
233pub const RIGHT_PATH_READLINK: rights_t = 0x0000000000008000;
234pub const RIGHT_PATH_RENAME_SOURCE: rights_t = 0x0000000000010000;
235pub const RIGHT_PATH_RENAME_TARGET: rights_t = 0x0000000000020000;
236pub const RIGHT_PATH_FILESTAT_GET: rights_t = 0x0000000000040000;
237pub const RIGHT_PATH_FILESTAT_SET_SIZE: rights_t = 0x0000000000080000;
238pub const RIGHT_PATH_FILESTAT_SET_TIMES: rights_t = 0x0000000000100000;
239pub const RIGHT_FD_FILESTAT_GET: rights_t = 0x0000000000200000;
240pub const RIGHT_FD_FILESTAT_SET_SIZE: rights_t = 0x0000000000400000;
241pub const RIGHT_FD_FILESTAT_SET_TIMES: rights_t = 0x0000000000800000;
242pub const RIGHT_PATH_SYMLINK: rights_t = 0x0000000001000000;
243pub const RIGHT_PATH_REMOVE_DIRECTORY: rights_t = 0x0000000002000000;
244pub const RIGHT_PATH_UNLINK_FILE: rights_t = 0x0000000004000000;
245pub const RIGHT_POLL_FD_READWRITE: rights_t = 0x0000000008000000;
246pub const RIGHT_SOCK_SHUTDOWN: rights_t = 0x0000000010000000;
247
248pub const roflags_t = u16;
249pub const SOCK_RECV_DATA_TRUNCATED: roflags_t = 0x0001;
250
251pub const sdflags_t = u8;
252pub const SHUT_RD: sdflags_t = 0x01;
253pub const SHUT_WR: sdflags_t = 0x02;
254
255pub const siflags_t = u16;
256
257pub const signal_t = u8;
258pub const SIGHUP: signal_t = 1;
259pub const SIGINT: signal_t = 2;
260pub const SIGQUIT: signal_t = 3;
261pub const SIGILL: signal_t = 4;
262pub const SIGTRAP: signal_t = 5;
263pub const SIGABRT: signal_t = 6;
264pub const SIGBUS: signal_t = 7;
265pub const SIGFPE: signal_t = 8;
266pub const SIGKILL: signal_t = 9;
267pub const SIGUSR1: signal_t = 10;
268pub const SIGSEGV: signal_t = 11;
269pub const SIGUSR2: signal_t = 12;
270pub const SIGPIPE: signal_t = 13;
271pub const SIGALRM: signal_t = 14;
272pub const SIGTERM: signal_t = 15;
273pub const SIGCHLD: signal_t = 16;
274pub const SIGCONT: signal_t = 17;
275pub const SIGSTOP: signal_t = 18;
276pub const SIGTSTP: signal_t = 19;
277pub const SIGTTIN: signal_t = 20;
278pub const SIGTTOU: signal_t = 21;
279pub const SIGURG: signal_t = 22;
280pub const SIGXCPU: signal_t = 23;
281pub const SIGXFSZ: signal_t = 24;
282pub const SIGVTALRM: signal_t = 25;
283pub const SIGPROF: signal_t = 26;
284pub const SIGWINCH: signal_t = 27;
285pub const SIGPOLL: signal_t = 28;
286pub const SIGPWR: signal_t = 29;
287pub const SIGSYS: signal_t = 30;
288
289pub const subclockflags_t = u16;
290pub const SUBSCRIPTION_CLOCK_ABSTIME: subclockflags_t = 0x0001;
291
292pub const subscription_t = extern struct {
293 userdata: userdata_t,
294 @"type": eventtype_t,
295 u: extern union {
296 clock: extern struct {
297 identifier: userdata_t,
298 clock_id: clockid_t,
299 timeout: timestamp_t,
300 precision: timestamp_t,
301 flags: subclockflags_t,
302 },
303 fd_readwrite: extern struct {
304 fd: fd_t,
305 },
306 },
307};
308
309pub const timestamp_t = u64;
310
311pub const userdata_t = u64;
312
313pub const whence_t = u8;
314pub const WHENCE_CUR: whence_t = 0;
315pub const WHENCE_END: whence_t = 1;
316pub const WHENCE_SET: whence_t = 2;
317
318pub extern "wasi_unstable" fn args_get(argv: [*][*]u8, argv_buf: [*]u8) errno_t;
319pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
320
321pub extern "wasi_unstable" fn clock_res_get(clock_id: clockid_t, resolution: *timestamp_t) errno_t;
322pub extern "wasi_unstable" fn clock_time_get(clock_id: clockid_t, precision: timestamp_t, timestamp: *timestamp_t) errno_t;
323
324pub extern "wasi_unstable" fn environ_get(environ: [*]?[*]u8, environ_buf: [*]u8) errno_t;
325pub extern "wasi_unstable" fn environ_sizes_get(environ_count: *usize, environ_buf_size: *usize) errno_t;
326
327pub extern "wasi_unstable" fn fd_advise(fd: fd_t, offset: filesize_t, len: filesize_t, advice: advice_t) errno_t;
328pub extern "wasi_unstable" fn fd_allocate(fd: fd_t, offset: filesize_t, len: filesize_t) errno_t;
329pub extern "wasi_unstable" fn fd_close(fd: fd_t) errno_t;
330pub extern "wasi_unstable" fn fd_datasync(fd: fd_t) errno_t;
331pub extern "wasi_unstable" fn fd_pread(fd: fd_t, iovs: *const iovec_t, iovs_len: usize, offset: filesize_t, nread: *usize) errno_t;
332pub extern "wasi_unstable" fn fd_pwrite(fd: fd_t, iovs: *const ciovec_t, iovs_len: usize, offset: filesize_t, nwritten: *usize) errno_t;
333pub extern "wasi_unstable" fn fd_read(fd: fd_t, iovs: *const iovec_t, iovs_len: usize, nread: *usize) errno_t;
334pub extern "wasi_unstable" fn fd_readdir(fd: fd_t, buf: [*]u8, buf_len: usize, cookie: dircookie_t, bufused: *usize) errno_t;
335pub extern "wasi_unstable" fn fd_renumber(from: fd_t, to: fd_t) errno_t;
336pub extern "wasi_unstable" fn fd_seek(fd: fd_t, offset: filedelta_t, whence: whence_t, newoffset: *filesize_t) errno_t;
337pub extern "wasi_unstable" fn fd_sync(fd: fd_t) errno_t;
338pub extern "wasi_unstable" fn fd_tell(fd: fd_t, newoffset: *filesize_t) errno_t;
339pub extern "wasi_unstable" fn fd_write(fd: fd_t, iovs: *const ciovec_t, iovs_len: usize, nwritten: *usize) errno_t;
340
341pub extern "wasi_unstable" fn fd_fdstat_get(fd: fd_t, buf: *fdstat_t) errno_t;
342pub extern "wasi_unstable" fn fd_fdstat_set_flags(fd: fd_t, flags: fdflags_t) errno_t;
343pub extern "wasi_unstable" fn fd_fdstat_set_rights(fd: fd_t, fs_rights_base: rights_t, fs_rights_inheriting: rights_t) errno_t;
344
345pub extern "wasi_unstable" fn fd_filestat_get(fd: fd_t, buf: *filestat_t) errno_t;
346pub extern "wasi_unstable" fn fd_filestat_set_size(fd: fd_t, st_size: filesize_t) errno_t;
347pub extern "wasi_unstable" fn fd_filestat_set_times(fd: fd_t, st_atim: timestamp_t, st_mtim: timestamp_t, fstflags: fstflags_t) errno_t;
348
349pub extern "wasi_unstable" fn fd_prestat_get(fd: fd_t, buf: *prestat_t) errno_t;
350pub extern "wasi_unstable" fn fd_prestat_dir_name(fd: fd_t, path: [*]u8, path_len: usize) errno_t;
351
352pub extern "wasi_unstable" fn path_create_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;
353pub extern "wasi_unstable" fn path_filestat_get(fd: fd_t, flags: lookupflags_t, path: [*]const u8, path_len: usize, buf: *filestat_t) errno_t;
354pub 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;
355pub 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;
356pub 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;
357pub extern "wasi_unstable" fn path_readlink(fd: fd_t, path: [*]const u8, path_len: usize, buf: [*]u8, buf_len: usize, bufused: *usize) errno_t;
358pub extern "wasi_unstable" fn path_remove_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;
359pub 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;
360pub 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;
361pub extern "wasi_unstable" fn path_unlink_file(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;
362
363pub extern "wasi_unstable" fn poll_oneoff(in: *const subscription_t, out: *event_t, nsubscriptions: usize, nevents: *usize) errno_t;
364
365pub extern "wasi_unstable" fn proc_exit(rval: exitcode_t) noreturn;
366pub extern "wasi_unstable" fn proc_raise(sig: signal_t) errno_t;
367
368pub extern "wasi_unstable" fn random_get(buf: [*]u8, buf_len: usize) errno_t;
369
370pub extern "wasi_unstable" fn sched_yield() errno_t;
371
372pub 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;
373pub 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;
374pub extern "wasi_unstable" fn sock_shutdown(sock: fd_t, how: sdflags_t) errno_t;
std/os/windows.zig+31
...@@ -239,6 +239,37 @@ pub const HEAP_CREATE_ENABLE_EXECUTE = 0x00040000;...@@ -239,6 +239,37 @@ pub const HEAP_CREATE_ENABLE_EXECUTE = 0x00040000;
239pub const HEAP_GENERATE_EXCEPTIONS = 0x00000004;239pub const HEAP_GENERATE_EXCEPTIONS = 0x00000004;
240pub const HEAP_NO_SERIALIZE = 0x00000001;240pub const HEAP_NO_SERIALIZE = 0x00000001;
241241
242// AllocationType values
243pub const MEM_COMMIT = 0x1000;
244pub const MEM_RESERVE = 0x2000;
245pub const MEM_RESET = 0x80000;
246pub const MEM_RESET_UNDO = 0x1000000;
247pub const MEM_LARGE_PAGES = 0x20000000;
248pub const MEM_PHYSICAL = 0x400000;
249pub const MEM_TOP_DOWN = 0x100000;
250pub const MEM_WRITE_WATCH = 0x200000;
251
252// Protect values
253pub const PAGE_EXECUTE = 0x10;
254pub const PAGE_EXECUTE_READ = 0x20;
255pub const PAGE_EXECUTE_READWRITE = 0x40;
256pub const PAGE_EXECUTE_WRITECOPY = 0x80;
257pub const PAGE_NOACCESS = 0x01;
258pub const PAGE_READONLY = 0x02;
259pub const PAGE_READWRITE = 0x04;
260pub const PAGE_WRITECOPY = 0x08;
261pub const PAGE_TARGETS_INVALID = 0x40000000;
262pub const PAGE_TARGETS_NO_UPDATE = 0x40000000; // Same as PAGE_TARGETS_INVALID
263pub const PAGE_GUARD = 0x100;
264pub const PAGE_NOCACHE = 0x200;
265pub const PAGE_WRITECOMBINE = 0x400;
266
267// FreeType values
268pub const MEM_COALESCE_PLACEHOLDERS = 0x1;
269pub const MEM_RESERVE_PLACEHOLDERS = 0x2;
270pub const MEM_DECOMMIT = 0x4000;
271pub const MEM_RELEASE = 0x8000;
272
242pub const PTHREAD_START_ROUTINE = extern fn (LPVOID) DWORD;273pub const PTHREAD_START_ROUTINE = extern fn (LPVOID) DWORD;
243pub const LPTHREAD_START_ROUTINE = PTHREAD_START_ROUTINE;274pub const LPTHREAD_START_ROUTINE = PTHREAD_START_ROUTINE;
244275
std/os/windows/kernel32.zig+3
...@@ -116,6 +116,9 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem...@@ -116,6 +116,9 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem
116116
117pub extern "kernel32" stdcallcc fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*const c_void) BOOL;117pub extern "kernel32" stdcallcc fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*const c_void) BOOL;
118118
119pub extern "kernel32" stdcallcc fn VirtualAlloc(lpAddress: ?LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD) ?LPVOID;
120pub extern "kernel32" stdcallcc fn VirtualFree(lpAddress: ?LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) BOOL;
121
119pub extern "kernel32" stdcallcc fn MoveFileExW(122pub extern "kernel32" stdcallcc fn MoveFileExW(
120 lpExistingFileName: [*]const u16,123 lpExistingFileName: [*]const u16,
121 lpNewFileName: [*]const u16,124 lpNewFileName: [*]const u16,
std/packed_int_array.zig created+649
...@@ -0,0 +1,649 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const debug = std.debug;
4const testing = std.testing;
5
6pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
7 //The general technique employed here is to cast bytes in the array to a container
8 // integer (having bits % 8 == 0) large enough to contain the number of bits we want,
9 // then we can retrieve or store the new value with a relative minimum of masking
10 // and shifting. In this worst case, this means that we'll need an integer that's
11 // actually 1 byte larger than the minimum required to store the bits, because it
12 // is possible that the bits start at the end of the first byte, continue through
13 // zero or more, then end in the beginning of the last. But, if we try to access
14 // a value in the very last byte of memory with that integer size, that extra byte
15 // will be out of bounds. Depending on the circumstances of the memory, that might
16 // mean the OS fatally kills the program. Thus, we use a larger container (MaxIo)
17 // most of the time, but a smaller container (MinIo) when touching the last byte
18 // of the memory.
19 const int_bits = comptime std.meta.bitCount(Int);
20
21 //in the best case, this is the number of bytes we need to touch
22 // to read or write a value, as bits
23 const min_io_bits = ((int_bits + 7) / 8) * 8;
24
25 //in the worst case, this is the number of bytes we need to touch
26 // to read or write a value, as bits
27 const max_io_bits = switch (int_bits) {
28 0 => 0,
29 1 => 8,
30 2...9 => 16,
31 10...65535 => ((int_bits / 8) + 2) * 8,
32 else => unreachable,
33 };
34
35 //we bitcast the desired Int type to an unsigned version of itself
36 // to avoid issues with shifting signed ints.
37 const UnInt = @IntType(false, int_bits);
38
39 //The maximum container int type
40 const MinIo = @IntType(false, min_io_bits);
41
42 //The minimum container int type
43 const MaxIo = @IntType(false, max_io_bits);
44
45 return struct {
46 pub fn get(bytes: []const u8, index: usize, bit_offset: u7) Int {
47 if (int_bits == 0) return 0;
48
49 const bit_index = (index * int_bits) + bit_offset;
50 const max_end_byte = (bit_index + max_io_bits) / 8;
51
52 //Using the larger container size will potentially read out of bounds
53 if (max_end_byte > bytes.len) return getBits(bytes, MinIo, bit_index);
54 return getBits(bytes, MaxIo, bit_index);
55 }
56
57 fn getBits(bytes: []const u8, comptime Container: type, bit_index: usize) Int {
58 const container_bits = comptime std.meta.bitCount(Container);
59 const Shift = std.math.Log2Int(Container);
60
61 const start_byte = bit_index / 8;
62 const head_keep_bits = bit_index - (start_byte * 8);
63 const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
64
65 //read bytes as container
66 const value_ptr = @ptrCast(*align(1) const Container, &bytes[start_byte]);
67 var value = value_ptr.*;
68
69 if (endian != builtin.endian) value = @bswap(Container, value);
70
71 switch (endian) {
72 .Big => {
73 value <<= @intCast(Shift, head_keep_bits);
74 value >>= @intCast(Shift, head_keep_bits);
75 value >>= @intCast(Shift, tail_keep_bits);
76 },
77 .Little => {
78 value <<= @intCast(Shift, tail_keep_bits);
79 value >>= @intCast(Shift, tail_keep_bits);
80 value >>= @intCast(Shift, head_keep_bits);
81 },
82 }
83
84 return @bitCast(Int, @truncate(UnInt, value));
85 }
86
87 pub fn set(bytes: []u8, index: usize, bit_offset: u3, int: Int) void {
88 if (int_bits == 0) return;
89
90 const bit_index = (index * int_bits) + bit_offset;
91 const max_end_byte = (bit_index + max_io_bits) / 8;
92
93 //Using the larger container size will potentially write out of bounds
94 if (max_end_byte > bytes.len) return setBits(bytes, MinIo, bit_index, int);
95 setBits(bytes, MaxIo, bit_index, int);
96 }
97
98 fn setBits(bytes: []u8, comptime Container: type, bit_index: usize, int: Int) void {
99 const container_bits = comptime std.meta.bitCount(Container);
100 const Shift = std.math.Log2Int(Container);
101
102 const start_byte = bit_index / 8;
103 const head_keep_bits = bit_index - (start_byte * 8);
104 const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
105 const keep_shift = switch (endian) {
106 .Big => @intCast(Shift, tail_keep_bits),
107 .Little => @intCast(Shift, head_keep_bits),
108 };
109
110 //position the bits where they need to be in the container
111 const value = @intCast(Container, @bitCast(UnInt, int)) << keep_shift;
112
113 //read existing bytes
114 const target_ptr = @ptrCast(*align(1) Container, &bytes[start_byte]);
115 var target = target_ptr.*;
116
117 if (endian != builtin.endian) target = @bswap(Container, target);
118
119 //zero the bits we want to replace in the existing bytes
120 const inv_mask = @intCast(Container, std.math.maxInt(UnInt)) << keep_shift;
121 const mask = ~inv_mask;
122 target &= mask;
123
124 //merge the new value
125 target |= value;
126
127 if (endian != builtin.endian) target = @bswap(Container, target);
128
129 //save it back
130 target_ptr.* = target;
131 }
132
133 fn slice(bytes: []u8, bit_offset: u3, start: usize, end: usize) PackedIntSliceEndian(Int, endian) {
134 debug.assert(end >= start);
135
136 const length = end - start;
137 const bit_index = (start * int_bits) + bit_offset;
138 const start_byte = bit_index / 8;
139 const end_byte = (bit_index + (length * int_bits) + 7) / 8;
140 const new_bytes = bytes[start_byte..end_byte];
141
142 if (length == 0) return PackedIntSliceEndian(Int, endian).init(new_bytes[0..0], 0);
143
144 var new_slice = PackedIntSliceEndian(Int, endian).init(new_bytes, length);
145 new_slice.bit_offset = @intCast(u3, (bit_index - (start_byte * 8)));
146 return new_slice;
147 }
148
149 fn sliceCast(bytes: []u8, comptime NewInt: type, comptime new_endian: builtin.Endian, bit_offset: u3, old_len: usize) PackedIntSliceEndian(NewInt, new_endian) {
150 const new_int_bits = comptime std.meta.bitCount(NewInt);
151 const New = PackedIntSliceEndian(NewInt, new_endian);
152
153 const total_bits = (old_len * int_bits);
154 const new_int_count = total_bits / new_int_bits;
155
156 debug.assert(total_bits == new_int_count * new_int_bits);
157
158 var new = New.init(bytes, new_int_count);
159 new.bit_offset = bit_offset;
160
161 return new;
162 }
163 };
164}
165
166///Creates a bit-packed array of integers of type Int. Bits
167/// are packed using native endianess and without storing any meta
168/// data. PackedIntArray(i3, 8) will occupy exactly 3 bytes of memory.
169pub fn PackedIntArray(comptime Int: type, comptime int_count: usize) type {
170 return PackedIntArrayEndian(Int, builtin.endian, int_count);
171}
172
173///Creates a bit-packed array of integers of type Int. Bits
174/// are packed using specified endianess and without storing any meta
175/// data.
176pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian, comptime int_count: usize) type {
177 const int_bits = comptime std.meta.bitCount(Int);
178 const total_bits = int_bits * int_count;
179 const total_bytes = (total_bits + 7) / 8;
180
181 const Io = PackedIntIo(Int, endian);
182
183 return struct {
184 const Self = @This();
185
186 bytes: [total_bytes]u8,
187
188 ///Returns the number of elements in the packed array
189 pub fn len(self: Self) usize {
190 return int_count;
191 }
192
193 ///Initialize a packed array using an unpacked array
194 /// or, more likely, an array literal.
195 pub fn init(ints: [int_count]Int) Self {
196 var self = Self(undefined);
197 for (ints) |int, i| self.set(i, int);
198 return self;
199 }
200
201 ///Return the Int stored at index
202 pub fn get(self: Self, index: usize) Int {
203 debug.assert(index < int_count);
204 return Io.get(self.bytes, index, 0);
205 }
206
207 ///Copy int into the array at index
208 pub fn set(self: *Self, index: usize, int: Int) void {
209 debug.assert(index < int_count);
210 return Io.set(&self.bytes, index, 0, int);
211 }
212
213 ///Create a PackedIntSlice of the array from given start to given end
214 pub fn slice(self: *Self, start: usize, end: usize) PackedIntSliceEndian(Int, endian) {
215 debug.assert(start < int_count);
216 debug.assert(end <= int_count);
217 return Io.slice(&self.bytes, 0, start, end);
218 }
219
220 ///Create a PackedIntSlice of the array using NewInt as the bit width integer.
221 /// NewInt's bit width must fit evenly within the array's Int's total bits.
222 pub fn sliceCast(self: *Self, comptime NewInt: type) PackedIntSlice(NewInt) {
223 return self.sliceCastEndian(NewInt, endian);
224 }
225
226 ///Create a PackedIntSlice of the array using NewInt as the bit width integer
227 /// and new_endian as the new endianess. NewInt's bit width must fit evenly within
228 /// the array's Int's total bits.
229 pub fn sliceCastEndian(self: *Self, comptime NewInt: type, comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian) {
230 return Io.sliceCast(&self.bytes, NewInt, new_endian, 0, int_count);
231 }
232 };
233}
234
235///Uses a slice as a bit-packed block of int_count integers of type Int.
236/// Bits are packed using native endianess and without storing any meta
237/// data.
238pub fn PackedIntSlice(comptime Int: type) type {
239 return PackedIntSliceEndian(Int, builtin.endian);
240}
241
242///Uses a slice as a bit-packed block of int_count integers of type Int.
243/// Bits are packed using specified endianess and without storing any meta
244/// data.
245pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian) type {
246 const int_bits = comptime std.meta.bitCount(Int);
247 const Io = PackedIntIo(Int, endian);
248
249 return struct {
250 const Self = @This();
251
252 bytes: []u8,
253 int_count: usize,
254 bit_offset: u3,
255
256 ///Returns the number of elements in the packed slice
257 pub fn len(self: Self) usize {
258 return self.int_count;
259 }
260
261 ///Calculates the number of bytes required to store a desired count
262 /// of Ints
263 pub fn bytesRequired(int_count: usize) usize {
264 const total_bits = int_bits * int_count;
265 const total_bytes = (total_bits + 7) / 8;
266 return total_bytes;
267 }
268
269 ///Initialize a packed slice using the memory at bytes, with int_count
270 /// elements. bytes must be large enough to accomodate the requested
271 /// count.
272 pub fn init(bytes: []u8, int_count: usize) Self {
273 debug.assert(bytes.len >= bytesRequired(int_count));
274
275 return Self{
276 .bytes = bytes,
277 .int_count = int_count,
278 .bit_offset = 0,
279 };
280 }
281
282 ///Return the Int stored at index
283 pub fn get(self: Self, index: usize) Int {
284 debug.assert(index < self.int_count);
285 return Io.get(self.bytes, index, self.bit_offset);
286 }
287
288 ///Copy int into the array at index
289 pub fn set(self: *Self, index: usize, int: Int) void {
290 debug.assert(index < self.int_count);
291 return Io.set(self.bytes, index, self.bit_offset, int);
292 }
293
294 ///Create a PackedIntSlice of this slice from given start to given end
295 pub fn slice(self: Self, start: usize, end: usize) PackedIntSliceEndian(Int, endian) {
296 debug.assert(start < self.int_count);
297 debug.assert(end <= self.int_count);
298 return Io.slice(self.bytes, self.bit_offset, start, end);
299 }
300
301 ///Create a PackedIntSlice of this slice using NewInt as the bit width integer.
302 /// NewInt's bit width must fit evenly within this slice's Int's total bits.
303 pub fn sliceCast(self: Self, comptime NewInt: type) PackedIntSliceEndian(NewInt, endian) {
304 return self.sliceCastEndian(NewInt, endian);
305 }
306
307 ///Create a PackedIntSlice of this slice using NewInt as the bit width integer
308 /// and new_endian as the new endianess. NewInt's bit width must fit evenly within
309 /// this slice's Int's total bits.
310 pub fn sliceCastEndian(self: Self, comptime NewInt: type, comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian) {
311 return Io.sliceCast(self.bytes, NewInt, new_endian, self.bit_offset, self.int_count);
312 }
313 };
314}
315
316test "PackedIntArray" {
317 @setEvalBranchQuota(10000);
318 const max_bits = 256;
319 const int_count = 19;
320
321 comptime var bits = 0;
322 inline while (bits <= 256) : (bits += 1) {
323 //alternate unsigned and signed
324 const even = bits % 2 == 0;
325 const I = @IntType(even, bits);
326
327 const PackedArray = PackedIntArray(I, int_count);
328 const expected_bytes = ((bits * int_count) + 7) / 8;
329 testing.expect(@sizeOf(PackedArray) == expected_bytes);
330
331 var data = PackedArray(undefined);
332
333 //write values, counting up
334 var i = usize(0);
335 var count = I(0);
336 while (i < data.len()) : (i += 1) {
337 data.set(i, count);
338 if (bits > 0) count +%= 1;
339 }
340
341 //read and verify values
342 i = 0;
343 count = 0;
344 while (i < data.len()) : (i += 1) {
345 const val = data.get(i);
346 testing.expect(val == count);
347 if (bits > 0) count +%= 1;
348 }
349 }
350}
351
352test "PackedIntArray init" {
353 const PackedArray = PackedIntArray(u3, 8);
354 var packed_array = PackedArray.init([]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
355 var i = usize(0);
356 while (i < packed_array.len()) : (i += 1) testing.expect(packed_array.get(i) == i);
357}
358
359test "PackedIntSlice" {
360 @setEvalBranchQuota(10000);
361 const max_bits = 256;
362 const int_count = 19;
363 const total_bits = max_bits * int_count;
364 const total_bytes = (total_bits + 7) / 8;
365
366 var buffer: [total_bytes]u8 = undefined;
367
368 comptime var bits = 0;
369 inline while (bits <= 256) : (bits += 1) {
370 //alternate unsigned and signed
371 const even = bits % 2 == 0;
372 const I = @IntType(even, bits);
373 const P = PackedIntSlice(I);
374
375 var data = P.init(&buffer, int_count);
376
377 //write values, counting up
378 var i = usize(0);
379 var count = I(0);
380 while (i < data.len()) : (i += 1) {
381 data.set(i, count);
382 if (bits > 0) count +%= 1;
383 }
384
385 //read and verify values
386 i = 0;
387 count = 0;
388 while (i < data.len()) : (i += 1) {
389 const val = data.get(i);
390 testing.expect(val == count);
391 if (bits > 0) count +%= 1;
392 }
393 }
394}
395
396test "PackedIntSlice of PackedInt(Array/Slice)" {
397 const max_bits = 16;
398 const int_count = 19;
399
400 comptime var bits = 0;
401 inline while (bits <= max_bits) : (bits += 1) {
402 const Int = @IntType(false, bits);
403
404 const PackedArray = PackedIntArray(Int, int_count);
405 var packed_array = PackedArray(undefined);
406
407 const limit = (1 << bits);
408
409 var i = usize(0);
410 while (i < packed_array.len()) : (i += 1) {
411 packed_array.set(i, @intCast(Int, i % limit));
412 }
413
414 //slice of array
415 var packed_slice = packed_array.slice(2, 5);
416 testing.expect(packed_slice.len() == 3);
417 const ps_bit_count = (bits * packed_slice.len()) + packed_slice.bit_offset;
418 const ps_expected_bytes = (ps_bit_count + 7) / 8;
419 testing.expect(packed_slice.bytes.len == ps_expected_bytes);
420 testing.expect(packed_slice.get(0) == 2 % limit);
421 testing.expect(packed_slice.get(1) == 3 % limit);
422 testing.expect(packed_slice.get(2) == 4 % limit);
423 packed_slice.set(1, 7 % limit);
424 testing.expect(packed_slice.get(1) == 7 % limit);
425
426 //write through slice
427 testing.expect(packed_array.get(3) == 7 % limit);
428
429 //slice of a slice
430 const packed_slice_two = packed_slice.slice(0, 3);
431 testing.expect(packed_slice_two.len() == 3);
432 const ps2_bit_count = (bits * packed_slice_two.len()) + packed_slice_two.bit_offset;
433 const ps2_expected_bytes = (ps2_bit_count + 7) / 8;
434 testing.expect(packed_slice_two.bytes.len == ps2_expected_bytes);
435 testing.expect(packed_slice_two.get(1) == 7 % limit);
436 testing.expect(packed_slice_two.get(2) == 4 % limit);
437
438 //size one case
439 const packed_slice_three = packed_slice_two.slice(1, 2);
440 testing.expect(packed_slice_three.len() == 1);
441 const ps3_bit_count = (bits * packed_slice_three.len()) + packed_slice_three.bit_offset;
442 const ps3_expected_bytes = (ps3_bit_count + 7) / 8;
443 testing.expect(packed_slice_three.bytes.len == ps3_expected_bytes);
444 testing.expect(packed_slice_three.get(0) == 7 % limit);
445
446 //empty slice case
447 const packed_slice_empty = packed_slice.slice(0, 0);
448 testing.expect(packed_slice_empty.len() == 0);
449 testing.expect(packed_slice_empty.bytes.len == 0);
450
451 //slicing at byte boundaries
452 const packed_slice_edge = packed_array.slice(8, 16);
453 testing.expect(packed_slice_edge.len() == 8);
454 const pse_bit_count = (bits * packed_slice_edge.len()) + packed_slice_edge.bit_offset;
455 const pse_expected_bytes = (pse_bit_count + 7) / 8;
456 testing.expect(packed_slice_edge.bytes.len == pse_expected_bytes);
457 testing.expect(packed_slice_edge.bit_offset == 0);
458 }
459}
460
461test "PackedIntSlice accumulating bit offsets" {
462 //bit_offset is u3, so standard debugging asserts should catch
463 // anything
464 {
465 const PackedArray = PackedIntArray(u3, 16);
466 var packed_array = PackedArray(undefined);
467
468 var packed_slice = packed_array.slice(0, packed_array.len());
469 var i = usize(0);
470 while (i < packed_array.len() - 1) : (i += 1) {
471 packed_slice = packed_slice.slice(1, packed_slice.len());
472 }
473 }
474 {
475 const PackedArray = PackedIntArray(u11, 88);
476 var packed_array = PackedArray(undefined);
477
478 var packed_slice = packed_array.slice(0, packed_array.len());
479 var i = usize(0);
480 while (i < packed_array.len() - 1) : (i += 1) {
481 packed_slice = packed_slice.slice(1, packed_slice.len());
482 }
483 }
484}
485
486//@NOTE: As I do not have a big endian system to test this on,
487// big endian values were not tested
488test "PackedInt(Array/Slice) sliceCast" {
489 const PackedArray = PackedIntArray(u1, 16);
490 var packed_array = PackedArray.init([]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
491 const packed_slice_cast_2 = packed_array.sliceCast(u2);
492 const packed_slice_cast_4 = packed_slice_cast_2.sliceCast(u4);
493 var packed_slice_cast_9 = packed_array.slice(0, (packed_array.len() / 9) * 9).sliceCast(u9);
494 const packed_slice_cast_3 = packed_slice_cast_9.sliceCast(u3);
495
496 var i = usize(0);
497 while (i < packed_slice_cast_2.len()) : (i += 1) {
498 const val = switch (builtin.endian) {
499 .Big => 0b01,
500 .Little => 0b10,
501 };
502 testing.expect(packed_slice_cast_2.get(i) == val);
503 }
504 i = 0;
505 while (i < packed_slice_cast_4.len()) : (i += 1) {
506 const val = switch (builtin.endian) {
507 .Big => 0b0101,
508 .Little => 0b1010,
509 };
510 testing.expect(packed_slice_cast_4.get(i) == val);
511 }
512 i = 0;
513 while (i < packed_slice_cast_9.len()) : (i += 1) {
514 const val = 0b010101010;
515 testing.expect(packed_slice_cast_9.get(i) == val);
516 packed_slice_cast_9.set(i, 0b111000111);
517 }
518 i = 0;
519 while (i < packed_slice_cast_3.len()) : (i += 1) {
520 const val = switch (builtin.endian) {
521 .Big => if (i % 2 == 0) u3(0b111) else u3(0b000),
522 .Little => if (i % 2 == 0) u3(0b111) else u3(0b000),
523 };
524 testing.expect(packed_slice_cast_3.get(i) == val);
525 }
526}
527
528test "PackedInt(Array/Slice)Endian" {
529 {
530 const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8);
531 var packed_array_be = PackedArrayBe.init([]u4{
532 0,
533 1,
534 2,
535 3,
536 4,
537 5,
538 6,
539 7,
540 });
541 testing.expect(packed_array_be.bytes[0] == 0b00000001);
542 testing.expect(packed_array_be.bytes[1] == 0b00100011);
543
544 var i = usize(0);
545 while (i < packed_array_be.len()) : (i += 1) {
546 testing.expect(packed_array_be.get(i) == i);
547 }
548
549 var packed_slice_le = packed_array_be.sliceCastEndian(u4, .Little);
550 i = 0;
551 while (i < packed_slice_le.len()) : (i += 1) {
552 const val = if (i % 2 == 0) i + 1 else i - 1;
553 testing.expect(packed_slice_le.get(i) == val);
554 }
555
556 var packed_slice_le_shift = packed_array_be.slice(1, 5).sliceCastEndian(u4, .Little);
557 i = 0;
558 while (i < packed_slice_le_shift.len()) : (i += 1) {
559 const val = if (i % 2 == 0) i else i + 2;
560 testing.expect(packed_slice_le_shift.get(i) == val);
561 }
562 }
563
564 {
565 const PackedArrayBe = PackedIntArrayEndian(u11, .Big, 8);
566 var packed_array_be = PackedArrayBe.init([]u11{
567 0,
568 1,
569 2,
570 3,
571 4,
572 5,
573 6,
574 7,
575 });
576 testing.expect(packed_array_be.bytes[0] == 0b00000000);
577 testing.expect(packed_array_be.bytes[1] == 0b00000000);
578 testing.expect(packed_array_be.bytes[2] == 0b00000100);
579 testing.expect(packed_array_be.bytes[3] == 0b00000001);
580 testing.expect(packed_array_be.bytes[4] == 0b00000000);
581
582 var i = usize(0);
583 while (i < packed_array_be.len()) : (i += 1) {
584 testing.expect(packed_array_be.get(i) == i);
585 }
586
587 var packed_slice_le = packed_array_be.sliceCastEndian(u11, .Little);
588 testing.expect(packed_slice_le.get(0) == 0b00000000000);
589 testing.expect(packed_slice_le.get(1) == 0b00010000000);
590 testing.expect(packed_slice_le.get(2) == 0b00000000100);
591 testing.expect(packed_slice_le.get(3) == 0b00000000000);
592 testing.expect(packed_slice_le.get(4) == 0b00010000011);
593 testing.expect(packed_slice_le.get(5) == 0b00000000010);
594 testing.expect(packed_slice_le.get(6) == 0b10000010000);
595 testing.expect(packed_slice_le.get(7) == 0b00000111001);
596
597 var packed_slice_le_shift = packed_array_be.slice(1, 5).sliceCastEndian(u11, .Little);
598 testing.expect(packed_slice_le_shift.get(0) == 0b00010000000);
599 testing.expect(packed_slice_le_shift.get(1) == 0b00000000100);
600 testing.expect(packed_slice_le_shift.get(2) == 0b00000000000);
601 testing.expect(packed_slice_le_shift.get(3) == 0b00010000011);
602 }
603}
604
605//@NOTE: Need to manually update this list as more posix os's get
606// added to DirectAllocator. Windows can be added too when DirectAllocator
607// switches to VirtualAlloc.
608
609//These tests prove we aren't accidentally accessing memory past
610// the end of the array/slice by placing it at the end of a page
611// and reading the last element. The assumption is that the page
612// after this one is not mapped and will cause a segfault if we
613// don't account for the bounds.
614test "PackedIntArray at end of available memory" {
615 switch (builtin.os) {
616 .linux, .macosx, .ios, .freebsd, .netbsd => {},
617 else => return,
618 }
619 const PackedArray = PackedIntArray(u3, 8);
620
621 const Padded = struct {
622 _: [std.os.page_size - @sizeOf(PackedArray)]u8,
623 p: PackedArray,
624 };
625
626 var da = std.heap.DirectAllocator.init();
627 const allocator = &da.allocator;
628
629 var pad = try allocator.create(Padded);
630 defer allocator.destroy(pad);
631 pad.p.set(7, std.math.maxInt(u3));
632}
633
634test "PackedIntSlice at end of available memory" {
635 switch (builtin.os) {
636 .linux, .macosx, .ios, .freebsd, .netbsd => {},
637 else => return,
638 }
639 const PackedSlice = PackedIntSlice(u11);
640
641 var da = std.heap.DirectAllocator.init();
642 const allocator = &da.allocator;
643
644 var page = try allocator.alloc(u8, std.os.page_size);
645 defer allocator.free(page);
646
647 var p = PackedSlice.init(page[std.os.page_size - 2 ..], 1);
648 p.set(0, std.math.maxInt(u11));
649}
std/pdb.zig+7-6
...@@ -588,7 +588,7 @@ const SuperBlock = packed struct {...@@ -588,7 +588,7 @@ const SuperBlock = packed struct {
588588
589const MsfStream = struct {589const MsfStream = struct {
590 in_file: os.File,590 in_file: os.File,
591 pos: usize,591 pos: u64,
592 blocks: []u32,592 blocks: []u32,
593 block_size: u32,593 block_size: u32,
594594
...@@ -598,7 +598,7 @@ const MsfStream = struct {...@@ -598,7 +598,7 @@ const MsfStream = struct {
598 pub const Error = @typeOf(read).ReturnType.ErrorSet;598 pub const Error = @typeOf(read).ReturnType.ErrorSet;
599 pub const Stream = io.InStream(Error);599 pub const Stream = io.InStream(Error);
600600
601 fn init(block_size: u32, block_count: u32, pos: usize, file: os.File, allocator: *mem.Allocator) !MsfStream {601 fn init(block_size: u32, block_count: u32, pos: u64, file: os.File, allocator: *mem.Allocator) !MsfStream {
602 var stream = MsfStream{602 var stream = MsfStream{
603 .in_file = file,603 .in_file = file,
604 .pos = 0,604 .pos = 0,
...@@ -660,23 +660,24 @@ const MsfStream = struct {...@@ -660,23 +660,24 @@ const MsfStream = struct {
660 return size;660 return size;
661 }661 }
662662
663 fn seekForward(self: *MsfStream, len: usize) !void {663 // XXX: The `len` parameter should be signed
664 fn seekForward(self: *MsfStream, len: u64) !void {
664 self.pos += len;665 self.pos += len;
665 if (self.pos >= self.blocks.len * self.block_size)666 if (self.pos >= self.blocks.len * self.block_size)
666 return error.EOF;667 return error.EOF;
667 }668 }
668669
669 fn seekTo(self: *MsfStream, len: usize) !void {670 fn seekTo(self: *MsfStream, len: u64) !void {
670 self.pos = len;671 self.pos = len;
671 if (self.pos >= self.blocks.len * self.block_size)672 if (self.pos >= self.blocks.len * self.block_size)
672 return error.EOF;673 return error.EOF;
673 }674 }
674675
675 fn getSize(self: *const MsfStream) usize {676 fn getSize(self: *const MsfStream) u64 {
676 return self.blocks.len * self.block_size;677 return self.blocks.len * self.block_size;
677 }678 }
678679
679 fn getFilePos(self: MsfStream) usize {680 fn getFilePos(self: MsfStream) u64 {
680 const block_id = self.pos / self.block_size;681 const block_id = self.pos / self.block_size;
681 const block = self.blocks[block_id];682 const block = self.blocks[block_id];
682 const offset = self.pos % self.block_size;683 const offset = self.pos % self.block_size;
std/rand.zig+2-2
...@@ -768,10 +768,10 @@ pub const Isaac64 = struct {...@@ -768,10 +768,10 @@ pub const Isaac64 = struct {
768 const x = self.m[base + m1];768 const x = self.m[base + m1];
769 self.a = mix +% self.m[base + m2];769 self.a = mix +% self.m[base + m2];
770770
771 const y = self.a +% self.b +% self.m[(x >> 3) % self.m.len];771 const y = self.a +% self.b +% self.m[@intCast(usize, (x >> 3) % self.m.len)];
772 self.m[base + m1] = y;772 self.m[base + m1] = y;
773773
774 self.b = x +% self.m[(y >> 11) % self.m.len];774 self.b = x +% self.m[@intCast(usize, (y >> 11) % self.m.len)];
775 self.r[self.r.len - 1 - base - m1] = self.b;775 self.r[self.r.len - 1 - base - m1] = self.b;
776 }776 }
777777
std/special/bootstrap.zig+13-61
...@@ -20,6 +20,10 @@ comptime {...@@ -20,6 +20,10 @@ comptime {
20}20}
2121
22nakedcc fn _start() noreturn {22nakedcc fn _start() noreturn {
23 if (builtin.os == builtin.Os.wasi) {
24 std.os.wasi.proc_exit(callMain());
25 }
26
23 switch (builtin.arch) {27 switch (builtin.arch) {
24 builtin.Arch.x86_64 => {28 builtin.Arch.x86_64 => {
25 argc_ptr = asm ("lea (%%rsp), %[argc]"29 argc_ptr = asm ("lea (%%rsp), %[argc]"
...@@ -63,24 +67,19 @@ fn posixCallMainAndExit() noreturn {...@@ -63,24 +67,19 @@ fn posixCallMainAndExit() noreturn {
63 var envp_count: usize = 0;67 var envp_count: usize = 0;
64 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}68 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
65 const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count];69 const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count];
70
66 if (builtin.os == builtin.Os.linux) {71 if (builtin.os == builtin.Os.linux) {
67 // Scan auxiliary vector.72 // Find the beginning of the auxiliary vector
68 const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);73 const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
69 std.os.linux_elf_aux_maybe = auxv;74 std.os.linux_elf_aux_maybe = auxv;
70 var i: usize = 0;75 // Initialize the TLS area
71 var at_phdr: usize = 0;76 std.os.linux.tls.initTLS();
72 var at_phnum: usize = 0;77
73 var at_phent: usize = 0;78 if (std.os.linux.tls.tls_image) |tls_img| {
74 while (auxv[i].a_un.a_val != 0) : (i += 1) {79 const tls_addr = std.os.linux.tls.allocateTLS(tls_img.alloc_size);
75 switch (auxv[i].a_type) {80 const tp = std.os.linux.tls.copyTLS(tls_addr);
76 std.elf.AT_PAGESZ => assert(auxv[i].a_un.a_val == std.os.page_size),81 std.os.linux.tls.setThreadPointer(tp);
77 std.elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
78 std.elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
79 std.elf.AT_PHENT => at_phent = auxv[i].a_un.a_val,
80 else => {},
81 }
82 }82 }
83 if (!builtin.single_threaded) linuxInitializeThreadLocalStorage(at_phdr, at_phnum, at_phent);
84 }83 }
8584
86 std.os.posix.exit(callMainWithArgs(argc, argv, envp));85 std.os.posix.exit(callMainWithArgs(argc, argv, envp));
...@@ -136,50 +135,3 @@ inline fn callMain() u8 {...@@ -136,50 +135,3 @@ inline fn callMain() u8 {
136135
137const main_thread_tls_align = 32;136const main_thread_tls_align = 32;
138var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64;137var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64;
139
140fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent: usize) void {
141 var phdr_addr = at_phdr;
142 var n = at_phnum;
143 var base: usize = 0;
144 while (n != 0) : ({
145 n -= 1;
146 phdr_addr += at_phent;
147 }) {
148 const phdr = @intToPtr(*std.elf.Phdr, phdr_addr);
149 // TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917
150 switch (phdr.p_type) {
151 std.elf.PT_PHDR => base = at_phdr - phdr.p_vaddr,
152 std.elf.PT_TLS => std.os.linux_tls_phdr = phdr,
153 else => continue,
154 }
155 }
156 const tls_phdr = std.os.linux_tls_phdr orelse return;
157 std.os.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr);
158 const end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz;
159 const max_end_addr = @ptrToInt(&main_thread_tls_bytes) + main_thread_tls_bytes.len;
160 assert(max_end_addr >= end_addr + @sizeOf(usize)); // not enough preallocated Thread Local Storage
161 assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough
162 @memcpy(&main_thread_tls_bytes, std.os.linux_tls_img_src, tls_phdr.p_filesz);
163 const end_ptr = @intToPtr(*usize, end_addr);
164 end_ptr.* = end_addr;
165 linuxSetThreadArea(end_addr);
166}
167
168fn linuxSetThreadArea(addr: usize) void {
169 switch (builtin.arch) {
170 builtin.Arch.x86_64 => {
171 const ARCH_SET_FS = 0x1002;
172 const rc = std.os.linux.syscall2(std.os.linux.SYS_arch_prctl, ARCH_SET_FS, addr);
173 // acrh_prctl is documented to never fail
174 assert(rc == 0);
175 },
176 builtin.Arch.aarch64 => {
177 asm volatile (
178 \\ msr tpidr_el0,x0
179 \\ mov w0,#0
180 \\ ret
181 );
182 },
183 else => @compileError("Unsupported architecture"),
184 }
185}
std/special/build_runner.zig+21-9
...@@ -94,6 +94,16 @@ pub fn main() !void {...@@ -94,6 +94,16 @@ pub fn main() !void {
94 return usageAndErr(&builder, false, try stderr_stream);94 return usageAndErr(&builder, false, try stderr_stream);
95 });95 });
96 builder.addSearchPrefix(search_prefix);96 builder.addSearchPrefix(search_prefix);
97 } else if (mem.eql(u8, arg, "--override-std-dir")) {
98 builder.override_std_dir = try unwrapArg(arg_it.next(allocator) orelse {
99 warn("Expected argument after --override-std-dir\n\n");
100 return usageAndErr(&builder, false, try stderr_stream);
101 });
102 } else if (mem.eql(u8, arg, "--override-lib-dir")) {
103 builder.override_lib_dir = try unwrapArg(arg_it.next(allocator) orelse {
104 warn("Expected argument after --override-lib-dir\n\n");
105 return usageAndErr(&builder, false, try stderr_stream);
106 });
97 } else if (mem.eql(u8, arg, "--verbose-tokenize")) {107 } else if (mem.eql(u8, arg, "--verbose-tokenize")) {
98 builder.verbose_tokenize = true;108 builder.verbose_tokenize = true;
99 } else if (mem.eql(u8, arg, "--verbose-ast")) {109 } else if (mem.eql(u8, arg, "--verbose-ast")) {
...@@ -187,15 +197,17 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {...@@ -187,15 +197,17 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
187 try out_stream.write(197 try out_stream.write(
188 \\198 \\
189 \\Advanced Options:199 \\Advanced Options:
190 \\ --build-file [file] Override path to build.zig200 \\ --build-file [file] Override path to build.zig
191 \\ --cache-dir [path] Override path to zig cache directory201 \\ --cache-dir [path] Override path to zig cache directory
192 \\ --verbose-tokenize Enable compiler debug output for tokenization202 \\ --override-std-dir [arg] Override path to Zig standard library
193 \\ --verbose-ast Enable compiler debug output for parsing into an AST203 \\ --override-lib-dir [arg] Override path to Zig lib directory
194 \\ --verbose-link Enable compiler debug output for linking204 \\ --verbose-tokenize Enable compiler debug output for tokenization
195 \\ --verbose-ir Enable compiler debug output for Zig IR205 \\ --verbose-ast Enable compiler debug output for parsing into an AST
196 \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR206 \\ --verbose-link Enable compiler debug output for linking
197 \\ --verbose-cimport Enable compiler debug output for C imports207 \\ --verbose-ir Enable compiler debug output for Zig IR
198 \\ --verbose-cc Enable compiler debug output for C compilation208 \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
209 \\ --verbose-cimport Enable compiler debug output for C imports
210 \\ --verbose-cc Enable compiler debug output for C compilation
199 \\211 \\
200 );212 );
201}213}
std/special/compiler_rt.zig+538-149
...@@ -5,20 +5,47 @@ comptime {...@@ -5,20 +5,47 @@ comptime {
5 const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak;5 const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak;
6 const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong;6 const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong;
77
8 switch (builtin.arch) {
9 .i386, .x86_64 => @export("__zig_probe_stack", @import("compiler_rt/stack_probe.zig").zig_probe_stack, linkage),
10 else => {},
11 }
12
13 @export("__lesf2", @import("compiler_rt/comparesf2.zig").__lesf2, linkage);
14 @export("__ledf2", @import("compiler_rt/comparedf2.zig").__ledf2, linkage);
8 @export("__letf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);15 @export("__letf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
16
17 @export("__gesf2", @import("compiler_rt/comparesf2.zig").__gesf2, linkage);
18 @export("__gedf2", @import("compiler_rt/comparedf2.zig").__gedf2, linkage);
9 @export("__getf2", @import("compiler_rt/comparetf2.zig").__getf2, linkage);19 @export("__getf2", @import("compiler_rt/comparetf2.zig").__getf2, linkage);
1020
11 if (!is_test) {21 if (!is_test) {
12 // only create these aliases when not testing22 // only create these aliases when not testing
23 @export("__cmpsf2", @import("compiler_rt/comparesf2.zig").__lesf2, linkage);
24 @export("__cmpdf2", @import("compiler_rt/comparedf2.zig").__ledf2, linkage);
13 @export("__cmptf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);25 @export("__cmptf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
26
27 @export("__eqsf2", @import("compiler_rt/comparesf2.zig").__eqsf2, linkage);
28 @export("__eqdf2", @import("compiler_rt/comparedf2.zig").__eqdf2, linkage);
14 @export("__eqtf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);29 @export("__eqtf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
30
31 @export("__ltsf2", @import("compiler_rt/comparesf2.zig").__ltsf2, linkage);
32 @export("__ltdf2", @import("compiler_rt/comparedf2.zig").__ltdf2, linkage);
15 @export("__lttf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);33 @export("__lttf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
34
35 @export("__nesf2", @import("compiler_rt/comparesf2.zig").__nesf2, linkage);
36 @export("__nedf2", @import("compiler_rt/comparedf2.zig").__nedf2, linkage);
16 @export("__netf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);37 @export("__netf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
38
39 @export("__gtsf2", @import("compiler_rt/comparesf2.zig").__gtsf2, linkage);
40 @export("__gtdf2", @import("compiler_rt/comparedf2.zig").__gtdf2, linkage);
17 @export("__gttf2", @import("compiler_rt/comparetf2.zig").__getf2, linkage);41 @export("__gttf2", @import("compiler_rt/comparetf2.zig").__getf2, linkage);
42
18 @export("__gnu_h2f_ieee", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage);43 @export("__gnu_h2f_ieee", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage);
19 @export("__gnu_f2h_ieee", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage);44 @export("__gnu_f2h_ieee", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage);
20 }45 }
2146
47 @export("__unordsf2", @import("compiler_rt/comparesf2.zig").__unordsf2, linkage);
48 @export("__unorddf2", @import("compiler_rt/comparedf2.zig").__unorddf2, linkage);
22 @export("__unordtf2", @import("compiler_rt/comparetf2.zig").__unordtf2, linkage);49 @export("__unordtf2", @import("compiler_rt/comparetf2.zig").__unordtf2, linkage);
2350
24 @export("__addsf3", @import("compiler_rt/addXf3.zig").__addsf3, linkage);51 @export("__addsf3", @import("compiler_rt/addXf3.zig").__addsf3, linkage);
...@@ -35,6 +62,17 @@ comptime {...@@ -35,6 +62,17 @@ comptime {
35 @export("__divsf3", @import("compiler_rt/divsf3.zig").__divsf3, linkage);62 @export("__divsf3", @import("compiler_rt/divsf3.zig").__divsf3, linkage);
36 @export("__divdf3", @import("compiler_rt/divdf3.zig").__divdf3, linkage);63 @export("__divdf3", @import("compiler_rt/divdf3.zig").__divdf3, linkage);
3764
65 @export("__ashlti3", @import("compiler_rt/ashlti3.zig").__ashlti3, linkage);
66 @export("__lshrti3", @import("compiler_rt/lshrti3.zig").__lshrti3, linkage);
67 @export("__ashrti3", @import("compiler_rt/ashrti3.zig").__ashrti3, linkage);
68
69 @export("__floatsidf", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage);
70 @export("__floatsisf", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage);
71 @export("__floatdidf", @import("compiler_rt/floatdidf.zig").__floatdidf, linkage);
72 @export("__floatsitf", @import("compiler_rt/floatsiXf.zig").__floatsitf, linkage);
73 @export("__floatunsidf", @import("compiler_rt/floatunsidf.zig").__floatunsidf, linkage);
74 @export("__floatundidf", @import("compiler_rt/floatundidf.zig").__floatundidf, linkage);
75
38 @export("__floattitf", @import("compiler_rt/floattitf.zig").__floattitf, linkage);76 @export("__floattitf", @import("compiler_rt/floattitf.zig").__floattitf, linkage);
39 @export("__floattidf", @import("compiler_rt/floattidf.zig").__floattidf, linkage);77 @export("__floattidf", @import("compiler_rt/floattidf.zig").__floattidf, linkage);
40 @export("__floattisf", @import("compiler_rt/floattisf.zig").__floattisf, linkage);78 @export("__floattisf", @import("compiler_rt/floattisf.zig").__floattisf, linkage);
...@@ -55,6 +93,10 @@ comptime {...@@ -55,6 +93,10 @@ comptime {
55 @export("__trunctfdf2", @import("compiler_rt/truncXfYf2.zig").__trunctfdf2, linkage);93 @export("__trunctfdf2", @import("compiler_rt/truncXfYf2.zig").__trunctfdf2, linkage);
56 @export("__trunctfsf2", @import("compiler_rt/truncXfYf2.zig").__trunctfsf2, linkage);94 @export("__trunctfsf2", @import("compiler_rt/truncXfYf2.zig").__trunctfsf2, linkage);
5795
96 @export("__truncdfsf2", @import("compiler_rt/truncXfYf2.zig").__truncdfsf2, linkage);
97
98 @export("__extendsfdf2", @import("compiler_rt/extendXfYf2.zig").__extendsfdf2, linkage);
99
58 @export("__fixunssfsi", @import("compiler_rt/fixunssfsi.zig").__fixunssfsi, linkage);100 @export("__fixunssfsi", @import("compiler_rt/fixunssfsi.zig").__fixunssfsi, linkage);
59 @export("__fixunssfdi", @import("compiler_rt/fixunssfdi.zig").__fixunssfdi, linkage);101 @export("__fixunssfdi", @import("compiler_rt/fixunssfdi.zig").__fixunssfdi, linkage);
60 @export("__fixunssfti", @import("compiler_rt/fixunssfti.zig").__fixunssfti, linkage);102 @export("__fixunssfti", @import("compiler_rt/fixunssfti.zig").__fixunssfti, linkage);
...@@ -80,18 +122,33 @@ comptime {...@@ -80,18 +122,33 @@ comptime {
80 @export("__udivmoddi4", @import("compiler_rt/udivmoddi4.zig").__udivmoddi4, linkage);122 @export("__udivmoddi4", @import("compiler_rt/udivmoddi4.zig").__udivmoddi4, linkage);
81 @export("__popcountdi2", @import("compiler_rt/popcountdi2.zig").__popcountdi2, linkage);123 @export("__popcountdi2", @import("compiler_rt/popcountdi2.zig").__popcountdi2, linkage);
82124
125 @export("__divmoddi4", __divmoddi4, linkage);
126 @export("__divsi3", __divsi3, linkage);
127 @export("__divdi3", __divdi3, linkage);
83 @export("__udivsi3", __udivsi3, linkage);128 @export("__udivsi3", __udivsi3, linkage);
84 @export("__udivdi3", __udivdi3, linkage);129 @export("__udivdi3", __udivdi3, linkage);
130 @export("__modsi3", __modsi3, linkage);
131 @export("__moddi3", __moddi3, linkage);
132 @export("__umodsi3", __umodsi3, linkage);
85 @export("__umoddi3", __umoddi3, linkage);133 @export("__umoddi3", __umoddi3, linkage);
134 @export("__divmodsi4", __divmodsi4, linkage);
86 @export("__udivmodsi4", __udivmodsi4, linkage);135 @export("__udivmodsi4", __udivmodsi4, linkage);
87136
88 @export("__negsf2", @import("compiler_rt/negXf2.zig").__negsf2, linkage);137 @export("__negsf2", @import("compiler_rt/negXf2.zig").__negsf2, linkage);
89 @export("__negdf2", @import("compiler_rt/negXf2.zig").__negdf2, linkage);138 @export("__negdf2", @import("compiler_rt/negXf2.zig").__negdf2, linkage);
90139
91 if (is_arm_arch and !is_arm_64) {140 if (is_arm_arch and !is_arm_64) {
141 @export("__aeabi_unwind_cpp_pr0", __aeabi_unwind_cpp_pr0, strong_linkage);
142 @export("__aeabi_unwind_cpp_pr1", __aeabi_unwind_cpp_pr1, linkage);
143 @export("__aeabi_unwind_cpp_pr2", __aeabi_unwind_cpp_pr2, linkage);
144
145 @export("__aeabi_ldivmod", __aeabi_ldivmod, linkage);
92 @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage);146 @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage);
93 @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);147
148 @export("__aeabi_idiv", __divsi3, linkage);
149 @export("__aeabi_idivmod", __aeabi_idivmod, linkage);
94 @export("__aeabi_uidiv", __udivsi3, linkage);150 @export("__aeabi_uidiv", __udivsi3, linkage);
151 @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);
95152
96 @export("__aeabi_memcpy", __aeabi_memcpy, linkage);153 @export("__aeabi_memcpy", __aeabi_memcpy, linkage);
97 @export("__aeabi_memcpy4", __aeabi_memcpy, linkage);154 @export("__aeabi_memcpy4", __aeabi_memcpy, linkage);
...@@ -113,6 +170,12 @@ comptime {...@@ -113,6 +170,12 @@ comptime {
113 @export("__aeabi_memcmp4", __aeabi_memcmp, linkage);170 @export("__aeabi_memcmp4", __aeabi_memcmp, linkage);
114 @export("__aeabi_memcmp8", __aeabi_memcmp, linkage);171 @export("__aeabi_memcmp8", __aeabi_memcmp, linkage);
115172
173 @export("__aeabi_f2d", @import("compiler_rt/extendXfYf2.zig").__extendsfdf2, linkage);
174 @export("__aeabi_i2d", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage);
175 @export("__aeabi_l2d", @import("compiler_rt/floatdidf.zig").__floatdidf, linkage);
176 @export("__aeabi_ui2d", @import("compiler_rt/floatunsidf.zig").__floatunsidf, linkage);
177 @export("__aeabi_ul2d", @import("compiler_rt/floatundidf.zig").__floatundidf, linkage);
178
116 @export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage);179 @export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage);
117 @export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage);180 @export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage);
118181
...@@ -132,6 +195,9 @@ comptime {...@@ -132,6 +195,9 @@ comptime {
132 @export("__aeabi_h2f", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage);195 @export("__aeabi_h2f", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage);
133 @export("__aeabi_f2h", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage);196 @export("__aeabi_f2h", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage);
134197
198 @export("__aeabi_i2f", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage);
199 @export("__aeabi_d2f", @import("compiler_rt/truncXfYf2.zig").__truncdfsf2, linkage);
200
135 @export("__aeabi_fadd", @import("compiler_rt/addXf3.zig").__addsf3, linkage);201 @export("__aeabi_fadd", @import("compiler_rt/addXf3.zig").__addsf3, linkage);
136 @export("__aeabi_dadd", @import("compiler_rt/addXf3.zig").__adddf3, linkage);202 @export("__aeabi_dadd", @import("compiler_rt/addXf3.zig").__adddf3, linkage);
137 @export("__aeabi_fsub", @import("compiler_rt/addXf3.zig").__subsf3, linkage);203 @export("__aeabi_fsub", @import("compiler_rt/addXf3.zig").__subsf3, linkage);
...@@ -144,26 +210,41 @@ comptime {...@@ -144,26 +210,41 @@ comptime {
144210
145 @export("__aeabi_fdiv", @import("compiler_rt/divsf3.zig").__divsf3, linkage);211 @export("__aeabi_fdiv", @import("compiler_rt/divsf3.zig").__divsf3, linkage);
146 @export("__aeabi_ddiv", @import("compiler_rt/divdf3.zig").__divdf3, linkage);212 @export("__aeabi_ddiv", @import("compiler_rt/divdf3.zig").__divdf3, linkage);
213
214 @export("__aeabi_fcmpeq", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpeq, linkage);
215 @export("__aeabi_fcmplt", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmplt, linkage);
216 @export("__aeabi_fcmple", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmple, linkage);
217 @export("__aeabi_fcmpge", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpge, linkage);
218 @export("__aeabi_fcmpgt", @import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpgt, linkage);
219 @export("__aeabi_fcmpun", @import("compiler_rt/comparesf2.zig").__unordsf2, linkage);
220
221 @export("__aeabi_dcmpeq", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpeq, linkage);
222 @export("__aeabi_dcmplt", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmplt, linkage);
223 @export("__aeabi_dcmple", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmple, linkage);
224 @export("__aeabi_dcmpge", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpge, linkage);
225 @export("__aeabi_dcmpgt", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpgt, linkage);
226 @export("__aeabi_dcmpun", @import("compiler_rt/comparedf2.zig").__unorddf2, linkage);
147 }227 }
148 if (builtin.os == builtin.Os.windows) {228 if (builtin.os == builtin.Os.windows) {
229 if (!builtin.link_libc) {
230 @export("_chkstk", @import("compiler_rt/stack_probe.zig")._chkstk, strong_linkage);
231 @export("__chkstk", @import("compiler_rt/stack_probe.zig").__chkstk, strong_linkage);
232 @export("___chkstk", @import("compiler_rt/stack_probe.zig").___chkstk, strong_linkage);
233 @export("__chkstk_ms", @import("compiler_rt/stack_probe.zig").__chkstk_ms, strong_linkage);
234 @export("___chkstk_ms", @import("compiler_rt/stack_probe.zig").___chkstk_ms, strong_linkage);
235 }
236
149 switch (builtin.arch) {237 switch (builtin.arch) {
150 builtin.Arch.i386 => {238 builtin.Arch.i386 => {
151 if (!builtin.link_libc) {
152 @export("_chkstk", _chkstk, strong_linkage);
153 @export("__chkstk_ms", __chkstk_ms, linkage);
154 }
155 @export("_aulldiv", @import("compiler_rt/aulldiv.zig")._aulldiv, strong_linkage);239 @export("_aulldiv", @import("compiler_rt/aulldiv.zig")._aulldiv, strong_linkage);
156 @export("_aullrem", @import("compiler_rt/aullrem.zig")._aullrem, strong_linkage);240 @export("_aullrem", @import("compiler_rt/aullrem.zig")._aullrem, strong_linkage);
157 },241 },
158 builtin.Arch.x86_64 => {242 builtin.Arch.x86_64 => {
159 if (!builtin.link_libc) {243 // The "ti" functions must use @Vector(2, u64) parameter types to adhere to the ABI
160 @export("__chkstk", __chkstk, strong_linkage);244 // that LLVM expects compiler-rt to have.
161 @export("___chkstk_ms", ___chkstk_ms, linkage);
162 }
163 @export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage);245 @export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage);
164 @export("__modti3", @import("compiler_rt/modti3.zig").__modti3_windows_x86_64, linkage);246 @export("__modti3", @import("compiler_rt/modti3.zig").__modti3_windows_x86_64, linkage);
165 @export("__multi3", @import("compiler_rt/multi3.zig").__multi3_windows_x86_64, linkage);247 @export("__multi3", @import("compiler_rt/multi3.zig").__multi3_windows_x86_64, linkage);
166 @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4_windows_x86_64, linkage);
167 @export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64, linkage);248 @export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64, linkage);
168 @export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64, linkage);249 @export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64, linkage);
169 @export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64, linkage);250 @export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64, linkage);
...@@ -174,11 +255,12 @@ comptime {...@@ -174,11 +255,12 @@ comptime {
174 @export("__divti3", @import("compiler_rt/divti3.zig").__divti3, linkage);255 @export("__divti3", @import("compiler_rt/divti3.zig").__divti3, linkage);
175 @export("__modti3", @import("compiler_rt/modti3.zig").__modti3, linkage);256 @export("__modti3", @import("compiler_rt/modti3.zig").__modti3, linkage);
176 @export("__multi3", @import("compiler_rt/multi3.zig").__multi3, linkage);257 @export("__multi3", @import("compiler_rt/multi3.zig").__multi3, linkage);
177 @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4, linkage);
178 @export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3, linkage);258 @export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3, linkage);
179 @export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4, linkage);259 @export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4, linkage);
180 @export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3, linkage);260 @export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3, linkage);
181 }261 }
262 @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4, linkage);
263 @export("__mulodi4", @import("compiler_rt/mulodi4.zig").__mulodi4, linkage);
182}264}
183265
184const std = @import("std");266const std = @import("std");
...@@ -198,15 +280,49 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn...@@ -198,15 +280,49 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
198 }280 }
199}281}
200282
201pub fn setXmm0(comptime T: type, value: T) void {283extern fn __aeabi_unwind_cpp_pr0() void {
202 comptime assert(builtin.arch == builtin.Arch.x86_64);284 unreachable;
203 const aligned_value: T align(16) = value;285}
204 asm volatile (286extern fn __aeabi_unwind_cpp_pr1() void {
205 \\movaps (%[ptr]), %%xmm0287 unreachable;
206 :288}
207 : [ptr] "r" (&aligned_value)289extern fn __aeabi_unwind_cpp_pr2() void {
208 : "xmm0"290 unreachable;
209 );291}
292
293extern fn __divmoddi4(a: i64, b: i64, rem: *i64) i64 {
294 @setRuntimeSafety(is_test);
295
296 const d = __divdi3(a, b);
297 rem.* = a -% (d *% b);
298 return d;
299}
300
301extern fn __divdi3(a: i64, b: i64) i64 {
302 @setRuntimeSafety(is_test);
303
304 // Set aside the sign of the quotient.
305 const sign = @bitCast(u64, (a ^ b) >> 63);
306 // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
307 const abs_a = (a ^ (a >> 63)) -% (a >> 63);
308 const abs_b = (b ^ (b >> 63)) -% (b >> 63);
309 // Unsigned division
310 const res = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), null);
311 // Apply sign of quotient to result and return.
312 return @bitCast(i64, (res ^ sign) -% sign);
313}
314
315extern fn __moddi3(a: i64, b: i64) i64 {
316 @setRuntimeSafety(is_test);
317
318 // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
319 const abs_a = (a ^ (a >> 63)) -% (a >> 63);
320 const abs_b = (b ^ (b >> 63)) -% (b >> 63);
321 // Unsigned division
322 var r: u64 = undefined;
323 _ = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), &r);
324 // Apply the sign of the dividend and return.
325 return (@bitCast(i64, r) ^ (a >> 63)) -% (a >> 63);
210}326}
211327
212extern fn __udivdi3(a: u64, b: u64) u64 {328extern fn __udivdi3(a: u64, b: u64) u64 {
...@@ -222,14 +338,35 @@ extern fn __umoddi3(a: u64, b: u64) u64 {...@@ -222,14 +338,35 @@ extern fn __umoddi3(a: u64, b: u64) u64 {
222 return r;338 return r;
223}339}
224340
225const AeabiUlDivModResult = extern struct {341extern fn __aeabi_uidivmod(n: u32, d: u32) extern struct{q: u32, r: u32} {
226 quot: u64,342 @setRuntimeSafety(is_test);
227 rem: u64,343
228};344 var result: @typeOf(__aeabi_uidivmod).ReturnType = undefined;
229extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult {345 result.q = __udivmodsi4(n, d, &result.r);
346 return result;
347}
348
349extern fn __aeabi_uldivmod(n: u64, d: u64) extern struct{q: u64, r: u64} {
350 @setRuntimeSafety(is_test);
351
352 var result: @typeOf(__aeabi_uldivmod).ReturnType = undefined;
353 result.q = __udivmoddi4(n, d, &result.r);
354 return result;
355}
356
357extern fn __aeabi_idivmod(n: i32, d: i32) extern struct{q: i32, r: i32} {
358 @setRuntimeSafety(is_test);
359
360 var result: @typeOf(__aeabi_idivmod).ReturnType = undefined;
361 result.q = __divmodsi4(n, d, &result.r);
362 return result;
363}
364
365extern fn __aeabi_ldivmod(n: i64, d: i64) extern struct{q: i64, r:i64} {
230 @setRuntimeSafety(is_test);366 @setRuntimeSafety(is_test);
231 var result: AeabiUlDivModResult = undefined;367
232 result.quot = __udivmoddi4(numerator, denominator, &result.rem);368 var result: @typeOf(__aeabi_ldivmod).ReturnType = undefined;
369 result.q = __divmoddi4(n, d, &result.r);
233 return result;370 return result;
234}371}
235372
...@@ -253,29 +390,74 @@ const is_arm_arch = switch (builtin.arch) {...@@ -253,29 +390,74 @@ const is_arm_arch = switch (builtin.arch) {
253390
254const is_arm_32 = is_arm_arch and !is_arm_64;391const is_arm_32 = is_arm_arch and !is_arm_64;
255392
256const use_thumb_1 = is_arm_32 and switch (builtin.arch.arm) {393const use_thumb_1 = usesThumb1(builtin.arch);
257 builtin.Arch.Arm32.v6,394
258 builtin.Arch.Arm32.v6m,395fn usesThumb1(arch: builtin.Arch) bool {
259 builtin.Arch.Arm32.v6k,396 return switch (arch) {
260 builtin.Arch.Arm32.v6t2,397 .arm => switch (arch.arm) {
261 => true,398 .v6m => true,
262 else => false,399 else => false,
263};400 },
401 .armeb => switch (arch.armeb) {
402 .v6m => true,
403 else => false,
404 },
405 .thumb => switch (arch.thumb) {
406 .v5,
407 .v5te,
408 .v4t,
409 .v6,
410 .v6m,
411 .v6k,
412 => true,
413 else => false,
414 },
415 .thumbeb => switch (arch.thumbeb) {
416 .v5,
417 .v5te,
418 .v4t,
419 .v6,
420 .v6m,
421 .v6k,
422 => true,
423 else => false,
424 },
425 else => false,
426 };
427}
264428
265nakedcc fn __aeabi_uidivmod() void {429test "usesThumb1" {
266 @setRuntimeSafety(false);430 testing.expect(usesThumb1(builtin.Arch{ .arm = .v6m }));
267 asm volatile (431 testing.expect(!usesThumb1(builtin.Arch{ .arm = .v5 }));
268 \\ push { lr }432 //etc.
269 \\ sub sp, sp, #4433
270 \\ mov r2, sp434 testing.expect(usesThumb1(builtin.Arch{ .armeb = .v6m }));
271 \\ bl __udivmodsi4435 testing.expect(!usesThumb1(builtin.Arch{ .armeb = .v5 }));
272 \\ ldr r1, [sp]436 //etc.
273 \\ add sp, sp, #4437
274 \\ pop { pc }438 testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5 }));
275 :439 testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5te }));
276 :440 testing.expect(usesThumb1(builtin.Arch{ .thumb = .v4t }));
277 : "r2", "r1"441 testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6 }));
278 );442 testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6k }));
443 testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6m }));
444 testing.expect(!usesThumb1(builtin.Arch{ .thumb = .v6t2 }));
445 //etc.
446
447 testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v5 }));
448 testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v5te }));
449 testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v4t }));
450 testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6 }));
451 testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6k }));
452 testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6m }));
453 testing.expect(!usesThumb1(builtin.Arch{ .thumbeb = .v6t2 }));
454 //etc.
455
456 testing.expect(!usesThumb1(builtin.Arch{ .aarch64 = .v8 }));
457 testing.expect(!usesThumb1(builtin.Arch{ .aarch64_be = .v8 }));
458 testing.expect(!usesThumb1(builtin.Arch.x86_64));
459 testing.expect(!usesThumb1(builtin.Arch.riscv32));
460 //etc.
279}461}
280462
281nakedcc fn __aeabi_memcpy() noreturn {463nakedcc fn __aeabi_memcpy() noreturn {
...@@ -368,107 +550,12 @@ nakedcc fn __aeabi_memcmp() noreturn {...@@ -368,107 +550,12 @@ nakedcc fn __aeabi_memcmp() noreturn {
368 unreachable;550 unreachable;
369}551}
370552
371// _chkstk (_alloca) routine - probe stack between %esp and (%esp-%eax) in 4k increments,553extern fn __divmodsi4(a: i32, b: i32, rem: *i32) i32 {
372// then decrement %esp by %eax. Preserves all registers except %esp and flags.554 @setRuntimeSafety(is_test);
373// This routine is windows specific
374// http://msdn.microsoft.com/en-us/library/ms648426.aspx
375nakedcc fn _chkstk() align(4) void {
376 @setRuntimeSafety(false);
377
378 asm volatile (
379 \\ push %%ecx
380 \\ push %%eax
381 \\ cmp $0x1000,%%eax
382 \\ lea 12(%%esp),%%ecx
383 \\ jb 1f
384 \\ 2:
385 \\ sub $0x1000,%%ecx
386 \\ test %%ecx,(%%ecx)
387 \\ sub $0x1000,%%eax
388 \\ cmp $0x1000,%%eax
389 \\ ja 2b
390 \\ 1:
391 \\ sub %%eax,%%ecx
392 \\ test %%ecx,(%%ecx)
393 \\ pop %%eax
394 \\ pop %%ecx
395 \\ ret
396 );
397}
398
399nakedcc fn __chkstk() align(4) void {
400 @setRuntimeSafety(false);
401
402 asm volatile (
403 \\ push %%rcx
404 \\ push %%rax
405 \\ cmp $0x1000,%%rax
406 \\ lea 24(%%rsp),%%rcx
407 \\ jb 1f
408 \\2:
409 \\ sub $0x1000,%%rcx
410 \\ test %%rcx,(%%rcx)
411 \\ sub $0x1000,%%rax
412 \\ cmp $0x1000,%%rax
413 \\ ja 2b
414 \\1:
415 \\ sub %%rax,%%rcx
416 \\ test %%rcx,(%%rcx)
417 \\ pop %%rax
418 \\ pop %%rcx
419 \\ ret
420 );
421}
422
423// _chkstk routine
424// This routine is windows specific
425// http://msdn.microsoft.com/en-us/library/ms648426.aspx
426nakedcc fn __chkstk_ms() align(4) void {
427 @setRuntimeSafety(false);
428
429 asm volatile (
430 \\ push %%ecx
431 \\ push %%eax
432 \\ cmp $0x1000,%%eax
433 \\ lea 12(%%esp),%%ecx
434 \\ jb 1f
435 \\ 2:
436 \\ sub $0x1000,%%ecx
437 \\ test %%ecx,(%%ecx)
438 \\ sub $0x1000,%%eax
439 \\ cmp $0x1000,%%eax
440 \\ ja 2b
441 \\ 1:
442 \\ sub %%eax,%%ecx
443 \\ test %%ecx,(%%ecx)
444 \\ pop %%eax
445 \\ pop %%ecx
446 \\ ret
447 );
448}
449
450nakedcc fn ___chkstk_ms() align(4) void {
451 @setRuntimeSafety(false);
452555
453 asm volatile (556 const d = __divsi3(a, b);
454 \\ push %%rcx557 rem.* = a -% (d * b);
455 \\ push %%rax558 return d;
456 \\ cmp $0x1000,%%rax
457 \\ lea 24(%%rsp),%%rcx
458 \\ jb 1f
459 \\2:
460 \\ sub $0x1000,%%rcx
461 \\ test %%rcx,(%%rcx)
462 \\ sub $0x1000,%%rax
463 \\ cmp $0x1000,%%rax
464 \\ ja 2b
465 \\1:
466 \\ sub %%rax,%%rcx
467 \\ test %%rcx,(%%rcx)
468 \\ pop %%rax
469 \\ pop %%rcx
470 \\ ret
471 );
472}559}
473560
474extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {561extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {
...@@ -479,6 +566,20 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {...@@ -479,6 +566,20 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {
479 return d;566 return d;
480}567}
481568
569extern fn __divsi3(n: i32, d: i32) i32 {
570 @setRuntimeSafety(is_test);
571
572 // Set aside the sign of the quotient.
573 const sign = @bitCast(u32, (n ^ d) >> 31);
574 // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
575 const abs_n = (n ^ (n >> 31)) -% (n >> 31);
576 const abs_d = (d ^ (d >> 31)) -% (d >> 31);
577 // abs(a) / abs(b)
578 const res = @bitCast(u32, abs_n) / @bitCast(u32, abs_d);
579 // Apply sign of quotient to result and return.
580 return @bitCast(i32, (res ^ sign) -% sign);
581}
582
482extern fn __udivsi3(n: u32, d: u32) u32 {583extern fn __udivsi3(n: u32, d: u32) u32 {
483 @setRuntimeSafety(is_test);584 @setRuntimeSafety(is_test);
484585
...@@ -520,6 +621,18 @@ extern fn __udivsi3(n: u32, d: u32) u32 {...@@ -520,6 +621,18 @@ extern fn __udivsi3(n: u32, d: u32) u32 {
520 return q;621 return q;
521}622}
522623
624extern fn __modsi3(n: i32, d: i32) i32 {
625 @setRuntimeSafety(is_test);
626
627 return n -% __divsi3(n, d) *% d;
628}
629
630extern fn __umodsi3(n: u32, d: u32) u32 {
631 @setRuntimeSafety(is_test);
632
633 return n -% __udivsi3(n, d) *% d;
634}
635
523test "test_umoddi3" {636test "test_umoddi3" {
524 test_one_umoddi3(0, 1, 0);637 test_one_umoddi3(0, 1, 0);
525 test_one_umoddi3(2, 1, 0);638 test_one_umoddi3(2, 1, 0);
...@@ -1206,3 +1319,279 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void {...@@ -1206,3 +1319,279 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void {
1206 const q: u32 = __udivsi3(a, b);1319 const q: u32 = __udivsi3(a, b);
1207 testing.expect(q == expected_q);1320 testing.expect(q == expected_q);
1208}1321}
1322
1323test "test_divsi3" {
1324 const cases = [][3]i32{
1325 []i32{ 0, 1, 0 },
1326 []i32{ 0, -1, 0 },
1327 []i32{ 2, 1, 2 },
1328 []i32{ 2, -1, -2 },
1329 []i32{ -2, 1, -2 },
1330 []i32{ -2, -1, 2 },
1331
1332 []i32{ @bitCast(i32, u32(0x80000000)), 1, @bitCast(i32, u32(0x80000000)) },
1333 []i32{ @bitCast(i32, u32(0x80000000)), -1, @bitCast(i32, u32(0x80000000)) },
1334 []i32{ @bitCast(i32, u32(0x80000000)), -2, 0x40000000 },
1335 []i32{ @bitCast(i32, u32(0x80000000)), 2, @bitCast(i32, u32(0xC0000000)) },
1336 };
1337
1338 for (cases) |case| {
1339 test_one_divsi3(case[0], case[1], case[2]);
1340 }
1341}
1342
1343fn test_one_divsi3(a: i32, b: i32, expected_q: i32) void {
1344 const q: i32 = __divsi3(a, b);
1345 testing.expect(q == expected_q);
1346}
1347
1348test "test_divmodsi4" {
1349 const cases = [][4]i32{
1350 []i32{ 0, 1, 0, 0 },
1351 []i32{ 0, -1, 0, 0 },
1352 []i32{ 2, 1, 2, 0 },
1353 []i32{ 2, -1, -2, 0 },
1354 []i32{ -2, 1, -2, 0 },
1355 []i32{ -2, -1, 2, 0 },
1356 []i32{ 7, 5, 1, 2 },
1357 []i32{ -7, 5, -1, -2 },
1358 []i32{ 19, 5, 3, 4 },
1359 []i32{ 19, -5, -3, 4 },
1360
1361 []i32{ @bitCast(i32, u32(0x80000000)), 8, @bitCast(i32, u32(0xf0000000)), 0 },
1362 []i32{ @bitCast(i32, u32(0x80000007)), 8, @bitCast(i32, u32(0xf0000001)), -1 },
1363 };
1364
1365 for (cases) |case| {
1366 test_one_divmodsi4(case[0], case[1], case[2], case[3]);
1367 }
1368}
1369
1370fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) void {
1371 var r: i32 = undefined;
1372 const q: i32 = __divmodsi4(a, b, &r);
1373 testing.expect(q == expected_q and r == expected_r);
1374}
1375
1376test "test_divdi3" {
1377 const cases = [][3]i64{
1378 []i64{ 0, 1, 0 },
1379 []i64{ 0, -1, 0 },
1380 []i64{ 2, 1, 2 },
1381 []i64{ 2, -1, -2 },
1382 []i64{ -2, 1, -2 },
1383 []i64{ -2, -1, 2 },
1384
1385 []i64{ @bitCast(i64, u64(0x8000000000000000)), 1, @bitCast(i64, u64(0x8000000000000000)) },
1386 []i64{ @bitCast(i64, u64(0x8000000000000000)), -1, @bitCast(i64, u64(0x8000000000000000)) },
1387 []i64{ @bitCast(i64, u64(0x8000000000000000)), -2, 0x4000000000000000 },
1388 []i64{ @bitCast(i64, u64(0x8000000000000000)), 2, @bitCast(i64, u64(0xC000000000000000)) },
1389 };
1390
1391 for (cases) |case| {
1392 test_one_divdi3(case[0], case[1], case[2]);
1393 }
1394}
1395
1396fn test_one_divdi3(a: i64, b: i64, expected_q: i64) void {
1397 const q: i64 = __divdi3(a, b);
1398 testing.expect(q == expected_q);
1399}
1400
1401test "test_moddi3" {
1402 const cases = [][3]i64{
1403 []i64{ 0, 1, 0 },
1404 []i64{ 0, -1, 0 },
1405 []i64{ 5, 3, 2 },
1406 []i64{ 5, -3, 2 },
1407 []i64{ -5, 3, -2 },
1408 []i64{ -5, -3, -2 },
1409
1410 []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), 1, 0 },
1411 []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), -1, 0 },
1412 []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), 2, 0 },
1413 []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), -2, 0 },
1414 []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), 3, -2 },
1415 []i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), -3, -2 },
1416 };
1417
1418 for (cases) |case| {
1419 test_one_moddi3(case[0], case[1], case[2]);
1420 }
1421}
1422
1423fn test_one_moddi3(a: i64, b: i64, expected_r: i64) void {
1424 const r: i64 = __moddi3(a, b);
1425 testing.expect(r == expected_r);
1426}
1427
1428test "test_modsi3" {
1429 const cases = [][3]i32{
1430 []i32{ 0, 1, 0 },
1431 []i32{ 0, -1, 0 },
1432 []i32{ 5, 3, 2 },
1433 []i32{ 5, -3, 2 },
1434 []i32{ -5, 3, -2 },
1435 []i32{ -5, -3, -2 },
1436 []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 1, 0x0 },
1437 []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 2, 0x0 },
1438 []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -2, 0x0 },
1439 []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 3, -2 },
1440 []i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -3, -2 },
1441 };
1442
1443 for (cases) |case| {
1444 test_one_modsi3(case[0], case[1], case[2]);
1445 }
1446}
1447
1448fn test_one_modsi3(a: i32, b: i32, expected_r: i32) void {
1449 const r: i32 = __modsi3(a, b);
1450 testing.expect(r == expected_r);
1451}
1452
1453test "test_umodsi3" {
1454 const cases = [][3]u32{
1455 []u32{ 0x00000000, 0x00000001, 0x00000000 },
1456 []u32{ 0x00000000, 0x00000002, 0x00000000 },
1457 []u32{ 0x00000000, 0x00000003, 0x00000000 },
1458 []u32{ 0x00000000, 0x00000010, 0x00000000 },
1459 []u32{ 0x00000000, 0x078644FA, 0x00000000 },
1460 []u32{ 0x00000000, 0x0747AE14, 0x00000000 },
1461 []u32{ 0x00000000, 0x7FFFFFFF, 0x00000000 },
1462 []u32{ 0x00000000, 0x80000000, 0x00000000 },
1463 []u32{ 0x00000000, 0xFFFFFFFD, 0x00000000 },
1464 []u32{ 0x00000000, 0xFFFFFFFE, 0x00000000 },
1465 []u32{ 0x00000000, 0xFFFFFFFF, 0x00000000 },
1466 []u32{ 0x00000001, 0x00000001, 0x00000000 },
1467 []u32{ 0x00000001, 0x00000002, 0x00000001 },
1468 []u32{ 0x00000001, 0x00000003, 0x00000001 },
1469 []u32{ 0x00000001, 0x00000010, 0x00000001 },
1470 []u32{ 0x00000001, 0x078644FA, 0x00000001 },
1471 []u32{ 0x00000001, 0x0747AE14, 0x00000001 },
1472 []u32{ 0x00000001, 0x7FFFFFFF, 0x00000001 },
1473 []u32{ 0x00000001, 0x80000000, 0x00000001 },
1474 []u32{ 0x00000001, 0xFFFFFFFD, 0x00000001 },
1475 []u32{ 0x00000001, 0xFFFFFFFE, 0x00000001 },
1476 []u32{ 0x00000001, 0xFFFFFFFF, 0x00000001 },
1477 []u32{ 0x00000002, 0x00000001, 0x00000000 },
1478 []u32{ 0x00000002, 0x00000002, 0x00000000 },
1479 []u32{ 0x00000002, 0x00000003, 0x00000002 },
1480 []u32{ 0x00000002, 0x00000010, 0x00000002 },
1481 []u32{ 0x00000002, 0x078644FA, 0x00000002 },
1482 []u32{ 0x00000002, 0x0747AE14, 0x00000002 },
1483 []u32{ 0x00000002, 0x7FFFFFFF, 0x00000002 },
1484 []u32{ 0x00000002, 0x80000000, 0x00000002 },
1485 []u32{ 0x00000002, 0xFFFFFFFD, 0x00000002 },
1486 []u32{ 0x00000002, 0xFFFFFFFE, 0x00000002 },
1487 []u32{ 0x00000002, 0xFFFFFFFF, 0x00000002 },
1488 []u32{ 0x00000003, 0x00000001, 0x00000000 },
1489 []u32{ 0x00000003, 0x00000002, 0x00000001 },
1490 []u32{ 0x00000003, 0x00000003, 0x00000000 },
1491 []u32{ 0x00000003, 0x00000010, 0x00000003 },
1492 []u32{ 0x00000003, 0x078644FA, 0x00000003 },
1493 []u32{ 0x00000003, 0x0747AE14, 0x00000003 },
1494 []u32{ 0x00000003, 0x7FFFFFFF, 0x00000003 },
1495 []u32{ 0x00000003, 0x80000000, 0x00000003 },
1496 []u32{ 0x00000003, 0xFFFFFFFD, 0x00000003 },
1497 []u32{ 0x00000003, 0xFFFFFFFE, 0x00000003 },
1498 []u32{ 0x00000003, 0xFFFFFFFF, 0x00000003 },
1499 []u32{ 0x00000010, 0x00000001, 0x00000000 },
1500 []u32{ 0x00000010, 0x00000002, 0x00000000 },
1501 []u32{ 0x00000010, 0x00000003, 0x00000001 },
1502 []u32{ 0x00000010, 0x00000010, 0x00000000 },
1503 []u32{ 0x00000010, 0x078644FA, 0x00000010 },
1504 []u32{ 0x00000010, 0x0747AE14, 0x00000010 },
1505 []u32{ 0x00000010, 0x7FFFFFFF, 0x00000010 },
1506 []u32{ 0x00000010, 0x80000000, 0x00000010 },
1507 []u32{ 0x00000010, 0xFFFFFFFD, 0x00000010 },
1508 []u32{ 0x00000010, 0xFFFFFFFE, 0x00000010 },
1509 []u32{ 0x00000010, 0xFFFFFFFF, 0x00000010 },
1510 []u32{ 0x078644FA, 0x00000001, 0x00000000 },
1511 []u32{ 0x078644FA, 0x00000002, 0x00000000 },
1512 []u32{ 0x078644FA, 0x00000003, 0x00000000 },
1513 []u32{ 0x078644FA, 0x00000010, 0x0000000A },
1514 []u32{ 0x078644FA, 0x078644FA, 0x00000000 },
1515 []u32{ 0x078644FA, 0x0747AE14, 0x003E96E6 },
1516 []u32{ 0x078644FA, 0x7FFFFFFF, 0x078644FA },
1517 []u32{ 0x078644FA, 0x80000000, 0x078644FA },
1518 []u32{ 0x078644FA, 0xFFFFFFFD, 0x078644FA },
1519 []u32{ 0x078644FA, 0xFFFFFFFE, 0x078644FA },
1520 []u32{ 0x078644FA, 0xFFFFFFFF, 0x078644FA },
1521 []u32{ 0x0747AE14, 0x00000001, 0x00000000 },
1522 []u32{ 0x0747AE14, 0x00000002, 0x00000000 },
1523 []u32{ 0x0747AE14, 0x00000003, 0x00000002 },
1524 []u32{ 0x0747AE14, 0x00000010, 0x00000004 },
1525 []u32{ 0x0747AE14, 0x078644FA, 0x0747AE14 },
1526 []u32{ 0x0747AE14, 0x0747AE14, 0x00000000 },
1527 []u32{ 0x0747AE14, 0x7FFFFFFF, 0x0747AE14 },
1528 []u32{ 0x0747AE14, 0x80000000, 0x0747AE14 },
1529 []u32{ 0x0747AE14, 0xFFFFFFFD, 0x0747AE14 },
1530 []u32{ 0x0747AE14, 0xFFFFFFFE, 0x0747AE14 },
1531 []u32{ 0x0747AE14, 0xFFFFFFFF, 0x0747AE14 },
1532 []u32{ 0x7FFFFFFF, 0x00000001, 0x00000000 },
1533 []u32{ 0x7FFFFFFF, 0x00000002, 0x00000001 },
1534 []u32{ 0x7FFFFFFF, 0x00000003, 0x00000001 },
1535 []u32{ 0x7FFFFFFF, 0x00000010, 0x0000000F },
1536 []u32{ 0x7FFFFFFF, 0x078644FA, 0x00156B65 },
1537 []u32{ 0x7FFFFFFF, 0x0747AE14, 0x043D70AB },
1538 []u32{ 0x7FFFFFFF, 0x7FFFFFFF, 0x00000000 },
1539 []u32{ 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF },
1540 []u32{ 0x7FFFFFFF, 0xFFFFFFFD, 0x7FFFFFFF },
1541 []u32{ 0x7FFFFFFF, 0xFFFFFFFE, 0x7FFFFFFF },
1542 []u32{ 0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF },
1543 []u32{ 0x80000000, 0x00000001, 0x00000000 },
1544 []u32{ 0x80000000, 0x00000002, 0x00000000 },
1545 []u32{ 0x80000000, 0x00000003, 0x00000002 },
1546 []u32{ 0x80000000, 0x00000010, 0x00000000 },
1547 []u32{ 0x80000000, 0x078644FA, 0x00156B66 },
1548 []u32{ 0x80000000, 0x0747AE14, 0x043D70AC },
1549 []u32{ 0x80000000, 0x7FFFFFFF, 0x00000001 },
1550 []u32{ 0x80000000, 0x80000000, 0x00000000 },
1551 []u32{ 0x80000000, 0xFFFFFFFD, 0x80000000 },
1552 []u32{ 0x80000000, 0xFFFFFFFE, 0x80000000 },
1553 []u32{ 0x80000000, 0xFFFFFFFF, 0x80000000 },
1554 []u32{ 0xFFFFFFFD, 0x00000001, 0x00000000 },
1555 []u32{ 0xFFFFFFFD, 0x00000002, 0x00000001 },
1556 []u32{ 0xFFFFFFFD, 0x00000003, 0x00000001 },
1557 []u32{ 0xFFFFFFFD, 0x00000010, 0x0000000D },
1558 []u32{ 0xFFFFFFFD, 0x078644FA, 0x002AD6C9 },
1559 []u32{ 0xFFFFFFFD, 0x0747AE14, 0x01333341 },
1560 []u32{ 0xFFFFFFFD, 0x7FFFFFFF, 0x7FFFFFFE },
1561 []u32{ 0xFFFFFFFD, 0x80000000, 0x7FFFFFFD },
1562 []u32{ 0xFFFFFFFD, 0xFFFFFFFD, 0x00000000 },
1563 []u32{ 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFD },
1564 []u32{ 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFD },
1565 []u32{ 0xFFFFFFFE, 0x00000001, 0x00000000 },
1566 []u32{ 0xFFFFFFFE, 0x00000002, 0x00000000 },
1567 []u32{ 0xFFFFFFFE, 0x00000003, 0x00000002 },
1568 []u32{ 0xFFFFFFFE, 0x00000010, 0x0000000E },
1569 []u32{ 0xFFFFFFFE, 0x078644FA, 0x002AD6CA },
1570 []u32{ 0xFFFFFFFE, 0x0747AE14, 0x01333342 },
1571 []u32{ 0xFFFFFFFE, 0x7FFFFFFF, 0x00000000 },
1572 []u32{ 0xFFFFFFFE, 0x80000000, 0x7FFFFFFE },
1573 []u32{ 0xFFFFFFFE, 0xFFFFFFFD, 0x00000001 },
1574 []u32{ 0xFFFFFFFE, 0xFFFFFFFE, 0x00000000 },
1575 []u32{ 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFE },
1576 []u32{ 0xFFFFFFFF, 0x00000001, 0x00000000 },
1577 []u32{ 0xFFFFFFFF, 0x00000002, 0x00000001 },
1578 []u32{ 0xFFFFFFFF, 0x00000003, 0x00000000 },
1579 []u32{ 0xFFFFFFFF, 0x00000010, 0x0000000F },
1580 []u32{ 0xFFFFFFFF, 0x078644FA, 0x002AD6CB },
1581 []u32{ 0xFFFFFFFF, 0x0747AE14, 0x01333343 },
1582 []u32{ 0xFFFFFFFF, 0x7FFFFFFF, 0x00000001 },
1583 []u32{ 0xFFFFFFFF, 0x80000000, 0x7FFFFFFF },
1584 []u32{ 0xFFFFFFFF, 0xFFFFFFFD, 0x00000002 },
1585 []u32{ 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001 },
1586 []u32{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 },
1587 };
1588
1589 for (cases) |case| {
1590 test_one_umodsi3(case[0], case[1], case[2]);
1591 }
1592}
1593
1594fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) void {
1595 const r: u32 = __umodsi3(a, b);
1596 testing.expect(r == expected_r);
1597}
std/special/compiler_rt/addXf3.zig+2-2
...@@ -78,8 +78,8 @@ fn addXf3(comptime T: type, a: T, b: T) T {...@@ -78,8 +78,8 @@ fn addXf3(comptime T: type, a: T, b: T) T {
78 const infRep = @bitCast(Z, std.math.inf(T));78 const infRep = @bitCast(Z, std.math.inf(T));
7979
80 // Detect if a or b is zero, infinity, or NaN.80 // Detect if a or b is zero, infinity, or NaN.
81 if (aAbs - Z(1) >= infRep - Z(1) or81 if (aAbs -% Z(1) >= infRep - Z(1) or
82 bAbs - Z(1) >= infRep - Z(1))82 bAbs -% Z(1) >= infRep - Z(1))
83 {83 {
84 // NaN + anything = qNaN84 // NaN + anything = qNaN
85 if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);85 if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
std/special/compiler_rt/arm/aeabi_dcmp.zig created+108
...@@ -0,0 +1,108 @@
1// Ported from:
2//
3// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_dcmp.S
4
5const compiler_rt_armhf_target = false; // TODO
6
7const ConditionalOperator = enum {
8 Eq,
9 Lt,
10 Le,
11 Ge,
12 Gt,
13};
14
15pub nakedcc fn __aeabi_dcmpeq() noreturn {
16 @setRuntimeSafety(false);
17 aeabi_dcmp(.Eq);
18 unreachable;
19}
20
21pub nakedcc fn __aeabi_dcmplt() noreturn {
22 @setRuntimeSafety(false);
23 aeabi_dcmp(.Lt);
24 unreachable;
25}
26
27pub nakedcc fn __aeabi_dcmple() noreturn {
28 @setRuntimeSafety(false);
29 aeabi_dcmp(.Le);
30 unreachable;
31}
32
33pub nakedcc fn __aeabi_dcmpge() noreturn {
34 @setRuntimeSafety(false);
35 aeabi_dcmp(.Ge);
36 unreachable;
37}
38
39pub nakedcc fn __aeabi_dcmpgt() noreturn {
40 @setRuntimeSafety(false);
41 aeabi_dcmp(.Gt);
42 unreachable;
43}
44
45inline fn convert_dcmp_args_to_df2_args() void {
46 asm volatile (
47 \\ vmov d0, r0, r1
48 \\ vmov d1, r2, r3
49 );
50}
51
52inline fn aeabi_dcmp(comptime cond: ConditionalOperator) void {
53 @setRuntimeSafety(false);
54 asm volatile (
55 \\ push { r4, lr }
56 );
57
58 if (compiler_rt_armhf_target) {
59 convert_dcmp_args_to_df2_args();
60 }
61
62 switch (cond) {
63 .Eq => asm volatile (
64 \\ bl __eqdf2
65 \\ cmp r0, #0
66 \\ beq 1f
67 \\ movs r0, #0
68 \\ pop { r4, pc }
69 \\ 1:
70 ),
71 .Lt => asm volatile (
72 \\ bl __ltdf2
73 \\ cmp r0, #0
74 \\ blt 1f
75 \\ movs r0, #0
76 \\ pop { r4, pc }
77 \\ 1:
78 ),
79 .Le => asm volatile (
80 \\ bl __ledf2
81 \\ cmp r0, #0
82 \\ ble 1f
83 \\ movs r0, #0
84 \\ pop { r4, pc }
85 \\ 1:
86 ),
87 .Ge => asm volatile (
88 \\ bl __ltdf2
89 \\ cmp r0, #0
90 \\ bge 1f
91 \\ movs r0, #0
92 \\ pop { r4, pc }
93 \\ 1:
94 ),
95 .Gt => asm volatile (
96 \\ bl __gtdf2
97 \\ cmp r0, #0
98 \\ bgt 1f
99 \\ movs r0, #0
100 \\ pop { r4, pc }
101 \\ 1:
102 ),
103 }
104 asm volatile (
105 \\ movs r0, #1
106 \\ pop { r4, pc }
107 );
108}
std/special/compiler_rt/arm/aeabi_fcmp.zig created+108
...@@ -0,0 +1,108 @@
1// Ported from:
2//
3// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_fcmp.S
4
5const compiler_rt_armhf_target = false; // TODO
6
7const ConditionalOperator = enum {
8 Eq,
9 Lt,
10 Le,
11 Ge,
12 Gt,
13};
14
15pub nakedcc fn __aeabi_fcmpeq() noreturn {
16 @setRuntimeSafety(false);
17 aeabi_fcmp(.Eq);
18 unreachable;
19}
20
21pub nakedcc fn __aeabi_fcmplt() noreturn {
22 @setRuntimeSafety(false);
23 aeabi_fcmp(.Lt);
24 unreachable;
25}
26
27pub nakedcc fn __aeabi_fcmple() noreturn {
28 @setRuntimeSafety(false);
29 aeabi_fcmp(.Le);
30 unreachable;
31}
32
33pub nakedcc fn __aeabi_fcmpge() noreturn {
34 @setRuntimeSafety(false);
35 aeabi_fcmp(.Ge);
36 unreachable;
37}
38
39pub nakedcc fn __aeabi_fcmpgt() noreturn {
40 @setRuntimeSafety(false);
41 aeabi_fcmp(.Gt);
42 unreachable;
43}
44
45inline fn convert_fcmp_args_to_sf2_args() void {
46 asm volatile (
47 \\ vmov s0, r0
48 \\ vmov s1, r1
49 );
50}
51
52inline fn aeabi_fcmp(comptime cond: ConditionalOperator) void {
53 @setRuntimeSafety(false);
54 asm volatile (
55 \\ push { r4, lr }
56 );
57
58 if (compiler_rt_armhf_target) {
59 convert_fcmp_args_to_sf2_args();
60 }
61
62 switch (cond) {
63 .Eq => asm volatile (
64 \\ bl __eqsf2
65 \\ cmp r0, #0
66 \\ beq 1f
67 \\ movs r0, #0
68 \\ pop { r4, pc }
69 \\ 1:
70 ),
71 .Lt => asm volatile (
72 \\ bl __ltsf2
73 \\ cmp r0, #0
74 \\ blt 1f
75 \\ movs r0, #0
76 \\ pop { r4, pc }
77 \\ 1:
78 ),
79 .Le => asm volatile (
80 \\ bl __lesf2
81 \\ cmp r0, #0
82 \\ ble 1f
83 \\ movs r0, #0
84 \\ pop { r4, pc }
85 \\ 1:
86 ),
87 .Ge => asm volatile (
88 \\ bl __ltsf2
89 \\ cmp r0, #0
90 \\ bge 1f
91 \\ movs r0, #0
92 \\ pop { r4, pc }
93 \\ 1:
94 ),
95 .Gt => asm volatile (
96 \\ bl __gtsf2
97 \\ cmp r0, #0
98 \\ bgt 1f
99 \\ movs r0, #0
100 \\ pop { r4, pc }
101 \\ 1:
102 ),
103 }
104 asm volatile (
105 \\ movs r0, #1
106 \\ pop { r4, pc }
107 );
108}
std/special/compiler_rt/ashlti3.zig created+41
...@@ -0,0 +1,41 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3
4pub extern fn __ashlti3(a: i128, b: i32) i128 {
5 var input = twords{ .all = a };
6 var result: twords = undefined;
7
8 if (b > 63) {
9 // 64 <= b < 128
10 result.s.low = 0;
11 result.s.high = input.s.low << @intCast(u6, b - 64);
12 } else {
13 // 0 <= b < 64
14 if (b == 0) return a;
15 result.s.low = input.s.low << @intCast(u6, b);
16 result.s.high = input.s.low >> @intCast(u6, 64 - b);
17 result.s.high |= input.s.high << @intCast(u6, b);
18 }
19
20 return result.all;
21}
22
23const twords = extern union {
24 all: i128,
25 s: S,
26
27 const S = if (builtin.endian == builtin.Endian.Little)
28 struct {
29 low: u64,
30 high: u64,
31 }
32 else
33 struct {
34 high: u64,
35 low: u64,
36 };
37};
38
39test "import ashlti3" {
40 _ = @import("ashlti3_test.zig");
41}
std/special/compiler_rt/ashlti3_test.zig created+46
...@@ -0,0 +1,46 @@
1const __ashlti3 = @import("ashlti3.zig").__ashlti3;
2const testing = @import("std").testing;
3
4fn test__ashlti3(a: i128, b: i32, expected: i128) void {
5 const x = __ashlti3(a, b);
6 testing.expect(x == expected);
7}
8
9test "ashlti3" {
10 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 0, @bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)));
11 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 1, @bitCast(i128, @intCast(u128, 0xFDB97530ECA8642BFDB97530ECA8642A)));
12 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 2, @bitCast(i128, @intCast(u128, 0xFB72EA61D950C857FB72EA61D950C854)));
13 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 3, @bitCast(i128, @intCast(u128, 0xF6E5D4C3B2A190AFF6E5D4C3B2A190A8)));
14 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 4, @bitCast(i128, @intCast(u128, 0xEDCBA9876543215FEDCBA98765432150)));
15 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 28, @bitCast(i128, @intCast(u128, 0x876543215FEDCBA98765432150000000)));
16 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 29, @bitCast(i128, @intCast(u128, 0x0ECA8642BFDB97530ECA8642A0000000)));
17 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 30, @bitCast(i128, @intCast(u128, 0x1D950C857FB72EA61D950C8540000000)));
18 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 31, @bitCast(i128, @intCast(u128, 0x3B2A190AFF6E5D4C3B2A190A80000000)));
19 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 32, @bitCast(i128, @intCast(u128, 0x76543215FEDCBA987654321500000000)));
20 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 33, @bitCast(i128, @intCast(u128, 0xECA8642BFDB97530ECA8642A00000000)));
21 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 34, @bitCast(i128, @intCast(u128, 0xD950C857FB72EA61D950C85400000000)));
22 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 35, @bitCast(i128, @intCast(u128, 0xB2A190AFF6E5D4C3B2A190A800000000)));
23 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 36, @bitCast(i128, @intCast(u128, 0x6543215FEDCBA9876543215000000000)));
24 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 60, @bitCast(i128, @intCast(u128, 0x5FEDCBA9876543215000000000000000)));
25 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 61, @bitCast(i128, @intCast(u128, 0xBFDB97530ECA8642A000000000000000)));
26 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 62, @bitCast(i128, @intCast(u128, 0x7FB72EA61D950C854000000000000000)));
27 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 63, @bitCast(i128, @intCast(u128, 0xFF6E5D4C3B2A190A8000000000000000)));
28 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 64, @bitCast(i128, @intCast(u128, 0xFEDCBA98765432150000000000000000)));
29 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 65, @bitCast(i128, @intCast(u128, 0xFDB97530ECA8642A0000000000000000)));
30 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 66, @bitCast(i128, @intCast(u128, 0xFB72EA61D950C8540000000000000000)));
31 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 67, @bitCast(i128, @intCast(u128, 0xF6E5D4C3B2A190A80000000000000000)));
32 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 68, @bitCast(i128, @intCast(u128, 0xEDCBA987654321500000000000000000)));
33 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 92, @bitCast(i128, @intCast(u128, 0x87654321500000000000000000000000)));
34 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 93, @bitCast(i128, @intCast(u128, 0x0ECA8642A00000000000000000000000)));
35 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 94, @bitCast(i128, @intCast(u128, 0x1D950C85400000000000000000000000)));
36 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 95, @bitCast(i128, @intCast(u128, 0x3B2A190A800000000000000000000000)));
37 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 96, @bitCast(i128, @intCast(u128, 0x76543215000000000000000000000000)));
38 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 97, @bitCast(i128, @intCast(u128, 0xECA8642A000000000000000000000000)));
39 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 98, @bitCast(i128, @intCast(u128, 0xD950C854000000000000000000000000)));
40 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 99, @bitCast(i128, @intCast(u128, 0xB2A190A8000000000000000000000000)));
41 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 100, @bitCast(i128, @intCast(u128, 0x65432150000000000000000000000000)));
42 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 124, @bitCast(i128, @intCast(u128, 0x50000000000000000000000000000000)));
43 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 125, @bitCast(i128, @intCast(u128, 0xA0000000000000000000000000000000)));
44 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 126, @bitCast(i128, @intCast(u128, 0x40000000000000000000000000000000)));
45 test__ashlti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 127, @bitCast(i128, @intCast(u128, 0x80000000000000000000000000000000)));
46}
std/special/compiler_rt/ashrti3.zig created+42
...@@ -0,0 +1,42 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3
4pub extern fn __ashrti3(a: i128, b: i32) i128 {
5 var input = twords{ .all = a };
6 var result: twords = undefined;
7
8 if (b > 63) {
9 // 64 <= b < 128
10 result.s.low = input.s.high >> @intCast(u6, b - 64);
11 result.s.high = input.s.high >> 63;
12 } else {
13 // 0 <= b < 64
14 if (b == 0) return a;
15 result.s.low = input.s.high << @intCast(u6, 64 - b);
16 // Avoid sign-extension here
17 result.s.low |= @bitCast(i64, @bitCast(u64, input.s.low) >> @intCast(u6, b));
18 result.s.high = input.s.high >> @intCast(u6, b);
19 }
20
21 return result.all;
22}
23
24const twords = extern union {
25 all: i128,
26 s: S,
27
28 const S = if (builtin.endian == builtin.Endian.Little)
29 struct {
30 low: i64,
31 high: i64,
32 }
33 else
34 struct {
35 high: i64,
36 low: i64,
37 };
38};
39
40test "import ashrti3" {
41 _ = @import("ashrti3_test.zig");
42}
std/special/compiler_rt/ashrti3_test.zig created+58
...@@ -0,0 +1,58 @@
1const __ashrti3 = @import("ashrti3.zig").__ashrti3;
2const testing = @import("std").testing;
3
4fn test__ashrti3(a: i128, b: i32, expected: i128) void {
5 const x = __ashrti3(a, b);
6 // @import("std").debug.warn("got 0x{x}\nexp 0x{x}\n", @truncate(u64,
7// @bitCast(u128, x) >> 64), @truncate(u64, @bitCast(u128, expected)) >> 64);
8 testing.expect(x == expected);
9}
10
11test "ashrti3" {
12 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 0, @bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)));
13 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 1, @bitCast(i128, @intCast(u128, 0xFF6E5D4C3B2A190AFF6E5D4C3B2A190A)));
14 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 2, @bitCast(i128, @intCast(u128, 0xFFB72EA61D950C857FB72EA61D950C85)));
15 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 3, @bitCast(i128, @intCast(u128, 0xFFDB97530ECA8642BFDB97530ECA8642)));
16 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 4, @bitCast(i128, @intCast(u128, 0xFFEDCBA9876543215FEDCBA987654321)));
17
18 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 28, @bitCast(i128, @intCast(u128, 0xFFFFFFFFEDCBA9876543215FEDCBA987)));
19 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 29, @bitCast(i128, @intCast(u128, 0xFFFFFFFFF6E5D4C3B2A190AFF6E5D4C3)));
20 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 30, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFB72EA61D950C857FB72EA61)));
21 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 31, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFDB97530ECA8642BFDB97530)));
22
23 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 32, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFEDCBA9876543215FEDCBA98)));
24
25 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 33, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFF6E5D4C3B2A190AFF6E5D4C)));
26 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 34, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFB72EA61D950C857FB72EA6)));
27 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 35, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFDB97530ECA8642BFDB9753)));
28 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 36, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFEDCBA9876543215FEDCBA9)));
29
30 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 60, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFEDCBA9876543215F)));
31 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 61, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFF6E5D4C3B2A190AF)));
32 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 62, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFB72EA61D950C857)));
33 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 63, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFDB97530ECA8642B)));
34
35 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 64, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFEDCBA9876543215)));
36
37 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 65, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFF6E5D4C3B2A190A)));
38 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 66, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFB72EA61D950C85)));
39 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 67, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFDB97530ECA8642)));
40 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 68, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFEDCBA987654321)));
41
42 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 92, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFEDCBA987)));
43 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 93, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFF6E5D4C3)));
44 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 94, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFB72EA61)));
45 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 95, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFDB97530)));
46
47 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 96, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFEDCBA98)));
48
49 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 97, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFF6E5D4C)));
50 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 98, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFB72EA6)));
51 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 99, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFDB9753)));
52 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 100, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFEDCBA9)));
53
54 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 124, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)));
55 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 125, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)));
56 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 126, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)));
57 test__ashrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 127, @bitCast(i128, @intCast(u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)));
58}
std/special/compiler_rt/comparedf2.zig created+122
...@@ -0,0 +1,122 @@
1// Ported from:
2//
3// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparedf2.c
4
5const std = @import("std");
6const builtin = @import("builtin");
7const is_test = builtin.is_test;
8
9const fp_t = f64;
10const rep_t = u64;
11const srep_t = i64;
12
13const typeWidth = rep_t.bit_count;
14const significandBits = std.math.floatMantissaBits(fp_t);
15const exponentBits = std.math.floatExponentBits(fp_t);
16const signBit = (rep_t(1) << (significandBits + exponentBits));
17const absMask = signBit - 1;
18const implicitBit = rep_t(1) << significandBits;
19const significandMask = implicitBit - 1;
20const exponentMask = absMask ^ significandMask;
21const infRep = @bitCast(rep_t, std.math.inf(fp_t));
22
23// TODO https://github.com/ziglang/zig/issues/641
24// and then make the return types of some of these functions the enum instead of c_int
25const LE_LESS = c_int(-1);
26const LE_EQUAL = c_int(0);
27const LE_GREATER = c_int(1);
28const LE_UNORDERED = c_int(1);
29
30pub extern fn __ledf2(a: fp_t, b: fp_t) c_int {
31 @setRuntimeSafety(is_test);
32 const aInt: srep_t = @bitCast(srep_t, a);
33 const bInt: srep_t = @bitCast(srep_t, b);
34 const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
35 const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
36
37 // If either a or b is NaN, they are unordered.
38 if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED;
39
40 // If a and b are both zeros, they are equal.
41 if ((aAbs | bAbs) == 0) return LE_EQUAL;
42
43 // If at least one of a and b is positive, we get the same result comparing
44 // a and b as signed integers as we would with a fp_ting-point compare.
45 if ((aInt & bInt) >= 0) {
46 if (aInt < bInt) {
47 return LE_LESS;
48 } else if (aInt == bInt) {
49 return LE_EQUAL;
50 } else return LE_GREATER;
51 }
52
53 // Otherwise, both are negative, so we need to flip the sense of the
54 // comparison to get the correct result. (This assumes a twos- or ones-
55 // complement integer representation; if integers are represented in a
56 // sign-magnitude representation, then this flip is incorrect).
57 else {
58 if (aInt > bInt) {
59 return LE_LESS;
60 } else if (aInt == bInt) {
61 return LE_EQUAL;
62 } else return LE_GREATER;
63 }
64}
65
66// TODO https://github.com/ziglang/zig/issues/641
67// and then make the return types of some of these functions the enum instead of c_int
68const GE_LESS = c_int(-1);
69const GE_EQUAL = c_int(0);
70const GE_GREATER = c_int(1);
71const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED
72
73pub extern fn __gedf2(a: fp_t, b: fp_t) c_int {
74 @setRuntimeSafety(is_test);
75 const aInt: srep_t = @bitCast(srep_t, a);
76 const bInt: srep_t = @bitCast(srep_t, b);
77 const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
78 const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
79
80 if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
81 if ((aAbs | bAbs) == 0) return GE_EQUAL;
82 if ((aInt & bInt) >= 0) {
83 if (aInt < bInt) {
84 return GE_LESS;
85 } else if (aInt == bInt) {
86 return GE_EQUAL;
87 } else return GE_GREATER;
88 } else {
89 if (aInt > bInt) {
90 return GE_LESS;
91 } else if (aInt == bInt) {
92 return GE_EQUAL;
93 } else return GE_GREATER;
94 }
95}
96
97pub extern fn __unorddf2(a: fp_t, b: fp_t) c_int {
98 @setRuntimeSafety(is_test);
99 const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
100 const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
101 return @boolToInt(aAbs > infRep or bAbs > infRep);
102}
103
104pub extern fn __eqdf2(a: fp_t, b: fp_t) c_int {
105 return __ledf2(a, b);
106}
107
108pub extern fn __ltdf2(a: fp_t, b: fp_t) c_int {
109 return __ledf2(a, b);
110}
111
112pub extern fn __nedf2(a: fp_t, b: fp_t) c_int {
113 return __ledf2(a, b);
114}
115
116pub extern fn __gtdf2(a: fp_t, b: fp_t) c_int {
117 return __gedf2(a, b);
118}
119
120test "import comparedf2" {
121 _ = @import("comparedf2_test.zig");
122}
std/special/compiler_rt/comparedf2_test.zig created+101
...@@ -0,0 +1,101 @@
1// Ported from:
2//
3// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/comparedf2_test.c
4
5const std = @import("std");
6const builtin = @import("builtin");
7const is_test = builtin.is_test;
8
9const comparedf2 = @import("comparedf2.zig");
10
11const TestVector = struct {
12 a: f64,
13 b: f64,
14 eqReference: c_int,
15 geReference: c_int,
16 gtReference: c_int,
17 leReference: c_int,
18 ltReference: c_int,
19 neReference: c_int,
20 unReference: c_int,
21};
22
23fn test__cmpdf2(vector: TestVector) bool {
24 if (comparedf2.__eqdf2(vector.a, vector.b) != vector.eqReference) {
25 return false;
26 }
27 if (comparedf2.__gedf2(vector.a, vector.b) != vector.geReference) {
28 return false;
29 }
30 if (comparedf2.__gtdf2(vector.a, vector.b) != vector.gtReference) {
31 return false;
32 }
33 if (comparedf2.__ledf2(vector.a, vector.b) != vector.leReference) {
34 return false;
35 }
36 if (comparedf2.__ltdf2(vector.a, vector.b) != vector.ltReference) {
37 return false;
38 }
39 if (comparedf2.__nedf2(vector.a, vector.b) != vector.neReference) {
40 return false;
41 }
42 if (comparedf2.__unorddf2(vector.a, vector.b) != vector.unReference) {
43 return false;
44 }
45 return true;
46}
47
48const arguments = []f64{
49 std.math.nan(f64),
50 -std.math.inf(f64),
51 -0x1.fffffffffffffp1023,
52 -0x1.0000000000001p0 - 0x1.0000000000000p0,
53 -0x1.fffffffffffffp-1,
54 -0x1.0000000000000p-1022,
55 -0x0.fffffffffffffp-1022,
56 -0x0.0000000000001p-1022,
57 -0.0,
58 0.0,
59 0x0.0000000000001p-1022,
60 0x0.fffffffffffffp-1022,
61 0x1.0000000000000p-1022,
62 0x1.fffffffffffffp-1,
63 0x1.0000000000000p0,
64 0x1.0000000000001p0,
65 0x1.fffffffffffffp1023,
66 std.math.inf(f64),
67};
68
69fn generateVector(comptime a: f64, comptime b: f64) TestVector {
70 const leResult = if (a < b) -1 else if (a == b) 0 else 1;
71 const geResult = if (a > b) 1 else if (a == b) 0 else -1;
72 const unResult = if (a != a or b != b) 1 else 0;
73 return TestVector{
74 .a = a,
75 .b = b,
76 .eqReference = leResult,
77 .geReference = geResult,
78 .gtReference = geResult,
79 .leReference = leResult,
80 .ltReference = leResult,
81 .neReference = leResult,
82 .unReference = unResult,
83 };
84}
85
86const test_vectors = init: {
87 @setEvalBranchQuota(10000);
88 var vectors: [arguments.len * arguments.len]TestVector = undefined;
89 for (arguments[0..]) |arg_i, i| {
90 for (arguments[0..]) |arg_j, j| {
91 vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j);
92 }
93 }
94 break :init vectors;
95};
96
97test "compare f64" {
98 for (test_vectors) |vector, i| {
99 std.testing.expect(test__cmpdf2(vector));
100 }
101}
std/special/compiler_rt/comparesf2.zig created+122
...@@ -0,0 +1,122 @@
1// Ported from:
2//
3// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c
4
5const std = @import("std");
6const builtin = @import("builtin");
7const is_test = builtin.is_test;
8
9const fp_t = f32;
10const rep_t = u32;
11const srep_t = i32;
12
13const typeWidth = rep_t.bit_count;
14const significandBits = std.math.floatMantissaBits(fp_t);
15const exponentBits = std.math.floatExponentBits(fp_t);
16const signBit = (rep_t(1) << (significandBits + exponentBits));
17const absMask = signBit - 1;
18const implicitBit = rep_t(1) << significandBits;
19const significandMask = implicitBit - 1;
20const exponentMask = absMask ^ significandMask;
21const infRep = @bitCast(rep_t, std.math.inf(fp_t));
22
23// TODO https://github.com/ziglang/zig/issues/641
24// and then make the return types of some of these functions the enum instead of c_int
25const LE_LESS = c_int(-1);
26const LE_EQUAL = c_int(0);
27const LE_GREATER = c_int(1);
28const LE_UNORDERED = c_int(1);
29
30pub extern fn __lesf2(a: fp_t, b: fp_t) c_int {
31 @setRuntimeSafety(is_test);
32 const aInt: srep_t = @bitCast(srep_t, a);
33 const bInt: srep_t = @bitCast(srep_t, b);
34 const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
35 const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
36
37 // If either a or b is NaN, they are unordered.
38 if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED;
39
40 // If a and b are both zeros, they are equal.
41 if ((aAbs | bAbs) == 0) return LE_EQUAL;
42
43 // If at least one of a and b is positive, we get the same result comparing
44 // a and b as signed integers as we would with a fp_ting-point compare.
45 if ((aInt & bInt) >= 0) {
46 if (aInt < bInt) {
47 return LE_LESS;
48 } else if (aInt == bInt) {
49 return LE_EQUAL;
50 } else return LE_GREATER;
51 }
52
53 // Otherwise, both are negative, so we need to flip the sense of the
54 // comparison to get the correct result. (This assumes a twos- or ones-
55 // complement integer representation; if integers are represented in a
56 // sign-magnitude representation, then this flip is incorrect).
57 else {
58 if (aInt > bInt) {
59 return LE_LESS;
60 } else if (aInt == bInt) {
61 return LE_EQUAL;
62 } else return LE_GREATER;
63 }
64}
65
66// TODO https://github.com/ziglang/zig/issues/641
67// and then make the return types of some of these functions the enum instead of c_int
68const GE_LESS = c_int(-1);
69const GE_EQUAL = c_int(0);
70const GE_GREATER = c_int(1);
71const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED
72
73pub extern fn __gesf2(a: fp_t, b: fp_t) c_int {
74 @setRuntimeSafety(is_test);
75 const aInt: srep_t = @bitCast(srep_t, a);
76 const bInt: srep_t = @bitCast(srep_t, b);
77 const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
78 const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
79
80 if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
81 if ((aAbs | bAbs) == 0) return GE_EQUAL;
82 if ((aInt & bInt) >= 0) {
83 if (aInt < bInt) {
84 return GE_LESS;
85 } else if (aInt == bInt) {
86 return GE_EQUAL;
87 } else return GE_GREATER;
88 } else {
89 if (aInt > bInt) {
90 return GE_LESS;
91 } else if (aInt == bInt) {
92 return GE_EQUAL;
93 } else return GE_GREATER;
94 }
95}
96
97pub extern fn __unordsf2(a: fp_t, b: fp_t) c_int {
98 @setRuntimeSafety(is_test);
99 const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
100 const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
101 return @boolToInt(aAbs > infRep or bAbs > infRep);
102}
103
104pub extern fn __eqsf2(a: fp_t, b: fp_t) c_int {
105 return __lesf2(a, b);
106}
107
108pub extern fn __ltsf2(a: fp_t, b: fp_t) c_int {
109 return __lesf2(a, b);
110}
111
112pub extern fn __nesf2(a: fp_t, b: fp_t) c_int {
113 return __lesf2(a, b);
114}
115
116pub extern fn __gtsf2(a: fp_t, b: fp_t) c_int {
117 return __gesf2(a, b);
118}
119
120test "import comparesf2" {
121 _ = @import("comparesf2_test.zig");
122}
std/special/compiler_rt/comparesf2_test.zig created+101
...@@ -0,0 +1,101 @@
1// Ported from:
2//
3// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/comparesf2_test.c
4
5const std = @import("std");
6const builtin = @import("builtin");
7const is_test = builtin.is_test;
8
9const comparesf2 = @import("comparesf2.zig");
10
11const TestVector = struct {
12 a: f32,
13 b: f32,
14 eqReference: c_int,
15 geReference: c_int,
16 gtReference: c_int,
17 leReference: c_int,
18 ltReference: c_int,
19 neReference: c_int,
20 unReference: c_int,
21};
22
23fn test__cmpsf2(vector: TestVector) bool {
24 if (comparesf2.__eqsf2(vector.a, vector.b) != vector.eqReference) {
25 return false;
26 }
27 if (comparesf2.__gesf2(vector.a, vector.b) != vector.geReference) {
28 return false;
29 }
30 if (comparesf2.__gtsf2(vector.a, vector.b) != vector.gtReference) {
31 return false;
32 }
33 if (comparesf2.__lesf2(vector.a, vector.b) != vector.leReference) {
34 return false;
35 }
36 if (comparesf2.__ltsf2(vector.a, vector.b) != vector.ltReference) {
37 return false;
38 }
39 if (comparesf2.__nesf2(vector.a, vector.b) != vector.neReference) {
40 return false;
41 }
42 if (comparesf2.__unordsf2(vector.a, vector.b) != vector.unReference) {
43 return false;
44 }
45 return true;
46}
47
48const arguments = []f32{
49 std.math.nan(f32),
50 -std.math.inf(f32),
51 -0x1.fffffep127,
52 -0x1.000002p0 - 0x1.000000p0,
53 -0x1.fffffep-1,
54 -0x1.000000p-126,
55 -0x0.fffffep-126,
56 -0x0.000002p-126,
57 -0.0,
58 0.0,
59 0x0.000002p-126,
60 0x0.fffffep-126,
61 0x1.000000p-126,
62 0x1.fffffep-1,
63 0x1.000000p0,
64 0x1.000002p0,
65 0x1.fffffep127,
66 std.math.inf(f32),
67};
68
69fn generateVector(comptime a: f32, comptime b: f32) TestVector {
70 const leResult = if (a < b) -1 else if (a == b) 0 else 1;
71 const geResult = if (a > b) 1 else if (a == b) 0 else -1;
72 const unResult = if (a != a or b != b) 1 else 0;
73 return TestVector{
74 .a = a,
75 .b = b,
76 .eqReference = leResult,
77 .geReference = geResult,
78 .gtReference = geResult,
79 .leReference = leResult,
80 .ltReference = leResult,
81 .neReference = leResult,
82 .unReference = unResult,
83 };
84}
85
86const test_vectors = init: {
87 @setEvalBranchQuota(10000);
88 var vectors: [arguments.len * arguments.len]TestVector = undefined;
89 for (arguments[0..]) |arg_i, i| {
90 for (arguments[0..]) |arg_j, j| {
91 vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j);
92 }
93 }
94 break :init vectors;
95};
96
97test "compare f32" {
98 for (test_vectors) |vector, i| {
99 std.testing.expect(test__cmpsf2(vector));
100 }
101}
std/special/compiler_rt/divti3.zig+3-3
...@@ -16,9 +16,9 @@ pub extern fn __divti3(a: i128, b: i128) i128 {...@@ -16,9 +16,9 @@ pub extern fn __divti3(a: i128, b: i128) i128 {
16 return (@bitCast(i128, r) ^ s) -% s;16 return (@bitCast(i128, r) ^ s) -% s;
17}17}
1818
19pub extern fn __divti3_windows_x86_64(a: *const i128, b: *const i128) void {19const v128 = @Vector(2, u64);
20 @setRuntimeSafety(builtin.is_test);20pub extern fn __divti3_windows_x86_64(a: v128, b: v128) v128 {
21 compiler_rt.setXmm0(i128, __divti3(a.*, b.*));21 return @bitCast(v128, @inlineCall(__divti3, @bitCast(i128, a), @bitCast(i128, b)));
22}22}
2323
24test "import divti3" {24test "import divti3" {
std/special/compiler_rt/extendXfYf2.zig+10-4
...@@ -2,21 +2,27 @@ const std = @import("std");...@@ -2,21 +2,27 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const is_test = builtin.is_test;3const is_test = builtin.is_test;
44
5pub extern fn __extendsfdf2(a: f32) f64 {
6 return @inlineCall(extendXfYf2, f64, f32, @bitCast(u32, a));
7}
8
5pub extern fn __extenddftf2(a: f64) f128 {9pub extern fn __extenddftf2(a: f64) f128 {
6 return extendXfYf2(f128, f64, a);10 return @inlineCall(extendXfYf2, f128, f64, @bitCast(u64, a));
7}11}
812
9pub extern fn __extendsftf2(a: f32) f128 {13pub extern fn __extendsftf2(a: f32) f128 {
10 return extendXfYf2(f128, f32, a);14 return @inlineCall(extendXfYf2, f128, f32, @bitCast(u32, a));
11}15}
1216
13pub extern fn __extendhfsf2(a: u16) f32 {17pub extern fn __extendhfsf2(a: u16) f32 {
14 return extendXfYf2(f32, f16, @bitCast(f16, a));18 return @inlineCall(extendXfYf2, f32, f16, a);
15}19}
1620
17const CHAR_BIT = 8;21const CHAR_BIT = 8;
1822
19inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {23fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: @IntType(false, @typeInfo(src_t).Float.bits)) dst_t {
24 @setRuntimeSafety(builtin.is_test);
25
20 const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);26 const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);
21 const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits);27 const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits);
22 const srcSigBits = std.math.floatMantissaBits(src_t);28 const srcSigBits = std.math.floatMantissaBits(src_t);
std/special/compiler_rt/floatdidf.zig created+22
...@@ -0,0 +1,22 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const twop52: f64 = 0x1.0p52;
5const twop32: f64 = 0x1.0p32;
6
7pub extern fn __floatdidf(a: i64) f64 {
8 @setRuntimeSafety(builtin.is_test);
9
10 if (a == 0) return 0;
11
12 var low = @bitCast(i64, twop52);
13 const high = @intToFloat(f64, @truncate(i32, a >> 32)) * twop32;
14
15 low |= @bitCast(i64, a & 0xFFFFFFFF);
16
17 return (high - twop52) + @bitCast(f64, low);
18}
19
20test "import floatdidf" {
21 _ = @import("floatdidf_test.zig");
22}
std/special/compiler_rt/floatdidf_test.zig created+53
...@@ -0,0 +1,53 @@
1const __floatdidf = @import("floatdidf.zig").__floatdidf;
2const testing = @import("std").testing;
3
4fn test__floatdidf(a: i64, expected: f64) void {
5 const r = __floatdidf(a);
6 testing.expect(r == expected);
7}
8
9test "floatdidf" {
10 test__floatdidf(0, 0.0);
11 test__floatdidf(1, 1.0);
12 test__floatdidf(2, 2.0);
13 test__floatdidf(20, 20.0);
14 test__floatdidf(-1, -1.0);
15 test__floatdidf(-2, -2.0);
16 test__floatdidf(-20, -20.0);
17 test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
18 test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
19 test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
20 test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
21 test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);
22 test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000800)), -0x1.FFFFFFFFFFFFEp+62);
23 test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);
24 test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000001000)), -0x1.FFFFFFFFFFFFCp+62);
25 test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000000)), -0x1.000000p+63);
26 test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000001)), -0x1.000000p+63);
27 test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
28 test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
29 test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
30 test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
31 test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
32 test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
33 test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
34 test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
35 test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
36 test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
37 test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
38 test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
39 test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
40 test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
41 test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
42 test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
43 test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
44 test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
45 test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
46 test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
47 test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
48 test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
49 test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
50 test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
51 test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
52 test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
53}
std/special/compiler_rt/floatsiXf.zig created+109
...@@ -0,0 +1,109 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const maxInt = std.math.maxInt;
4
5fn floatsiXf(comptime T: type, a: i32) T {
6 @setRuntimeSafety(builtin.is_test);
7
8 const Z = @IntType(false, T.bit_count);
9 const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1));
10
11 if (a == 0) {
12 return T(0.0);
13 }
14
15 const significandBits = std.math.floatMantissaBits(T);
16 const exponentBits = std.math.floatExponentBits(T);
17 const exponentBias = ((1 << exponentBits - 1) - 1);
18
19 const implicitBit = Z(1) << significandBits;
20 const signBit = Z(1 << Z.bit_count - 1);
21
22 const sign = a >> 31;
23 // Take absolute value of a via abs(x) = (x^(x >> 31)) - (x >> 31).
24 const abs_a = (a ^ sign) -% sign;
25 // The exponent is the width of abs(a)
26 const exp = Z(31 - @clz(abs_a));
27
28 const sign_bit = if (sign < 0) signBit else 0;
29
30 var mantissa: Z = undefined;
31 // Shift a into the significand field and clear the implicit bit.
32 if (exp <= significandBits) {
33 // No rounding needed
34 const shift = @intCast(S, significandBits - exp);
35 mantissa = @intCast(Z, @bitCast(u32, abs_a)) << shift ^ implicitBit;
36 } else {
37 const shift = @intCast(S, exp - significandBits);
38 // Round to the nearest number after truncation
39 mantissa = @intCast(Z, @bitCast(u32, abs_a)) >> shift ^ implicitBit;
40 // Align to the left and check if the truncated part is halfway over
41 const round = @bitCast(u32, abs_a) << @intCast(u5, 31 - shift);
42 mantissa += @boolToInt(round > 0x80000000);
43 // Tie to even
44 mantissa += mantissa & 1;
45 }
46
47 // Use the addition instead of a or since we may have a carry from the
48 // mantissa to the exponent
49 var result = mantissa;
50 result += (exp + exponentBias) << significandBits;
51 result += sign_bit;
52
53 return @bitCast(T, result);
54}
55
56pub extern fn __floatsisf(arg: i32) f32 {
57 @setRuntimeSafety(builtin.is_test);
58 return @inlineCall(floatsiXf, f32, arg);
59}
60
61pub extern fn __floatsidf(arg: i32) f64 {
62 @setRuntimeSafety(builtin.is_test);
63 return @inlineCall(floatsiXf, f64, arg);
64}
65
66pub extern fn __floatsitf(arg: i32) f128 {
67 @setRuntimeSafety(builtin.is_test);
68 return @inlineCall(floatsiXf, f128, arg);
69}
70
71fn test_one_floatsitf(a: i32, expected: u128) void {
72 const r = __floatsitf(a);
73 std.testing.expect(@bitCast(u128, r) == expected);
74}
75
76fn test_one_floatsidf(a: i32, expected: u64) void {
77 const r = __floatsidf(a);
78 std.testing.expect(@bitCast(u64, r) == expected);
79}
80
81fn test_one_floatsisf(a: i32, expected: u32) void {
82 const r = __floatsisf(a);
83 std.testing.expect(@bitCast(u32, r) == expected);
84}
85
86test "floatsidf" {
87 test_one_floatsidf(0, 0x0000000000000000);
88 test_one_floatsidf(1, 0x3ff0000000000000);
89 test_one_floatsidf(-1, 0xbff0000000000000);
90 test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000);
91 test_one_floatsidf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc1e0000000000000);
92}
93
94test "floatsisf" {
95 test_one_floatsisf(0, 0x00000000);
96 test_one_floatsisf(1, 0x3f800000);
97 test_one_floatsisf(-1, 0xbf800000);
98 test_one_floatsisf(0x7FFFFFFF, 0x4f000000);
99 test_one_floatsisf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xcf000000);
100}
101
102test "floatsitf" {
103 test_one_floatsitf(0, 0);
104 test_one_floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000);
105 test_one_floatsitf(0x12345678, 0x401b2345678000000000000000000000);
106 test_one_floatsitf(-0x12345678, 0xc01b2345678000000000000000000000);
107 test_one_floatsitf(@bitCast(i32, @intCast(u32, 0xffffffff)), 0xbfff0000000000000000000000000000);
108 test_one_floatsitf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc01e0000000000000000000000000000);
109}
std/special/compiler_rt/floatundidf.zig created+24
...@@ -0,0 +1,24 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const twop52: f64 = 0x1.0p52;
5const twop84: f64 = 0x1.0p84;
6const twop84_plus_twop52: f64 = 0x1.00000001p84;
7
8pub extern fn __floatundidf(a: u64) f64 {
9 @setRuntimeSafety(builtin.is_test);
10
11 if (a == 0) return 0;
12
13 var high = @bitCast(u64, twop84);
14 var low = @bitCast(u64, twop52);
15
16 high |= a >> 32;
17 low |= a & 0xFFFFFFFF;
18
19 return (@bitCast(f64, high) - twop84_plus_twop52) + @bitCast(f64, low);
20}
21
22test "import floatundidf" {
23 _ = @import("floatundidf_test.zig");
24}
std/special/compiler_rt/floatundidf_test.zig created+50
...@@ -0,0 +1,50 @@
1const __floatundidf = @import("floatundidf.zig").__floatundidf;
2const testing = @import("std").testing;
3
4fn test__floatundidf(a: u64, expected: f64) void {
5 const r = __floatundidf(a);
6 testing.expect(r == expected);
7}
8
9test "floatundidf" {
10 test__floatundidf(0, 0.0);
11 test__floatundidf(1, 1.0);
12 test__floatundidf(2, 2.0);
13 test__floatundidf(20, 20.0);
14 test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
15 test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
16 test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
17 test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
18 test__floatundidf(0x8000008000000000, 0x1.000001p+63);
19 test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63);
20 test__floatundidf(0x8000010000000000, 0x1.000002p+63);
21 test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63);
22 test__floatundidf(0x8000000000000000, 0x1p+63);
23 test__floatundidf(0x8000000000000001, 0x1p+63);
24 test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
25 test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
26 test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
27 test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
28 test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
29 test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
30 test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
31 test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
32 test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
33 test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
34 test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
35 test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
36 test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
37 test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
38 test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
39 test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
40 test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
41 test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
42 test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
43 test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
44 test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
45 test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
46 test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
47 test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
48 test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
49 test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
50}
std/special/compiler_rt/floatunsidf.zig created+33
...@@ -0,0 +1,33 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const maxInt = std.math.maxInt;
4
5const implicitBit = u64(1) << 52;
6
7pub extern fn __floatunsidf(arg: u32) f64 {
8 @setRuntimeSafety(builtin.is_test);
9
10 if (arg == 0) return 0.0;
11
12 // The exponent is the width of abs(a)
13 const exp = u64(31) - @clz(arg);
14 // Shift a into the significand field and clear the implicit bit
15 const shift = @intCast(u6, 52 - exp);
16 const mant = u64(arg) << shift ^ implicitBit;
17
18 return @bitCast(f64, mant | (exp + 1023) << 52);
19}
20
21fn test_one_floatunsidf(a: u32, expected: u64) void {
22 const r = __floatunsidf(a);
23 std.testing.expect(@bitCast(u64, r) == expected);
24}
25
26test "floatsidf" {
27 // Test the produced bit pattern
28 test_one_floatunsidf(0, 0x0000000000000000);
29 test_one_floatunsidf(1, 0x3ff0000000000000);
30 test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000);
31 test_one_floatunsidf(@intCast(u32, 0x80000000), 0x41e0000000000000);
32 test_one_floatunsidf(@intCast(u32, 0xFFFFFFFF), 0x41efffffffe00000);
33}
std/special/compiler_rt/lshrti3.zig created+41
...@@ -0,0 +1,41 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3
4pub extern fn __lshrti3(a: i128, b: i32) i128 {
5 var input = twords{ .all = a };
6 var result: twords = undefined;
7
8 if (b > 63) {
9 // 64 <= b < 128
10 result.s.low = input.s.high >> @intCast(u6, b - 64);
11 result.s.high = 0;
12 } else {
13 // 0 <= b < 64
14 if (b == 0) return a;
15 result.s.low = input.s.high << @intCast(u6, 64 - b);
16 result.s.low |= input.s.low >> @intCast(u6, b);
17 result.s.high = input.s.high >> @intCast(u6, b);
18 }
19
20 return result.all;
21}
22
23const twords = extern union {
24 all: i128,
25 s: S,
26
27 const S = if (builtin.endian == builtin.Endian.Little)
28 struct {
29 low: u64,
30 high: u64,
31 }
32 else
33 struct {
34 high: u64,
35 low: u64,
36 };
37};
38
39test "import lshrti3" {
40 _ = @import("lshrti3_test.zig");
41}
std/special/compiler_rt/lshrti3_test.zig created+46
...@@ -0,0 +1,46 @@
1const __lshrti3 = @import("lshrti3.zig").__lshrti3;
2const testing = @import("std").testing;
3
4fn test__lshrti3(a: i128, b: i32, expected: i128) void {
5 const x = __lshrti3(a, b);
6 testing.expect(x == expected);
7}
8
9test "lshrti3" {
10 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 0, @bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)));
11 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 1, @bitCast(i128, @intCast(u128, 0x7F6E5D4C3B2A190AFF6E5D4C3B2A190A)));
12 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 2, @bitCast(i128, @intCast(u128, 0x3FB72EA61D950C857FB72EA61D950C85)));
13 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 3, @bitCast(i128, @intCast(u128, 0x1FDB97530ECA8642BFDB97530ECA8642)));
14 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 4, @bitCast(i128, @intCast(u128, 0x0FEDCBA9876543215FEDCBA987654321)));
15 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 28, @bitCast(i128, @intCast(u128, 0x0000000FEDCBA9876543215FEDCBA987)));
16 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 29, @bitCast(i128, @intCast(u128, 0x00000007F6E5D4C3B2A190AFF6E5D4C3)));
17 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 30, @bitCast(i128, @intCast(u128, 0x00000003FB72EA61D950C857FB72EA61)));
18 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 31, @bitCast(i128, @intCast(u128, 0x00000001FDB97530ECA8642BFDB97530)));
19 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 32, @bitCast(i128, @intCast(u128, 0x00000000FEDCBA9876543215FEDCBA98)));
20 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 33, @bitCast(i128, @intCast(u128, 0x000000007F6E5D4C3B2A190AFF6E5D4C)));
21 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 34, @bitCast(i128, @intCast(u128, 0x000000003FB72EA61D950C857FB72EA6)));
22 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 35, @bitCast(i128, @intCast(u128, 0x000000001FDB97530ECA8642BFDB9753)));
23 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 36, @bitCast(i128, @intCast(u128, 0x000000000FEDCBA9876543215FEDCBA9)));
24 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 60, @bitCast(i128, @intCast(u128, 0x000000000000000FEDCBA9876543215F)));
25 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 61, @bitCast(i128, @intCast(u128, 0x0000000000000007F6E5D4C3B2A190AF)));
26 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 62, @bitCast(i128, @intCast(u128, 0x0000000000000003FB72EA61D950C857)));
27 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 63, @bitCast(i128, @intCast(u128, 0x0000000000000001FDB97530ECA8642B)));
28 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 64, @bitCast(i128, @intCast(u128, 0x0000000000000000FEDCBA9876543215)));
29 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 65, @bitCast(i128, @intCast(u128, 0x00000000000000007F6E5D4C3B2A190A)));
30 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 66, @bitCast(i128, @intCast(u128, 0x00000000000000003FB72EA61D950C85)));
31 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 67, @bitCast(i128, @intCast(u128, 0x00000000000000001FDB97530ECA8642)));
32 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 68, @bitCast(i128, @intCast(u128, 0x00000000000000000FEDCBA987654321)));
33 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 92, @bitCast(i128, @intCast(u128, 0x00000000000000000000000FEDCBA987)));
34 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 93, @bitCast(i128, @intCast(u128, 0x000000000000000000000007F6E5D4C3)));
35 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 94, @bitCast(i128, @intCast(u128, 0x000000000000000000000003FB72EA61)));
36 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 95, @bitCast(i128, @intCast(u128, 0x000000000000000000000001FDB97530)));
37 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 96, @bitCast(i128, @intCast(u128, 0x000000000000000000000000FEDCBA98)));
38 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 97, @bitCast(i128, @intCast(u128, 0x0000000000000000000000007F6E5D4C)));
39 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 98, @bitCast(i128, @intCast(u128, 0x0000000000000000000000003FB72EA6)));
40 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 99, @bitCast(i128, @intCast(u128, 0x0000000000000000000000001FDB9753)));
41 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 100, @bitCast(i128, @intCast(u128, 0x0000000000000000000000000FEDCBA9)));
42 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 124, @bitCast(i128, @intCast(u128, 0x0000000000000000000000000000000F)));
43 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 125, @bitCast(i128, @intCast(u128, 0x00000000000000000000000000000007)));
44 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 126, @bitCast(i128, @intCast(u128, 0x00000000000000000000000000000003)));
45 test__lshrti3(@bitCast(i128, @intCast(u128, 0xFEDCBA9876543215FEDCBA9876543215)), 127, @bitCast(i128, @intCast(u128, 0x00000000000000000000000000000001)));
46}
std/special/compiler_rt/modti3.zig+3-3
...@@ -20,9 +20,9 @@ pub extern fn __modti3(a: i128, b: i128) i128 {...@@ -20,9 +20,9 @@ pub extern fn __modti3(a: i128, b: i128) i128 {
20 return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -120 return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -1
21}21}
2222
23pub extern fn __modti3_windows_x86_64(a: *const i128, b: *const i128) void {23const v128 = @Vector(2, u64);
24 @setRuntimeSafety(builtin.is_test);24pub extern fn __modti3_windows_x86_64(a: v128, b: v128) v128 {
25 compiler_rt.setXmm0(i128, __modti3(a.*, b.*));25 return @bitCast(v128, @inlineCall(__modti3, @bitCast(i128, a), @bitCast(i128, b)));
26}26}
2727
28test "import modti3" {28test "import modti3" {
std/special/compiler_rt/mulodi4.zig created+44
...@@ -0,0 +1,44 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const maxInt = std.math.maxInt;
4const minInt = std.math.minInt;
5
6pub extern fn __mulodi4(a: i64, b: i64, overflow: *c_int) i64 {
7 @setRuntimeSafety(builtin.is_test);
8
9 const min = @bitCast(i64, u64(1 << (i64.bit_count - 1)));
10 const max = ~min;
11
12 overflow.* = 0;
13 const result = a *% b;
14
15 // Edge cases
16 if (a == min) {
17 if (b != 0 and b != 1) overflow.* = 1;
18 return result;
19 }
20 if (b == min) {
21 if (a != 0 and a != 1) overflow.* = 1;
22 return result;
23 }
24
25 // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
26 const abs_a = (a ^ (a >> 63)) -% (a >> 63);
27 const abs_b = (b ^ (b >> 63)) -% (b >> 63);
28
29 // Unitary magnitude, cannot have overflow
30 if (abs_a < 2 or abs_b < 2) return result;
31
32 // Compare the signs of the operands
33 if ((a ^ b) >> 63 != 0) {
34 if (abs_a > @divTrunc(max, abs_b)) overflow.* = 1;
35 } else {
36 if (abs_a > @divTrunc(min, -abs_b)) overflow.* = 1;
37 }
38
39 return result;
40}
41
42test "import mulodi4" {
43 _ = @import("mulodi4_test.zig");
44}
std/special/compiler_rt/mulodi4_test.zig created+85
...@@ -0,0 +1,85 @@
1const __mulodi4 = @import("mulodi4.zig").__mulodi4;
2const testing = @import("std").testing;
3
4fn test__mulodi4(a: i64, b: i64, expected: i64, expected_overflow: c_int) void {
5 var overflow: c_int = undefined;
6 const x = __mulodi4(a, b, &overflow);
7 testing.expect(overflow == expected_overflow and (expected_overflow != 0 or x == expected));
8}
9
10test "mulodi4" {
11 test__mulodi4(0, 0, 0, 0);
12 test__mulodi4(0, 1, 0, 0);
13 test__mulodi4(1, 0, 0, 0);
14 test__mulodi4(0, 10, 0, 0);
15 test__mulodi4(10, 0, 0, 0);
16 test__mulodi4(0, 81985529216486895, 0, 0);
17 test__mulodi4(81985529216486895, 0, 0, 0);
18
19 test__mulodi4(0, -1, 0, 0);
20 test__mulodi4(-1, 0, 0, 0);
21 test__mulodi4(0, -10, 0, 0);
22 test__mulodi4(-10, 0, 0, 0);
23 test__mulodi4(0, -81985529216486895, 0, 0);
24 test__mulodi4(-81985529216486895, 0, 0, 0);
25
26 test__mulodi4(1, 1, 1, 0);
27 test__mulodi4(1, 10, 10, 0);
28 test__mulodi4(10, 1, 10, 0);
29 test__mulodi4(1, 81985529216486895, 81985529216486895, 0);
30 test__mulodi4(81985529216486895, 1, 81985529216486895, 0);
31
32 test__mulodi4(1, -1, -1, 0);
33 test__mulodi4(1, -10, -10, 0);
34 test__mulodi4(-10, 1, -10, 0);
35 test__mulodi4(1, -81985529216486895, -81985529216486895, 0);
36 test__mulodi4(-81985529216486895, 1, -81985529216486895, 0);
37
38 test__mulodi4(3037000499, 3037000499, 9223372030926249001, 0);
39 test__mulodi4(-3037000499, 3037000499, -9223372030926249001, 0);
40 test__mulodi4(3037000499, -3037000499, -9223372030926249001, 0);
41 test__mulodi4(-3037000499, -3037000499, 9223372030926249001, 0);
42
43 test__mulodi4(4398046511103, 2097152, 9223372036852678656, 0);
44 test__mulodi4(-4398046511103, 2097152, -9223372036852678656, 0);
45 test__mulodi4(4398046511103, -2097152, -9223372036852678656, 0);
46 test__mulodi4(-4398046511103, -2097152, 9223372036852678656, 0);
47
48 test__mulodi4(2097152, 4398046511103, 9223372036852678656, 0);
49 test__mulodi4(-2097152, 4398046511103, -9223372036852678656, 0);
50 test__mulodi4(2097152, -4398046511103, -9223372036852678656, 0);
51 test__mulodi4(-2097152, -4398046511103, 9223372036852678656, 0);
52
53 test__mulodi4(0x7FFFFFFFFFFFFFFF, -2, 2, 1);
54 test__mulodi4(-2, 0x7FFFFFFFFFFFFFFF, 2, 1);
55 test__mulodi4(0x7FFFFFFFFFFFFFFF, -1, @bitCast(i64, u64(0x8000000000000001)), 0);
56 test__mulodi4(-1, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, u64(0x8000000000000001)), 0);
57 test__mulodi4(0x7FFFFFFFFFFFFFFF, 0, 0, 0);
58 test__mulodi4(0, 0x7FFFFFFFFFFFFFFF, 0, 0);
59 test__mulodi4(0x7FFFFFFFFFFFFFFF, 1, 0x7FFFFFFFFFFFFFFF, 0);
60 test__mulodi4(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF, 0);
61 test__mulodi4(0x7FFFFFFFFFFFFFFF, 2, @bitCast(i64, u64(0x8000000000000001)), 1);
62 test__mulodi4(2, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, u64(0x8000000000000001)), 1);
63
64 test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), -2, @bitCast(i64, u64(0x8000000000000000)), 1);
65 test__mulodi4(-2, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 1);
66 test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), -1, @bitCast(i64, u64(0x8000000000000000)), 1);
67 test__mulodi4(-1, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 1);
68 test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), 0, 0, 0);
69 test__mulodi4(0, @bitCast(i64, u64(0x8000000000000000)), 0, 0);
70 test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), 1, @bitCast(i64, u64(0x8000000000000000)), 0);
71 test__mulodi4(1, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 0);
72 test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), 2, @bitCast(i64, u64(0x8000000000000000)), 1);
73 test__mulodi4(2, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 1);
74
75 test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), -2, @bitCast(i64, u64(0x8000000000000001)), 1);
76 test__mulodi4(-2, @bitCast(i64, u64(0x8000000000000001)), @bitCast(i64, u64(0x8000000000000001)), 1);
77 test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), -1, 0x7FFFFFFFFFFFFFFF, 0);
78 test__mulodi4(-1, @bitCast(i64, u64(0x8000000000000001)), 0x7FFFFFFFFFFFFFFF, 0);
79 test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), 0, 0, 0);
80 test__mulodi4(0, @bitCast(i64, u64(0x8000000000000001)), 0, 0);
81 test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), 1, @bitCast(i64, u64(0x8000000000000001)), 0);
82 test__mulodi4(1, @bitCast(i64, u64(0x8000000000000001)), @bitCast(i64, u64(0x8000000000000001)), 0);
83 test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), 2, @bitCast(i64, u64(0x8000000000000000)), 1);
84 test__mulodi4(2, @bitCast(i64, u64(0x8000000000000001)), @bitCast(i64, u64(0x8000000000000000)), 1);
85}
std/special/compiler_rt/muloti4.zig+2-8
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1const udivmod = @import("udivmod.zig").udivmod;
2const builtin = @import("builtin");1const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");2const compiler_rt = @import("../compiler_rt.zig");
43
...@@ -33,11 +32,11 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {...@@ -33,11 +32,11 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {
33 }32 }
3433
35 if (sa == sb) {34 if (sa == sb) {
36 if (abs_a > @divFloor(max, abs_b)) {35 if (abs_a > @divTrunc(max, abs_b)) {
37 overflow.* = 1;36 overflow.* = 1;
38 }37 }
39 } else {38 } else {
40 if (abs_a > @divFloor(min, -abs_b)) {39 if (abs_a > @divTrunc(min, -abs_b)) {
41 overflow.* = 1;40 overflow.* = 1;
42 }41 }
43 }42 }
...@@ -45,11 +44,6 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {...@@ -45,11 +44,6 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {
45 return r;44 return r;
46}45}
4746
48pub extern fn __muloti4_windows_x86_64(a: *const i128, b: *const i128, overflow: *c_int) void {
49 @setRuntimeSafety(builtin.is_test);
50 compiler_rt.setXmm0(i128, __muloti4(a.*, b.*, overflow));
51}
52
53test "import muloti4" {47test "import muloti4" {
54 _ = @import("muloti4_test.zig");48 _ = @import("muloti4_test.zig");
55}49}
std/special/compiler_rt/multi3.zig+3-3
...@@ -14,9 +14,9 @@ pub extern fn __multi3(a: i128, b: i128) i128 {...@@ -14,9 +14,9 @@ pub extern fn __multi3(a: i128, b: i128) i128 {
14 return r.all;14 return r.all;
15}15}
1616
17pub extern fn __multi3_windows_x86_64(a: *const i128, b: *const i128) void {17const v128 = @Vector(2, u64);
18 @setRuntimeSafety(builtin.is_test);18pub extern fn __multi3_windows_x86_64(a: v128, b: v128) v128 {
19 compiler_rt.setXmm0(i128, __multi3(a.*, b.*));19 return @bitCast(v128, @inlineCall(__multi3, @bitCast(i128, a), @bitCast(i128, b)));
20}20}
2121
22fn __mulddi3(a: u64, b: u64) i128 {22fn __mulddi3(a: u64, b: u64) i128 {
std/special/compiler_rt/stack_probe.zig created+206
...@@ -0,0 +1,206 @@
1const builtin = @import("builtin");
2
3// Zig's own stack-probe routine (available only on x86 and x86_64)
4pub nakedcc fn zig_probe_stack() void {
5 @setRuntimeSafety(false);
6
7 // Versions of the Linux kernel before 5.1 treat any access below SP as
8 // invalid so let's update it on the go, otherwise we'll get a segfault
9 // instead of triggering the stack growth.
10
11 switch (builtin.arch) {
12 .x86_64 => {
13 // %rax = probe length, %rsp = stack pointer
14 asm volatile (
15 \\ push %%rcx
16 \\ mov %%rax, %%rcx
17 \\ cmp $0x1000,%%rcx
18 \\ jb 2f
19 \\ 1:
20 \\ sub $0x1000,%%rsp
21 \\ orl $0,16(%%rsp)
22 \\ sub $0x1000,%%rcx
23 \\ cmp $0x1000,%%rcx
24 \\ ja 1b
25 \\ 2:
26 \\ sub %%rcx, %%rsp
27 \\ orl $0,16(%%rsp)
28 \\ add %%rax,%%rsp
29 \\ pop %%rcx
30 \\ ret
31 );
32 },
33 .i386 => {
34 // %eax = probe length, %esp = stack pointer
35 asm volatile (
36 \\ push %%ecx
37 \\ mov %%eax, %%ecx
38 \\ cmp $0x1000,%%ecx
39 \\ jb 2f
40 \\ 1:
41 \\ sub $0x1000,%%esp
42 \\ orl $0,8(%%esp)
43 \\ sub $0x1000,%%ecx
44 \\ cmp $0x1000,%%ecx
45 \\ ja 1b
46 \\ 2:
47 \\ sub %%ecx, %%esp
48 \\ orl $0,8(%%esp)
49 \\ add %%eax,%%esp
50 \\ pop %%ecx
51 \\ ret
52 );
53 },
54 else => { }
55 }
56
57 unreachable;
58}
59
60fn win_probe_stack_only() void {
61 @setRuntimeSafety(false);
62
63 switch (builtin.arch) {
64 .x86_64 => {
65 asm volatile (
66 \\ push %%rcx
67 \\ push %%rax
68 \\ cmp $0x1000,%%rax
69 \\ lea 24(%%rsp),%%rcx
70 \\ jb 1f
71 \\ 2:
72 \\ sub $0x1000,%%rcx
73 \\ test %%rcx,(%%rcx)
74 \\ sub $0x1000,%%rax
75 \\ cmp $0x1000,%%rax
76 \\ ja 2b
77 \\ 1:
78 \\ sub %%rax,%%rcx
79 \\ test %%rcx,(%%rcx)
80 \\ pop %%rax
81 \\ pop %%rcx
82 \\ ret
83 );
84 },
85 .i386 => {
86 asm volatile (
87 \\ push %%ecx
88 \\ push %%eax
89 \\ cmp $0x1000,%%eax
90 \\ lea 12(%%esp),%%ecx
91 \\ jb 1f
92 \\ 2:
93 \\ sub $0x1000,%%ecx
94 \\ test %%ecx,(%%ecx)
95 \\ sub $0x1000,%%eax
96 \\ cmp $0x1000,%%eax
97 \\ ja 2b
98 \\ 1:
99 \\ sub %%eax,%%ecx
100 \\ test %%ecx,(%%ecx)
101 \\ pop %%eax
102 \\ pop %%ecx
103 \\ ret
104 );
105 },
106 else => { }
107 }
108
109 unreachable;
110}
111
112fn win_probe_stack_adjust_sp() void {
113 @setRuntimeSafety(false);
114
115 switch (builtin.arch) {
116 .x86_64 => {
117 asm volatile (
118 \\ push %%rcx
119 \\ cmp $0x1000,%%rax
120 \\ lea 16(%%rsp),%%rcx
121 \\ jb 1f
122 \\ 2:
123 \\ sub $0x1000,%%rcx
124 \\ test %%rcx,(%%rcx)
125 \\ sub $0x1000,%%rax
126 \\ cmp $0x1000,%%rax
127 \\ ja 2b
128 \\ 1:
129 \\ sub %%rax,%%rcx
130 \\ test %%rcx,(%%rcx)
131 \\
132 \\ lea 8(%%rsp),%%rax
133 \\ mov %%rcx,%%rsp
134 \\ mov -8(%%rax),%%rcx
135 \\ push (%%rax)
136 \\ sub %%rsp,%%rax
137 \\ ret
138 );
139 },
140 .i386 => {
141 asm volatile (
142 \\ push %%ecx
143 \\ cmp $0x1000,%%eax
144 \\ lea 8(%%esp),%%ecx
145 \\ jb 1f
146 \\ 2:
147 \\ sub $0x1000,%%ecx
148 \\ test %%ecx,(%%ecx)
149 \\ sub $0x1000,%%eax
150 \\ cmp $0x1000,%%eax
151 \\ ja 2b
152 \\ 1:
153 \\ sub %%eax,%%ecx
154 \\ test %%ecx,(%%ecx)
155 \\
156 \\ lea 4(%%esp),%%eax
157 \\ mov %%ecx,%%esp
158 \\ mov -4(%%eax),%%ecx
159 \\ push (%%eax)
160 \\ sub %%esp,%%eax
161 \\ ret
162 );
163 },
164 else => { },
165 }
166
167 unreachable;
168}
169
170// Windows has a multitude of stack-probing functions with similar names and
171// slightly different behaviours: some behave as alloca() and update the stack
172// pointer after probing the stack, other do not.
173//
174// Function name | Adjusts the SP? |
175// | x86 | x86_64 |
176// ----------------------------------------
177// _chkstk (_alloca) | yes | yes |
178// __chkstk | yes | no |
179// __chkstk_ms | no | no |
180// ___chkstk (__alloca) | yes | yes |
181// ___chkstk_ms | no | no |
182
183pub nakedcc fn _chkstk() void {
184 @setRuntimeSafety(false);
185 @inlineCall(win_probe_stack_adjust_sp);
186}
187pub nakedcc fn __chkstk() void {
188 @setRuntimeSafety(false);
189 switch (builtin.arch) {
190 .i386 => @inlineCall(win_probe_stack_adjust_sp),
191 .x86_64 => @inlineCall(win_probe_stack_only),
192 else => unreachable
193 }
194}
195pub nakedcc fn ___chkstk() void {
196 @setRuntimeSafety(false);
197 @inlineCall(win_probe_stack_adjust_sp);
198}
199pub nakedcc fn __chkstk_ms() void {
200 @setRuntimeSafety(false);
201 @inlineCall(win_probe_stack_only);
202}
203pub nakedcc fn ___chkstk_ms() void {
204 @setRuntimeSafety(false);
205 @inlineCall(win_probe_stack_only);
206}
std/special/compiler_rt/truncXfYf2.zig+4
...@@ -16,6 +16,10 @@ pub extern fn __trunctfdf2(a: f128) f64 {...@@ -16,6 +16,10 @@ pub extern fn __trunctfdf2(a: f128) f64 {
16 return truncXfYf2(f64, f128, a);16 return truncXfYf2(f64, f128, a);
17}17}
1818
19pub extern fn __truncdfsf2(a: f64) f32 {
20 return truncXfYf2(f32, f64, a);
21}
22
19inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {23inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
20 const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);24 const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);
21 const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits);25 const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits);
std/special/compiler_rt/truncXfYf2_test.zig+37
...@@ -200,3 +200,40 @@ test "trunctfdf2" {...@@ -200,3 +200,40 @@ test "trunctfdf2" {
200 test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);200 test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);
201 test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);201 test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);
202}202}
203
204const __truncdfsf2 = @import("truncXfYf2.zig").__truncdfsf2;
205
206fn test__truncdfsf2(a: f64, expected: u32) void {
207 const x = __truncdfsf2(a);
208
209 const rep = @bitCast(u32, x);
210 if (rep == expected) {
211 return;
212 }
213 // test other possible NaN representation(signal NaN)
214 else if (expected == 0x7fc00000) {
215 if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) {
216 return;
217 }
218 }
219
220 @import("std").debug.warn("got 0x{x} wanted 0x{x}\n", rep, expected);
221
222 @panic("__trunctfsf2 test failure");
223}
224
225test "truncdfsf2" {
226 // nan & qnan
227 test__truncdfsf2(@bitCast(f64, u64(0x7ff8000000000000)), 0x7fc00000);
228 test__truncdfsf2(@bitCast(f64, u64(0x7ff0000000000001)), 0x7fc00000);
229 // inf
230 test__truncdfsf2(@bitCast(f64, u64(0x7ff0000000000000)), 0x7f800000);
231 test__truncdfsf2(@bitCast(f64, u64(0xfff0000000000000)), 0xff800000);
232
233 test__truncdfsf2(0.0, 0x0);
234 test__truncdfsf2(1.0, 0x3f800000);
235 test__truncdfsf2(-1.0, 0xbf800000);
236
237 // huge number becomes inf
238 test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);
239}
std/special/compiler_rt/udivmodti4.zig+3-2
...@@ -7,9 +7,10 @@ pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) u128 {...@@ -7,9 +7,10 @@ pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) u128 {
7 return udivmod(u128, a, b, maybe_rem);7 return udivmod(u128, a, b, maybe_rem);
8}8}
99
10pub extern fn __udivmodti4_windows_x86_64(a: *const u128, b: *const u128, maybe_rem: ?*u128) void {10const v128 = @Vector(2, u64);
11pub extern fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) v128 {
11 @setRuntimeSafety(builtin.is_test);12 @setRuntimeSafety(builtin.is_test);
12 compiler_rt.setXmm0(u128, udivmod(u128, a.*, b.*, maybe_rem));13 return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), maybe_rem));
13}14}
1415
15test "import udivmodti4" {16test "import udivmodti4" {
std/special/compiler_rt/udivti3.zig+3-2
...@@ -6,7 +6,8 @@ pub extern fn __udivti3(a: u128, b: u128) u128 {...@@ -6,7 +6,8 @@ pub extern fn __udivti3(a: u128, b: u128) u128 {
6 return udivmodti4.__udivmodti4(a, b, null);6 return udivmodti4.__udivmodti4(a, b, null);
7}7}
88
9pub extern fn __udivti3_windows_x86_64(a: *const u128, b: *const u128) void {9const v128 = @Vector(2, u64);
10pub extern fn __udivti3_windows_x86_64(a: v128, b: v128) v128 {
10 @setRuntimeSafety(builtin.is_test);11 @setRuntimeSafety(builtin.is_test);
11 udivmodti4.__udivmodti4_windows_x86_64(a, b, null);12 return udivmodti4.__udivmodti4_windows_x86_64(a, b, null);
12}13}
std/special/compiler_rt/umodti3.zig+3-3
...@@ -9,7 +9,7 @@ pub extern fn __umodti3(a: u128, b: u128) u128 {...@@ -9,7 +9,7 @@ pub extern fn __umodti3(a: u128, b: u128) u128 {
9 return r;9 return r;
10}10}
1111
12pub extern fn __umodti3_windows_x86_64(a: *const u128, b: *const u128) void {12const v128 = @Vector(2, u64);
13 @setRuntimeSafety(builtin.is_test);13pub extern fn __umodti3_windows_x86_64(a: v128, b: v128) v128 {
14 compiler_rt.setXmm0(u128, __umodti3(a.*, b.*));14 return @bitCast(v128, @inlineCall(__umodti3, @bitCast(u128, a), @bitCast(u128, b)));
15}15}
std/special/fmt_runner.zig deleted-260
...@@ -1,260 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4const os = std.os;
5const io = std.io;
6const mem = std.mem;
7const Allocator = mem.Allocator;
8const ArrayList = std.ArrayList;
9const Buffer = std.Buffer;
10const ast = std.zig.ast;
11
12const arg = @import("fmt/arg.zig");
13const self_hosted_main = @import("fmt/main.zig");
14const Args = arg.Args;
15const Flag = arg.Flag;
16const errmsg = @import("fmt/errmsg.zig");
17
18var stderr_file: os.File = undefined;
19var stderr: *io.OutStream(os.File.WriteError) = undefined;
20var stdout: *io.OutStream(os.File.WriteError) = undefined;
21
22// This brings `zig fmt` to stage 1.
23pub fn main() !void {
24 // Here we use an ArenaAllocator backed by a DirectAllocator because `zig fmt` is a short-lived,
25 // one shot program. We don't need to waste time freeing memory and finding places to squish
26 // bytes into. So we free everything all at once at the very end.
27 var direct_allocator = std.heap.DirectAllocator.init();
28 var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
29 const allocator = &arena.allocator;
30
31 var stdout_file = try std.io.getStdOut();
32 var stdout_out_stream = stdout_file.outStream();
33 stdout = &stdout_out_stream.stream;
34
35 stderr_file = try std.io.getStdErr();
36 var stderr_out_stream = stderr_file.outStream();
37 stderr = &stderr_out_stream.stream;
38 const args = try std.os.argsAlloc(allocator);
39
40 var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args[1..]);
41 defer flags.deinit();
42
43 if (flags.present("help")) {
44 try stdout.write(self_hosted_main.usage_fmt);
45 os.exit(0);
46 }
47
48 const color = blk: {
49 if (flags.single("color")) |color_flag| {
50 if (mem.eql(u8, color_flag, "auto")) {
51 break :blk errmsg.Color.Auto;
52 } else if (mem.eql(u8, color_flag, "on")) {
53 break :blk errmsg.Color.On;
54 } else if (mem.eql(u8, color_flag, "off")) {
55 break :blk errmsg.Color.Off;
56 } else unreachable;
57 } else {
58 break :blk errmsg.Color.Auto;
59 }
60 };
61
62 if (flags.present("stdin")) {
63 if (flags.positionals.len != 0) {
64 try stderr.write("cannot use --stdin with positional arguments\n");
65 os.exit(1);
66 }
67
68 var stdin_file = try io.getStdIn();
69 var stdin = stdin_file.inStream();
70
71 const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
72 defer allocator.free(source_code);
73
74 var tree = std.zig.parse(allocator, source_code) catch |err| {
75 try stderr.print("error parsing stdin: {}\n", err);
76 os.exit(1);
77 };
78 defer tree.deinit();
79
80 var error_it = tree.errors.iterator(0);
81 while (error_it.next()) |parse_error| {
82 try printErrMsgToFile(allocator, parse_error, &tree, "<stdin>", stderr_file, color);
83 }
84 if (tree.errors.len != 0) {
85 os.exit(1);
86 }
87 if (flags.present("check")) {
88 const anything_changed = try std.zig.render(allocator, io.null_out_stream, &tree);
89 const code = if (anything_changed) u8(1) else u8(0);
90 os.exit(code);
91 }
92
93 _ = try std.zig.render(allocator, stdout, &tree);
94 return;
95 }
96
97 if (flags.positionals.len == 0) {
98 try stderr.write("expected at least one source file argument\n");
99 os.exit(1);
100 }
101
102 var fmt = Fmt{
103 .seen = Fmt.SeenMap.init(allocator),
104 .any_error = false,
105 .color = color,
106 .allocator = allocator,
107 };
108
109 const check_mode = flags.present("check");
110
111 for (flags.positionals.toSliceConst()) |file_path| {
112 try fmtPath(&fmt, file_path, check_mode);
113 }
114 if (fmt.any_error) {
115 os.exit(1);
116 }
117}
118
119const FmtError = error{
120 SystemResources,
121 OperationAborted,
122 IoPending,
123 BrokenPipe,
124 Unexpected,
125 WouldBlock,
126 FileClosed,
127 DestinationAddressRequired,
128 DiskQuota,
129 FileTooBig,
130 InputOutput,
131 NoSpaceLeft,
132 AccessDenied,
133 OutOfMemory,
134 RenameAcrossMountPoints,
135 ReadOnlyFileSystem,
136 LinkQuotaExceeded,
137 FileBusy,
138} || os.File.OpenError;
139
140fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
141 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
142 defer fmt.allocator.free(file_path);
143
144 if (try fmt.seen.put(file_path, {})) |_| return;
145
146 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
147 error.IsDir, error.AccessDenied => {
148 // TODO make event based (and dir.next())
149 var dir = try std.os.Dir.open(fmt.allocator, file_path);
150 defer dir.close();
151
152 while (try dir.next()) |entry| {
153 if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
154 const full_path = try os.path.join(fmt.allocator, [][]const u8{ file_path, entry.name });
155 try fmtPath(fmt, full_path, check_mode);
156 }
157 }
158 return;
159 },
160 else => {
161 // TODO lock stderr printing
162 try stderr.print("unable to open '{}': {}\n", file_path, err);
163 fmt.any_error = true;
164 return;
165 },
166 };
167 defer fmt.allocator.free(source_code);
168
169 var tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
170 try stderr.print("error parsing file '{}': {}\n", file_path, err);
171 fmt.any_error = true;
172 return;
173 };
174 defer tree.deinit();
175
176 var error_it = tree.errors.iterator(0);
177 while (error_it.next()) |parse_error| {
178 try printErrMsgToFile(fmt.allocator, parse_error, &tree, file_path, stderr_file, fmt.color);
179 }
180 if (tree.errors.len != 0) {
181 fmt.any_error = true;
182 return;
183 }
184
185 if (check_mode) {
186 const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, &tree);
187 if (anything_changed) {
188 try stderr.print("{}\n", file_path);
189 fmt.any_error = true;
190 }
191 } else {
192 // TODO make this evented
193 const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
194 defer baf.destroy();
195
196 const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), &tree);
197 if (anything_changed) {
198 try stderr.print("{}\n", file_path);
199 try baf.finish();
200 }
201 }
202}
203
204const Fmt = struct {
205 seen: SeenMap,
206 any_error: bool,
207 color: errmsg.Color,
208 allocator: *mem.Allocator,
209
210 const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
211};
212
213fn printErrMsgToFile(allocator: *mem.Allocator, parse_error: *const ast.Error, tree: *ast.Tree,
214 path: []const u8, file: os.File, color: errmsg.Color,) !void
215{
216 const color_on = switch (color) {
217 errmsg.Color.Auto => file.isTty(),
218 errmsg.Color.On => true,
219 errmsg.Color.Off => false,
220 };
221 const lok_token = parse_error.loc();
222 const span = errmsg.Span{
223 .first = lok_token,
224 .last = lok_token,
225 };
226
227 const first_token = tree.tokens.at(span.first);
228 const last_token = tree.tokens.at(span.last);
229 const start_loc = tree.tokenLocationPtr(0, first_token);
230 const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
231
232 var text_buf = try std.Buffer.initSize(allocator, 0);
233 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
234 try parse_error.render(&tree.tokens, out_stream);
235 const text = text_buf.toOwnedSlice();
236
237 const stream = &file.outStream().stream;
238 if (!color_on) {
239 try stream.print(
240 "{}:{}:{}: error: {}\n",
241 path,
242 start_loc.line + 1,
243 start_loc.column + 1,
244 text,
245 );
246 return;
247 }
248
249 try stream.print(
250 "{}:{}:{}: error: {}\n{}\n",
251 path,
252 start_loc.line + 1,
253 start_loc.column + 1,
254 text,
255 tree.source[start_loc.line_start..start_loc.line_end],
256 );
257 try stream.writeByteNTimes(' ', start_loc.column);
258 try stream.writeByteNTimes('~', last_token.end - first_token.start);
259 try stream.write("\n");
260}
std/special/panic.zig+6-1
...@@ -9,10 +9,15 @@ const std = @import("std");...@@ -9,10 +9,15 @@ const std = @import("std");
9pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {9pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
10 @setCold(true);10 @setCold(true);
11 switch (builtin.os) {11 switch (builtin.os) {
12 // TODO: fix panic in zen.12 // TODO: fix panic in zen
13 builtin.Os.freestanding, builtin.Os.zen => {13 builtin.Os.freestanding, builtin.Os.zen => {
14 while (true) {}14 while (true) {}
15 },15 },
16 builtin.Os.wasi => {
17 std.debug.warn("{}", msg);
18 _ = std.os.wasi.proc_raise(std.os.wasi.SIGABRT);
19 unreachable;
20 },
16 builtin.Os.uefi => {21 builtin.Os.uefi => {
17 // TODO look into using the debug info and logging helpful messages22 // TODO look into using the debug info and logging helpful messages
18 std.os.abort();23 std.os.abort();
std/special/test_runner.zig+1-1
...@@ -8,7 +8,7 @@ pub fn main() !void {...@@ -8,7 +8,7 @@ pub fn main() !void {
8 var ok_count: usize = 0;8 var ok_count: usize = 0;
9 var skip_count: usize = 0;9 var skip_count: usize = 0;
10 for (test_fn_list) |test_fn, i| {10 for (test_fn_list) |test_fn, i| {
11 warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name);11 warn("{}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
1212
13 if (test_fn.func()) |_| {13 if (test_fn.func()) |_| {
14 ok_count += 1;14 ok_count += 1;
std/std.zig+7
...@@ -9,6 +9,10 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;...@@ -9,6 +9,10 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
9pub const HashMap = @import("hash_map.zig").HashMap;9pub const HashMap = @import("hash_map.zig").HashMap;
10pub const LinkedList = @import("linked_list.zig").LinkedList;10pub const LinkedList = @import("linked_list.zig").LinkedList;
11pub const Mutex = @import("mutex.zig").Mutex;11pub const Mutex = @import("mutex.zig").Mutex;
12pub const PackedIntArrayEndian = @import("packed_int_array.zig").PackedIntArrayEndian;
13pub const PackedIntArray = @import("packed_int_array.zig").PackedIntArray;
14pub const PackedIntSliceEndian = @import("packed_int_array.zig").PackedIntSliceEndian;
15pub const PackedIntSlice = @import("packed_int_array.zig").PackedIntSlice;
12pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue;16pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue;
13pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;17pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
14pub const SegmentedList = @import("segmented_list.zig").SegmentedList;18pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
...@@ -87,6 +91,7 @@ test "std" {...@@ -87,6 +91,7 @@ test "std" {
87 _ = @import("net.zig");91 _ = @import("net.zig");
88 _ = @import("os.zig");92 _ = @import("os.zig");
89 _ = @import("pdb.zig");93 _ = @import("pdb.zig");
94 _ = @import("packed_int_array.zig");
90 _ = @import("priority_queue.zig");95 _ = @import("priority_queue.zig");
91 _ = @import("rand.zig");96 _ = @import("rand.zig");
92 _ = @import("sort.zig");97 _ = @import("sort.zig");
...@@ -94,4 +99,6 @@ test "std" {...@@ -94,4 +99,6 @@ test "std" {
94 _ = @import("unicode.zig");99 _ = @import("unicode.zig");
95 _ = @import("valgrind.zig");100 _ = @import("valgrind.zig");
96 _ = @import("zig.zig");101 _ = @import("zig.zig");
102
103 _ = @import("debug/leb128.zig");
97}104}
std/zig/ast.zig+5-4
...@@ -18,7 +18,11 @@ pub const Tree = struct {...@@ -18,7 +18,11 @@ pub const Tree = struct {
18 pub const ErrorList = SegmentedList(Error, 0);18 pub const ErrorList = SegmentedList(Error, 0);
1919
20 pub fn deinit(self: *Tree) void {20 pub fn deinit(self: *Tree) void {
21 self.arena_allocator.deinit();21 // Here we copy the arena allocator into stack memory, because
22 // otherwise it would destroy itself while it was still working.
23 var arena_allocator = self.arena_allocator;
24 arena_allocator.deinit();
25 // self is destroyed
22 }26 }
2327
24 pub fn renderError(self: *Tree, parse_error: *Error, stream: var) !void {28 pub fn renderError(self: *Tree, parse_error: *Error, stream: var) !void {
...@@ -551,7 +555,6 @@ pub const Node = struct {...@@ -551,7 +555,6 @@ pub const Node = struct {
551 doc_comments: ?*DocComment,555 doc_comments: ?*DocComment,
552 decls: DeclList,556 decls: DeclList,
553 eof_token: TokenIndex,557 eof_token: TokenIndex,
554 shebang: ?TokenIndex,
555558
556 pub const DeclList = SegmentedList(*Node, 4);559 pub const DeclList = SegmentedList(*Node, 4);
557560
...@@ -563,7 +566,6 @@ pub const Node = struct {...@@ -563,7 +566,6 @@ pub const Node = struct {
563 }566 }
564567
565 pub fn firstToken(self: *const Root) TokenIndex {568 pub fn firstToken(self: *const Root) TokenIndex {
566 if (self.shebang) |shebang| return shebang;
567 return if (self.decls.len == 0) self.eof_token else (self.decls.at(0).*).firstToken();569 return if (self.decls.len == 0) self.eof_token else (self.decls.at(0).*).firstToken();
568 }570 }
569571
...@@ -2307,7 +2309,6 @@ test "iterate" {...@@ -2307,7 +2309,6 @@ test "iterate" {
2307 .doc_comments = null,2309 .doc_comments = null,
2308 .decls = Node.Root.DeclList.init(std.debug.global_allocator),2310 .decls = Node.Root.DeclList.init(std.debug.global_allocator),
2309 .eof_token = 0,2311 .eof_token = 0,
2310 .shebang = null,
2311 };2312 };
2312 var base = &root.base;2313 var base = &root.base;
2313 testing.expect(base.iterate(0) == null);2314 testing.expect(base.iterate(0) == null);
std/zig/parse.zig+179-159
...@@ -9,7 +9,7 @@ const Error = ast.Error;...@@ -9,7 +9,7 @@ const Error = ast.Error;
99
10/// Result should be freed with tree.deinit() when there are10/// Result should be freed with tree.deinit() when there are
11/// no more references to any of the tokens or nodes.11/// no more references to any of the tokens or nodes.
12pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {12pub fn parse(allocator: *mem.Allocator, source: []const u8) !*ast.Tree {
13 var tree_arena = std.heap.ArenaAllocator.init(allocator);13 var tree_arena = std.heap.ArenaAllocator.init(allocator);
14 errdefer tree_arena.deinit();14 errdefer tree_arena.deinit();
1515
...@@ -22,12 +22,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -22,12 +22,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
22 .base = ast.Node{ .id = ast.Node.Id.Root },22 .base = ast.Node{ .id = ast.Node.Id.Root },
23 .decls = ast.Node.Root.DeclList.init(arena),23 .decls = ast.Node.Root.DeclList.init(arena),
24 .doc_comments = null,24 .doc_comments = null,
25 .shebang = null,
26 // initialized when we get the eof token25 // initialized when we get the eof token
27 .eof_token = undefined,26 .eof_token = undefined,
28 };27 };
2928
30 var tree = ast.Tree{29 const tree = try arena.create(ast.Tree);
30 tree.* = ast.Tree{
31 .source = source,31 .source = source,
32 .root_node = root_node,32 .root_node = root_node,
33 .arena_allocator = tree_arena,33 .arena_allocator = tree_arena,
...@@ -43,15 +43,6 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -43,15 +43,6 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
43 }43 }
44 var tok_it = tree.tokens.iterator(0);44 var tok_it = tree.tokens.iterator(0);
4545
46 // skip over shebang line
47 shebang: {
48 const shebang_tok_index = tok_it.index;
49 const shebang_tok_ptr = tok_it.peek() orelse break :shebang;
50 if (shebang_tok_ptr.id != Token.Id.ShebangLine) break :shebang;
51 root_node.shebang = shebang_tok_index;
52 _ = tok_it.next();
53 }
54
55 // skip over line comments at the top of the file46 // skip over line comments at the top of the file
56 while (true) {47 while (true) {
57 const next_tok = tok_it.peek() orelse break;48 const next_tok = tok_it.peek() orelse break;
...@@ -67,9 +58,9 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -67,9 +58,9 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
6758
68 switch (state) {59 switch (state) {
69 State.TopLevel => {60 State.TopLevel => {
70 const comments = try eatDocComments(arena, &tok_it, &tree);61 const comments = try eatDocComments(arena, &tok_it, tree);
7162
72 const token = nextToken(&tok_it, &tree);63 const token = nextToken(&tok_it, tree);
73 const token_index = token.index;64 const token_index = token.index;
74 const token_ptr = token.ptr;65 const token_ptr = token.ptr;
75 switch (token_ptr.id) {66 switch (token_ptr.id) {
...@@ -150,7 +141,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -150,7 +141,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
150 continue;141 continue;
151 },142 },
152 else => {143 else => {
153 prevToken(&tok_it, &tree);144 prevToken(&tok_it, tree);
154 stack.append(State.TopLevel) catch unreachable;145 stack.append(State.TopLevel) catch unreachable;
155 try stack.append(State{146 try stack.append(State{
156 .TopLevelExtern = TopLevelDeclCtx{147 .TopLevelExtern = TopLevelDeclCtx{
...@@ -166,7 +157,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -166,7 +157,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
166 }157 }
167 },158 },
168 State.TopLevelExtern => |ctx| {159 State.TopLevelExtern => |ctx| {
169 const token = nextToken(&tok_it, &tree);160 const token = nextToken(&tok_it, tree);
170 const token_index = token.index;161 const token_index = token.index;
171 const token_ptr = token.ptr;162 const token_ptr = token.ptr;
172 switch (token_ptr.id) {163 switch (token_ptr.id) {
...@@ -201,7 +192,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -201,7 +192,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
201 continue;192 continue;
202 },193 },
203 else => {194 else => {
204 prevToken(&tok_it, &tree);195 prevToken(&tok_it, tree);
205 stack.append(State{ .TopLevelDecl = ctx }) catch unreachable;196 stack.append(State{ .TopLevelDecl = ctx }) catch unreachable;
206 continue;197 continue;
207 },198 },
...@@ -209,11 +200,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -209,11 +200,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
209 },200 },
210 State.TopLevelLibname => |ctx| {201 State.TopLevelLibname => |ctx| {
211 const lib_name = blk: {202 const lib_name = blk: {
212 const lib_name_token = nextToken(&tok_it, &tree);203 const lib_name_token = nextToken(&tok_it, tree);
213 const lib_name_token_index = lib_name_token.index;204 const lib_name_token_index = lib_name_token.index;
214 const lib_name_token_ptr = lib_name_token.ptr;205 const lib_name_token_ptr = lib_name_token.ptr;
215 break :blk (try parseStringLiteral(arena, &tok_it, lib_name_token_ptr, lib_name_token_index, &tree)) orelse {206 break :blk (try parseStringLiteral(arena, &tok_it, lib_name_token_ptr, lib_name_token_index, tree)) orelse {
216 prevToken(&tok_it, &tree);207 prevToken(&tok_it, tree);
217 break :blk null;208 break :blk null;
218 };209 };
219 };210 };
...@@ -230,7 +221,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -230,7 +221,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
230 continue;221 continue;
231 },222 },
232 State.ThreadLocal => |ctx| {223 State.ThreadLocal => |ctx| {
233 const token = nextToken(&tok_it, &tree);224 const token = nextToken(&tok_it, tree);
234 const token_index = token.index;225 const token_index = token.index;
235 const token_ptr = token.ptr;226 const token_ptr = token.ptr;
236 switch (token_ptr.id) {227 switch (token_ptr.id) {
...@@ -256,7 +247,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -256,7 +247,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
256 }247 }
257 },248 },
258 State.TopLevelDecl => |ctx| {249 State.TopLevelDecl => |ctx| {
259 const token = nextToken(&tok_it, &tree);250 const token = nextToken(&tok_it, tree);
260 const token_index = token.index;251 const token_index = token.index;
261 const token_ptr = token.ptr;252 const token_ptr = token.ptr;
262 switch (token_ptr.id) {253 switch (token_ptr.id) {
...@@ -397,7 +388,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -397,7 +388,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
397 }388 }
398 },389 },
399 State.TopLevelExternOrField => |ctx| {390 State.TopLevelExternOrField => |ctx| {
400 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| {391 if (eatToken(&tok_it, tree, Token.Id.Identifier)) |identifier| {
401 const node = try arena.create(ast.Node.StructField);392 const node = try arena.create(ast.Node.StructField);
402 node.* = ast.Node.StructField{393 node.* = ast.Node.StructField{
403 .base = ast.Node{ .id = ast.Node.Id.StructField },394 .base = ast.Node{ .id = ast.Node.Id.StructField },
...@@ -434,11 +425,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -434,11 +425,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
434 },425 },
435426
436 State.FieldInitValue => |ctx| {427 State.FieldInitValue => |ctx| {
437 const eq_tok = nextToken(&tok_it, &tree);428 const eq_tok = nextToken(&tok_it, tree);
438 const eq_tok_index = eq_tok.index;429 const eq_tok_index = eq_tok.index;
439 const eq_tok_ptr = eq_tok.ptr;430 const eq_tok_ptr = eq_tok.ptr;
440 if (eq_tok_ptr.id != Token.Id.Equal) {431 if (eq_tok_ptr.id != Token.Id.Equal) {
441 prevToken(&tok_it, &tree);432 prevToken(&tok_it, tree);
442 continue;433 continue;
443 }434 }
444 stack.append(State{ .Expression = ctx }) catch unreachable;435 stack.append(State{ .Expression = ctx }) catch unreachable;
...@@ -446,7 +437,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -446,7 +437,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
446 },437 },
447438
448 State.ContainerKind => |ctx| {439 State.ContainerKind => |ctx| {
449 const token = nextToken(&tok_it, &tree);440 const token = nextToken(&tok_it, tree);
450 const token_index = token.index;441 const token_index = token.index;
451 const token_ptr = token.ptr;442 const token_ptr = token.ptr;
452 const node = try arena.create(ast.Node.ContainerDecl);443 const node = try arena.create(ast.Node.ContainerDecl);
...@@ -479,7 +470,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -479,7 +470,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
479 },470 },
480471
481 State.ContainerInitArgStart => |container_decl| {472 State.ContainerInitArgStart => |container_decl| {
482 if (eatToken(&tok_it, &tree, Token.Id.LParen) == null) {473 if (eatToken(&tok_it, tree, Token.Id.LParen) == null) {
483 continue;474 continue;
484 }475 }
485476
...@@ -489,24 +480,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -489,24 +480,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
489 },480 },
490481
491 State.ContainerInitArg => |container_decl| {482 State.ContainerInitArg => |container_decl| {
492 const init_arg_token = nextToken(&tok_it, &tree);483 const init_arg_token = nextToken(&tok_it, tree);
493 const init_arg_token_index = init_arg_token.index;484 const init_arg_token_index = init_arg_token.index;
494 const init_arg_token_ptr = init_arg_token.ptr;485 const init_arg_token_ptr = init_arg_token.ptr;
495 switch (init_arg_token_ptr.id) {486 switch (init_arg_token_ptr.id) {
496 Token.Id.Keyword_enum => {487 Token.Id.Keyword_enum => {
497 container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Enum = null };488 container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Enum = null };
498 const lparen_tok = nextToken(&tok_it, &tree);489 const lparen_tok = nextToken(&tok_it, tree);
499 const lparen_tok_index = lparen_tok.index;490 const lparen_tok_index = lparen_tok.index;
500 const lparen_tok_ptr = lparen_tok.ptr;491 const lparen_tok_ptr = lparen_tok.ptr;
501 if (lparen_tok_ptr.id == Token.Id.LParen) {492 if (lparen_tok_ptr.id == Token.Id.LParen) {
502 try stack.append(State{ .ExpectToken = Token.Id.RParen });493 try stack.append(State{ .ExpectToken = Token.Id.RParen });
503 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &container_decl.init_arg_expr.Enum } });494 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &container_decl.init_arg_expr.Enum } });
504 } else {495 } else {
505 prevToken(&tok_it, &tree);496 prevToken(&tok_it, tree);
506 }497 }
507 },498 },
508 else => {499 else => {
509 prevToken(&tok_it, &tree);500 prevToken(&tok_it, tree);
510 container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Type = undefined };501 container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Type = undefined };
511 stack.append(State{ .Expression = OptionalCtx{ .Required = &container_decl.init_arg_expr.Type } }) catch unreachable;502 stack.append(State{ .Expression = OptionalCtx{ .Required = &container_decl.init_arg_expr.Type } }) catch unreachable;
512 },503 },
...@@ -515,8 +506,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -515,8 +506,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
515 },506 },
516507
517 State.ContainerDecl => |container_decl| {508 State.ContainerDecl => |container_decl| {
518 const comments = try eatDocComments(arena, &tok_it, &tree);509 const comments = try eatDocComments(arena, &tok_it, tree);
519 const token = nextToken(&tok_it, &tree);510 const token = nextToken(&tok_it, tree);
520 const token_index = token.index;511 const token_index = token.index;
521 const token_ptr = token.ptr;512 const token_ptr = token.ptr;
522 switch (token_ptr.id) {513 switch (token_ptr.id) {
...@@ -629,6 +620,35 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -629,6 +620,35 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
629 });620 });
630 continue;621 continue;
631 },622 },
623 Token.Id.Keyword_comptime => {
624 const block = try arena.create(ast.Node.Block);
625 block.* = ast.Node.Block{
626 .base = ast.Node{ .id = ast.Node.Id.Block },
627 .label = null,
628 .lbrace = undefined,
629 .statements = ast.Node.Block.StatementList.init(arena),
630 .rbrace = undefined,
631 };
632
633 const node = try arena.create(ast.Node.Comptime);
634 node.* = ast.Node.Comptime{
635 .base = ast.Node{ .id = ast.Node.Id.Comptime },
636 .comptime_token = token_index,
637 .expr = &block.base,
638 .doc_comments = comments,
639 };
640 try container_decl.fields_and_decls.push(&node.base);
641
642 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
643 try stack.append(State{ .Block = block });
644 try stack.append(State{
645 .ExpectTokenSave = ExpectTokenSave{
646 .id = Token.Id.LBrace,
647 .ptr = &block.lbrace,
648 },
649 });
650 continue;
651 },
632 Token.Id.RBrace => {652 Token.Id.RBrace => {
633 if (comments != null) {653 if (comments != null) {
634 ((try tree.errors.addOne())).* = Error{ .UnattachedDocComment = Error.UnattachedDocComment{ .token = token_index } };654 ((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 {...@@ -638,7 +658,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
638 continue;658 continue;
639 },659 },
640 else => {660 else => {
641 prevToken(&tok_it, &tree);661 prevToken(&tok_it, tree);
642 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;662 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
643 try stack.append(State{663 try stack.append(State{
644 .TopLevelExtern = TopLevelDeclCtx{664 .TopLevelExtern = TopLevelDeclCtx{
...@@ -690,7 +710,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -690,7 +710,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
690 State.VarDeclAlign => |var_decl| {710 State.VarDeclAlign => |var_decl| {
691 try stack.append(State{ .VarDeclSection = var_decl });711 try stack.append(State{ .VarDeclSection = var_decl });
692712
693 const next_token = nextToken(&tok_it, &tree);713 const next_token = nextToken(&tok_it, tree);
694 const next_token_index = next_token.index;714 const next_token_index = next_token.index;
695 const next_token_ptr = next_token.ptr;715 const next_token_ptr = next_token.ptr;
696 if (next_token_ptr.id == Token.Id.Keyword_align) {716 if (next_token_ptr.id == Token.Id.Keyword_align) {
...@@ -700,13 +720,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -700,13 +720,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
700 continue;720 continue;
701 }721 }
702722
703 prevToken(&tok_it, &tree);723 prevToken(&tok_it, tree);
704 continue;724 continue;
705 },725 },
706 State.VarDeclSection => |var_decl| {726 State.VarDeclSection => |var_decl| {
707 try stack.append(State{ .VarDeclEq = var_decl });727 try stack.append(State{ .VarDeclEq = var_decl });
708728
709 const next_token = nextToken(&tok_it, &tree);729 const next_token = nextToken(&tok_it, tree);
710 const next_token_index = next_token.index;730 const next_token_index = next_token.index;
711 const next_token_ptr = next_token.ptr;731 const next_token_ptr = next_token.ptr;
712 if (next_token_ptr.id == Token.Id.Keyword_linksection) {732 if (next_token_ptr.id == Token.Id.Keyword_linksection) {
...@@ -716,11 +736,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -716,11 +736,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
716 continue;736 continue;
717 }737 }
718738
719 prevToken(&tok_it, &tree);739 prevToken(&tok_it, tree);
720 continue;740 continue;
721 },741 },
722 State.VarDeclEq => |var_decl| {742 State.VarDeclEq => |var_decl| {
723 const token = nextToken(&tok_it, &tree);743 const token = nextToken(&tok_it, tree);
724 const token_index = token.index;744 const token_index = token.index;
725 const token_ptr = token.ptr;745 const token_ptr = token.ptr;
726 switch (token_ptr.id) {746 switch (token_ptr.id) {
...@@ -742,7 +762,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -742,7 +762,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
742 },762 },
743763
744 State.VarDeclSemiColon => |var_decl| {764 State.VarDeclSemiColon => |var_decl| {
745 const semicolon_token = nextToken(&tok_it, &tree);765 const semicolon_token = nextToken(&tok_it, tree);
746766
747 if (semicolon_token.ptr.id != Token.Id.Semicolon) {767 if (semicolon_token.ptr.id != Token.Id.Semicolon) {
748 ((try tree.errors.addOne())).* = Error{768 ((try tree.errors.addOne())).* = Error{
...@@ -756,18 +776,18 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -756,18 +776,18 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
756776
757 var_decl.semicolon_token = semicolon_token.index;777 var_decl.semicolon_token = semicolon_token.index;
758778
759 if (eatToken(&tok_it, &tree, Token.Id.DocComment)) |doc_comment_token| {779 if (eatToken(&tok_it, tree, Token.Id.DocComment)) |doc_comment_token| {
760 const loc = tree.tokenLocation(semicolon_token.ptr.end, doc_comment_token);780 const loc = tree.tokenLocation(semicolon_token.ptr.end, doc_comment_token);
761 if (loc.line == 0) {781 if (loc.line == 0) {
762 try pushDocComment(arena, doc_comment_token, &var_decl.doc_comments);782 try pushDocComment(arena, doc_comment_token, &var_decl.doc_comments);
763 } else {783 } else {
764 prevToken(&tok_it, &tree);784 prevToken(&tok_it, tree);
765 }785 }
766 }786 }
767 },787 },
768788
769 State.FnDef => |fn_proto| {789 State.FnDef => |fn_proto| {
770 const token = nextToken(&tok_it, &tree);790 const token = nextToken(&tok_it, tree);
771 const token_index = token.index;791 const token_index = token.index;
772 const token_ptr = token.ptr;792 const token_ptr = token.ptr;
773 switch (token_ptr.id) {793 switch (token_ptr.id) {
...@@ -796,7 +816,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -796,7 +816,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
796 try stack.append(State{ .ParamDecl = fn_proto });816 try stack.append(State{ .ParamDecl = fn_proto });
797 try stack.append(State{ .ExpectToken = Token.Id.LParen });817 try stack.append(State{ .ExpectToken = Token.Id.LParen });
798818
799 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |name_token| {819 if (eatToken(&tok_it, tree, Token.Id.Identifier)) |name_token| {
800 fn_proto.name_token = name_token;820 fn_proto.name_token = name_token;
801 }821 }
802 continue;822 continue;
...@@ -804,7 +824,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -804,7 +824,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
804 State.FnProtoAlign => |fn_proto| {824 State.FnProtoAlign => |fn_proto| {
805 stack.append(State{ .FnProtoSection = fn_proto }) catch unreachable;825 stack.append(State{ .FnProtoSection = fn_proto }) catch unreachable;
806826
807 if (eatToken(&tok_it, &tree, Token.Id.Keyword_align)) |align_token| {827 if (eatToken(&tok_it, tree, Token.Id.Keyword_align)) |align_token| {
808 try stack.append(State{ .ExpectToken = Token.Id.RParen });828 try stack.append(State{ .ExpectToken = Token.Id.RParen });
809 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.align_expr } });829 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.align_expr } });
810 try stack.append(State{ .ExpectToken = Token.Id.LParen });830 try stack.append(State{ .ExpectToken = Token.Id.LParen });
...@@ -814,7 +834,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -814,7 +834,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
814 State.FnProtoSection => |fn_proto| {834 State.FnProtoSection => |fn_proto| {
815 stack.append(State{ .FnProtoReturnType = fn_proto }) catch unreachable;835 stack.append(State{ .FnProtoReturnType = fn_proto }) catch unreachable;
816836
817 if (eatToken(&tok_it, &tree, Token.Id.Keyword_linksection)) |align_token| {837 if (eatToken(&tok_it, tree, Token.Id.Keyword_linksection)) |align_token| {
818 try stack.append(State{ .ExpectToken = Token.Id.RParen });838 try stack.append(State{ .ExpectToken = Token.Id.RParen });
819 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.section_expr } });839 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.section_expr } });
820 try stack.append(State{ .ExpectToken = Token.Id.LParen });840 try stack.append(State{ .ExpectToken = Token.Id.LParen });
...@@ -822,7 +842,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -822,7 +842,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
822 continue;842 continue;
823 },843 },
824 State.FnProtoReturnType => |fn_proto| {844 State.FnProtoReturnType => |fn_proto| {
825 const token = nextToken(&tok_it, &tree);845 const token = nextToken(&tok_it, tree);
826 const token_index = token.index;846 const token_index = token.index;
827 const token_ptr = token.ptr;847 const token_ptr = token.ptr;
828 switch (token_ptr.id) {848 switch (token_ptr.id) {
...@@ -845,7 +865,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -845,7 +865,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
845 }865 }
846 }866 }
847867
848 prevToken(&tok_it, &tree);868 prevToken(&tok_it, tree);
849 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = undefined };869 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = undefined };
850 stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.Explicit } }) catch unreachable;870 stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.Explicit } }) catch unreachable;
851 continue;871 continue;
...@@ -854,8 +874,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -854,8 +874,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
854 },874 },
855875
856 State.ParamDecl => |fn_proto| {876 State.ParamDecl => |fn_proto| {
857 const comments = try eatDocComments(arena, &tok_it, &tree);877 const comments = try eatDocComments(arena, &tok_it, tree);
858 if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {878 if (eatToken(&tok_it, tree, Token.Id.RParen)) |_| {
859 continue;879 continue;
860 }880 }
861 const param_decl = try arena.create(ast.Node.ParamDecl);881 const param_decl = try arena.create(ast.Node.ParamDecl);
...@@ -881,9 +901,9 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -881,9 +901,9 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
881 continue;901 continue;
882 },902 },
883 State.ParamDeclAliasOrComptime => |param_decl| {903 State.ParamDeclAliasOrComptime => |param_decl| {
884 if (eatToken(&tok_it, &tree, Token.Id.Keyword_comptime)) |comptime_token| {904 if (eatToken(&tok_it, tree, Token.Id.Keyword_comptime)) |comptime_token| {
885 param_decl.comptime_token = comptime_token;905 param_decl.comptime_token = comptime_token;
886 } else if (eatToken(&tok_it, &tree, Token.Id.Keyword_noalias)) |noalias_token| {906 } else if (eatToken(&tok_it, tree, Token.Id.Keyword_noalias)) |noalias_token| {
887 param_decl.noalias_token = noalias_token;907 param_decl.noalias_token = noalias_token;
888 }908 }
889 continue;909 continue;
...@@ -891,20 +911,20 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -891,20 +911,20 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
891 State.ParamDeclName => |param_decl| {911 State.ParamDeclName => |param_decl| {
892 // TODO: Here, we eat two tokens in one state. This means that we can't have912 // TODO: Here, we eat two tokens in one state. This means that we can't have
893 // comments between these two tokens.913 // comments between these two tokens.
894 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |ident_token| {914 if (eatToken(&tok_it, tree, Token.Id.Identifier)) |ident_token| {
895 if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| {915 if (eatToken(&tok_it, tree, Token.Id.Colon)) |_| {
896 param_decl.name_token = ident_token;916 param_decl.name_token = ident_token;
897 } else {917 } else {
898 prevToken(&tok_it, &tree);918 prevToken(&tok_it, tree);
899 }919 }
900 }920 }
901 continue;921 continue;
902 },922 },
903 State.ParamDeclEnd => |ctx| {923 State.ParamDeclEnd => |ctx| {
904 if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {924 if (eatToken(&tok_it, tree, Token.Id.Ellipsis3)) |ellipsis3| {
905 ctx.param_decl.var_args_token = ellipsis3;925 ctx.param_decl.var_args_token = ellipsis3;
906926
907 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) {927 switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RParen)) {
908 ExpectCommaOrEndResult.end_token => |t| {928 ExpectCommaOrEndResult.end_token => |t| {
909 if (t == null) {929 if (t == null) {
910 stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable;930 stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable;
...@@ -924,7 +944,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -924,7 +944,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
924 continue;944 continue;
925 },945 },
926 State.ParamDeclComma => |fn_proto| {946 State.ParamDeclComma => |fn_proto| {
927 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) {947 switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RParen)) {
928 ExpectCommaOrEndResult.end_token => |t| {948 ExpectCommaOrEndResult.end_token => |t| {
929 if (t == null) {949 if (t == null) {
930 stack.append(State{ .ParamDecl = fn_proto }) catch unreachable;950 stack.append(State{ .ParamDecl = fn_proto }) catch unreachable;
...@@ -939,7 +959,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -939,7 +959,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
939 },959 },
940960
941 State.MaybeLabeledExpression => |ctx| {961 State.MaybeLabeledExpression => |ctx| {
942 if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| {962 if (eatToken(&tok_it, tree, Token.Id.Colon)) |_| {
943 stack.append(State{963 stack.append(State{
944 .LabeledExpression = LabelCtx{964 .LabeledExpression = LabelCtx{
945 .label = ctx.label,965 .label = ctx.label,
...@@ -953,7 +973,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -953,7 +973,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
953 continue;973 continue;
954 },974 },
955 State.LabeledExpression => |ctx| {975 State.LabeledExpression => |ctx| {
956 const token = nextToken(&tok_it, &tree);976 const token = nextToken(&tok_it, tree);
957 const token_index = token.index;977 const token_index = token.index;
958 const token_ptr = token.ptr;978 const token_ptr = token.ptr;
959 switch (token_ptr.id) {979 switch (token_ptr.id) {
...@@ -1008,13 +1028,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1008,13 +1028,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1008 return tree;1028 return tree;
1009 }1029 }
10101030
1011 prevToken(&tok_it, &tree);1031 prevToken(&tok_it, tree);
1012 continue;1032 continue;
1013 },1033 },
1014 }1034 }
1015 },1035 },
1016 State.Inline => |ctx| {1036 State.Inline => |ctx| {
1017 const token = nextToken(&tok_it, &tree);1037 const token = nextToken(&tok_it, tree);
1018 const token_index = token.index;1038 const token_index = token.index;
1019 const token_ptr = token.ptr;1039 const token_ptr = token.ptr;
1020 switch (token_ptr.id) {1040 switch (token_ptr.id) {
...@@ -1046,7 +1066,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1046,7 +1066,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1046 return tree;1066 return tree;
1047 }1067 }
10481068
1049 prevToken(&tok_it, &tree);1069 prevToken(&tok_it, tree);
1050 continue;1070 continue;
1051 },1071 },
1052 }1072 }
...@@ -1103,7 +1123,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1103,7 +1123,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1103 continue;1123 continue;
1104 },1124 },
1105 State.Else => |dest| {1125 State.Else => |dest| {
1106 if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {1126 if (eatToken(&tok_it, tree, Token.Id.Keyword_else)) |else_token| {
1107 const node = try arena.create(ast.Node.Else);1127 const node = try arena.create(ast.Node.Else);
1108 node.* = ast.Node.Else{1128 node.* = ast.Node.Else{
1109 .base = ast.Node{ .id = ast.Node.Id.Else },1129 .base = ast.Node{ .id = ast.Node.Id.Else },
...@@ -1122,7 +1142,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1122,7 +1142,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1122 },1142 },
11231143
1124 State.Block => |block| {1144 State.Block => |block| {
1125 const token = nextToken(&tok_it, &tree);1145 const token = nextToken(&tok_it, tree);
1126 const token_index = token.index;1146 const token_index = token.index;
1127 const token_ptr = token.ptr;1147 const token_ptr = token.ptr;
1128 switch (token_ptr.id) {1148 switch (token_ptr.id) {
...@@ -1131,7 +1151,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1131,7 +1151,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1131 continue;1151 continue;
1132 },1152 },
1133 else => {1153 else => {
1134 prevToken(&tok_it, &tree);1154 prevToken(&tok_it, tree);
1135 stack.append(State{ .Block = block }) catch unreachable;1155 stack.append(State{ .Block = block }) catch unreachable;
11361156
1137 try stack.append(State{ .Statement = block });1157 try stack.append(State{ .Statement = block });
...@@ -1140,7 +1160,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1140,7 +1160,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1140 }1160 }
1141 },1161 },
1142 State.Statement => |block| {1162 State.Statement => |block| {
1143 const token = nextToken(&tok_it, &tree);1163 const token = nextToken(&tok_it, tree);
1144 const token_index = token.index;1164 const token_index = token.index;
1145 const token_ptr = token.ptr;1165 const token_ptr = token.ptr;
1146 switch (token_ptr.id) {1166 switch (token_ptr.id) {
...@@ -1197,7 +1217,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1197,7 +1217,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1197 continue;1217 continue;
1198 },1218 },
1199 else => {1219 else => {
1200 prevToken(&tok_it, &tree);1220 prevToken(&tok_it, tree);
1201 const statement = try block.statements.addOne();1221 const statement = try block.statements.addOne();
1202 try stack.append(State{ .Semicolon = statement });1222 try stack.append(State{ .Semicolon = statement });
1203 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } });1223 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } });
...@@ -1206,7 +1226,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1206,7 +1226,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1206 }1226 }
1207 },1227 },
1208 State.ComptimeStatement => |ctx| {1228 State.ComptimeStatement => |ctx| {
1209 const token = nextToken(&tok_it, &tree);1229 const token = nextToken(&tok_it, tree);
1210 const token_index = token.index;1230 const token_index = token.index;
1211 const token_ptr = token.ptr;1231 const token_ptr = token.ptr;
1212 switch (token_ptr.id) {1232 switch (token_ptr.id) {
...@@ -1226,8 +1246,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1226,8 +1246,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1226 continue;1246 continue;
1227 },1247 },
1228 else => {1248 else => {
1229 prevToken(&tok_it, &tree);1249 prevToken(&tok_it, tree);
1230 prevToken(&tok_it, &tree);1250 prevToken(&tok_it, tree);
1231 const statement = try ctx.block.statements.addOne();1251 const statement = try ctx.block.statements.addOne();
1232 try stack.append(State{ .Semicolon = statement });1252 try stack.append(State{ .Semicolon = statement });
1233 try stack.append(State{ .Expression = OptionalCtx{ .Required = statement } });1253 try stack.append(State{ .Expression = OptionalCtx{ .Required = statement } });
...@@ -1245,11 +1265,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1245,11 +1265,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1245 },1265 },
12461266
1247 State.AsmOutputItems => |items| {1267 State.AsmOutputItems => |items| {
1248 const lbracket = nextToken(&tok_it, &tree);1268 const lbracket = nextToken(&tok_it, tree);
1249 const lbracket_index = lbracket.index;1269 const lbracket_index = lbracket.index;
1250 const lbracket_ptr = lbracket.ptr;1270 const lbracket_ptr = lbracket.ptr;
1251 if (lbracket_ptr.id != Token.Id.LBracket) {1271 if (lbracket_ptr.id != Token.Id.LBracket) {
1252 prevToken(&tok_it, &tree);1272 prevToken(&tok_it, tree);
1253 continue;1273 continue;
1254 }1274 }
12551275
...@@ -1280,7 +1300,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1280,7 +1300,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1280 continue;1300 continue;
1281 },1301 },
1282 State.AsmOutputReturnOrType => |node| {1302 State.AsmOutputReturnOrType => |node| {
1283 const token = nextToken(&tok_it, &tree);1303 const token = nextToken(&tok_it, tree);
1284 const token_index = token.index;1304 const token_index = token.index;
1285 const token_ptr = token.ptr;1305 const token_ptr = token.ptr;
1286 switch (token_ptr.id) {1306 switch (token_ptr.id) {
...@@ -1300,11 +1320,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1300,11 +1320,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1300 }1320 }
1301 },1321 },
1302 State.AsmInputItems => |items| {1322 State.AsmInputItems => |items| {
1303 const lbracket = nextToken(&tok_it, &tree);1323 const lbracket = nextToken(&tok_it, tree);
1304 const lbracket_index = lbracket.index;1324 const lbracket_index = lbracket.index;
1305 const lbracket_ptr = lbracket.ptr;1325 const lbracket_ptr = lbracket.ptr;
1306 if (lbracket_ptr.id != Token.Id.LBracket) {1326 if (lbracket_ptr.id != Token.Id.LBracket) {
1307 prevToken(&tok_it, &tree);1327 prevToken(&tok_it, tree);
1308 continue;1328 continue;
1309 }1329 }
13101330
...@@ -1335,16 +1355,16 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1335,16 +1355,16 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1335 continue;1355 continue;
1336 },1356 },
1337 State.AsmClobberItems => |items| {1357 State.AsmClobberItems => |items| {
1338 while (eatToken(&tok_it, &tree, Token.Id.StringLiteral)) |strlit| {1358 while (eatToken(&tok_it, tree, Token.Id.StringLiteral)) |strlit| {
1339 try items.push(strlit);1359 try items.push(strlit);
1340 if (eatToken(&tok_it, &tree, Token.Id.Comma) == null)1360 if (eatToken(&tok_it, tree, Token.Id.Comma) == null)
1341 break;1361 break;
1342 }1362 }
1343 continue;1363 continue;
1344 },1364 },
13451365
1346 State.ExprListItemOrEnd => |list_state| {1366 State.ExprListItemOrEnd => |list_state| {
1347 if (eatToken(&tok_it, &tree, list_state.end)) |token_index| {1367 if (eatToken(&tok_it, tree, list_state.end)) |token_index| {
1348 (list_state.ptr).* = token_index;1368 (list_state.ptr).* = token_index;
1349 continue;1369 continue;
1350 }1370 }
...@@ -1354,7 +1374,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1354,7 +1374,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1354 continue;1374 continue;
1355 },1375 },
1356 State.ExprListCommaOrEnd => |list_state| {1376 State.ExprListCommaOrEnd => |list_state| {
1357 switch (expectCommaOrEnd(&tok_it, &tree, list_state.end)) {1377 switch (expectCommaOrEnd(&tok_it, tree, list_state.end)) {
1358 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {1378 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1359 (list_state.ptr).* = end;1379 (list_state.ptr).* = end;
1360 continue;1380 continue;
...@@ -1369,7 +1389,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1369,7 +1389,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1369 }1389 }
1370 },1390 },
1371 State.FieldInitListItemOrEnd => |list_state| {1391 State.FieldInitListItemOrEnd => |list_state| {
1372 if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| {1392 if (eatToken(&tok_it, tree, Token.Id.RBrace)) |rbrace| {
1373 (list_state.ptr).* = rbrace;1393 (list_state.ptr).* = rbrace;
1374 continue;1394 continue;
1375 }1395 }
...@@ -1401,7 +1421,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1401,7 +1421,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1401 continue;1421 continue;
1402 },1422 },
1403 State.FieldInitListCommaOrEnd => |list_state| {1423 State.FieldInitListCommaOrEnd => |list_state| {
1404 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {1424 switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RBrace)) {
1405 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {1425 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1406 (list_state.ptr).* = end;1426 (list_state.ptr).* = end;
1407 continue;1427 continue;
...@@ -1416,17 +1436,17 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1416,17 +1436,17 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1416 }1436 }
1417 },1437 },
1418 State.FieldListCommaOrEnd => |field_ctx| {1438 State.FieldListCommaOrEnd => |field_ctx| {
1419 const end_token = nextToken(&tok_it, &tree);1439 const end_token = nextToken(&tok_it, tree);
1420 const end_token_index = end_token.index;1440 const end_token_index = end_token.index;
1421 const end_token_ptr = end_token.ptr;1441 const end_token_ptr = end_token.ptr;
1422 switch (end_token_ptr.id) {1442 switch (end_token_ptr.id) {
1423 Token.Id.Comma => {1443 Token.Id.Comma => {
1424 if (eatToken(&tok_it, &tree, Token.Id.DocComment)) |doc_comment_token| {1444 if (eatToken(&tok_it, tree, Token.Id.DocComment)) |doc_comment_token| {
1425 const loc = tree.tokenLocation(end_token_ptr.end, doc_comment_token);1445 const loc = tree.tokenLocation(end_token_ptr.end, doc_comment_token);
1426 if (loc.line == 0) {1446 if (loc.line == 0) {
1427 try pushDocComment(arena, doc_comment_token, field_ctx.doc_comments);1447 try pushDocComment(arena, doc_comment_token, field_ctx.doc_comments);
1428 } else {1448 } else {
1429 prevToken(&tok_it, &tree);1449 prevToken(&tok_it, tree);
1430 }1450 }
1431 }1451 }
14321452
...@@ -1449,7 +1469,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1449,7 +1469,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1449 }1469 }
1450 },1470 },
1451 State.ErrorTagListItemOrEnd => |list_state| {1471 State.ErrorTagListItemOrEnd => |list_state| {
1452 if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| {1472 if (eatToken(&tok_it, tree, Token.Id.RBrace)) |rbrace| {
1453 (list_state.ptr).* = rbrace;1473 (list_state.ptr).* = rbrace;
1454 continue;1474 continue;
1455 }1475 }
...@@ -1461,7 +1481,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1461,7 +1481,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1461 continue;1481 continue;
1462 },1482 },
1463 State.ErrorTagListCommaOrEnd => |list_state| {1483 State.ErrorTagListCommaOrEnd => |list_state| {
1464 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {1484 switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RBrace)) {
1465 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {1485 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1466 (list_state.ptr).* = end;1486 (list_state.ptr).* = end;
1467 continue;1487 continue;
...@@ -1476,12 +1496,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1476,12 +1496,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1476 }1496 }
1477 },1497 },
1478 State.SwitchCaseOrEnd => |list_state| {1498 State.SwitchCaseOrEnd => |list_state| {
1479 if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| {1499 if (eatToken(&tok_it, tree, Token.Id.RBrace)) |rbrace| {
1480 (list_state.ptr).* = rbrace;1500 (list_state.ptr).* = rbrace;
1481 continue;1501 continue;
1482 }1502 }
14831503
1484 const comments = try eatDocComments(arena, &tok_it, &tree);1504 const comments = try eatDocComments(arena, &tok_it, tree);
1485 const node = try arena.create(ast.Node.SwitchCase);1505 const node = try arena.create(ast.Node.SwitchCase);
1486 node.* = ast.Node.SwitchCase{1506 node.* = ast.Node.SwitchCase{
1487 .base = ast.Node{ .id = ast.Node.Id.SwitchCase },1507 .base = ast.Node{ .id = ast.Node.Id.SwitchCase },
...@@ -1500,7 +1520,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1500,7 +1520,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1500 },1520 },
15011521
1502 State.SwitchCaseCommaOrEnd => |list_state| {1522 State.SwitchCaseCommaOrEnd => |list_state| {
1503 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {1523 switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RBrace)) {
1504 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {1524 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1505 (list_state.ptr).* = end;1525 (list_state.ptr).* = end;
1506 continue;1526 continue;
...@@ -1516,7 +1536,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1516,7 +1536,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1516 },1536 },
15171537
1518 State.SwitchCaseFirstItem => |switch_case| {1538 State.SwitchCaseFirstItem => |switch_case| {
1519 const token = nextToken(&tok_it, &tree);1539 const token = nextToken(&tok_it, tree);
1520 const token_index = token.index;1540 const token_index = token.index;
1521 const token_ptr = token.ptr;1541 const token_ptr = token.ptr;
1522 if (token_ptr.id == Token.Id.Keyword_else) {1542 if (token_ptr.id == Token.Id.Keyword_else) {
...@@ -1535,26 +1555,26 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1535,26 +1555,26 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1535 });1555 });
1536 continue;1556 continue;
1537 } else {1557 } else {
1538 prevToken(&tok_it, &tree);1558 prevToken(&tok_it, tree);
1539 stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;1559 stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;
1540 try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });1560 try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });
1541 continue;1561 continue;
1542 }1562 }
1543 },1563 },
1544 State.SwitchCaseItemOrEnd => |switch_case| {1564 State.SwitchCaseItemOrEnd => |switch_case| {
1545 const token = nextToken(&tok_it, &tree);1565 const token = nextToken(&tok_it, tree);
1546 if (token.ptr.id == Token.Id.EqualAngleBracketRight) {1566 if (token.ptr.id == Token.Id.EqualAngleBracketRight) {
1547 switch_case.arrow_token = token.index;1567 switch_case.arrow_token = token.index;
1548 continue;1568 continue;
1549 } else {1569 } else {
1550 prevToken(&tok_it, &tree);1570 prevToken(&tok_it, tree);
1551 stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;1571 stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;
1552 try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });1572 try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });
1553 continue;1573 continue;
1554 }1574 }
1555 },1575 },
1556 State.SwitchCaseItemCommaOrEnd => |switch_case| {1576 State.SwitchCaseItemCommaOrEnd => |switch_case| {
1557 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.EqualAngleBracketRight)) {1577 switch (expectCommaOrEnd(&tok_it, tree, Token.Id.EqualAngleBracketRight)) {
1558 ExpectCommaOrEndResult.end_token => |end_token| {1578 ExpectCommaOrEndResult.end_token => |end_token| {
1559 if (end_token) |t| {1579 if (end_token) |t| {
1560 switch_case.arrow_token = t;1580 switch_case.arrow_token = t;
...@@ -1572,14 +1592,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1572,14 +1592,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1572 },1592 },
15731593
1574 State.SuspendBody => |suspend_node| {1594 State.SuspendBody => |suspend_node| {
1575 const token = nextToken(&tok_it, &tree);1595 const token = nextToken(&tok_it, tree);
1576 switch (token.ptr.id) {1596 switch (token.ptr.id) {
1577 Token.Id.Semicolon => {1597 Token.Id.Semicolon => {
1578 prevToken(&tok_it, &tree);1598 prevToken(&tok_it, tree);
1579 continue;1599 continue;
1580 },1600 },
1581 Token.Id.LBrace => {1601 Token.Id.LBrace => {
1582 prevToken(&tok_it, &tree);1602 prevToken(&tok_it, tree);
1583 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } });1603 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } });
1584 continue;1604 continue;
1585 },1605 },
...@@ -1589,7 +1609,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1589,7 +1609,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1589 }1609 }
1590 },1610 },
1591 State.AsyncAllocator => |async_node| {1611 State.AsyncAllocator => |async_node| {
1592 if (eatToken(&tok_it, &tree, Token.Id.AngleBracketLeft) == null) {1612 if (eatToken(&tok_it, tree, Token.Id.AngleBracketLeft) == null) {
1593 continue;1613 continue;
1594 }1614 }
15951615
...@@ -1630,7 +1650,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1630,7 +1650,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1630 },1650 },
16311651
1632 State.ExternType => |ctx| {1652 State.ExternType => |ctx| {
1633 if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| {1653 if (eatToken(&tok_it, tree, Token.Id.Keyword_fn)) |fn_token| {
1634 const fn_proto = try arena.create(ast.Node.FnProto);1654 const fn_proto = try arena.create(ast.Node.FnProto);
1635 fn_proto.* = ast.Node.FnProto{1655 fn_proto.* = ast.Node.FnProto{
1636 .base = ast.Node{ .id = ast.Node.Id.FnProto },1656 .base = ast.Node{ .id = ast.Node.Id.FnProto },
...@@ -1663,7 +1683,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1663,7 +1683,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1663 continue;1683 continue;
1664 },1684 },
1665 State.SliceOrArrayAccess => |node| {1685 State.SliceOrArrayAccess => |node| {
1666 const token = nextToken(&tok_it, &tree);1686 const token = nextToken(&tok_it, tree);
1667 const token_index = token.index;1687 const token_index = token.index;
1668 const token_ptr = token.ptr;1688 const token_ptr = token.ptr;
1669 switch (token_ptr.id) {1689 switch (token_ptr.id) {
...@@ -1696,7 +1716,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1696,7 +1716,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1696 }1716 }
1697 },1717 },
1698 State.SliceOrArrayType => |node| {1718 State.SliceOrArrayType => |node| {
1699 if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| {1719 if (eatToken(&tok_it, tree, Token.Id.RBracket)) |_| {
1700 node.op = ast.Node.PrefixOp.Op{1720 node.op = ast.Node.PrefixOp.Op{
1701 .SliceType = ast.Node.PrefixOp.PtrInfo{1721 .SliceType = ast.Node.PrefixOp.PtrInfo{
1702 .align_info = null,1722 .align_info = null,
...@@ -1718,7 +1738,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1718,7 +1738,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1718 },1738 },
17191739
1720 State.PtrTypeModifiers => |addr_of_info| {1740 State.PtrTypeModifiers => |addr_of_info| {
1721 const token = nextToken(&tok_it, &tree);1741 const token = nextToken(&tok_it, tree);
1722 const token_index = token.index;1742 const token_index = token.index;
1723 const token_ptr = token.ptr;1743 const token_ptr = token.ptr;
1724 switch (token_ptr.id) {1744 switch (token_ptr.id) {
...@@ -1768,14 +1788,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1768,14 +1788,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1768 continue;1788 continue;
1769 },1789 },
1770 else => {1790 else => {
1771 prevToken(&tok_it, &tree);1791 prevToken(&tok_it, tree);
1772 continue;1792 continue;
1773 },1793 },
1774 }1794 }
1775 },1795 },
17761796
1777 State.AlignBitRange => |align_info| {1797 State.AlignBitRange => |align_info| {
1778 const token = nextToken(&tok_it, &tree);1798 const token = nextToken(&tok_it, tree);
1779 switch (token.ptr.id) {1799 switch (token.ptr.id) {
1780 Token.Id.Colon => {1800 Token.Id.Colon => {
1781 align_info.bit_range = ast.Node.PrefixOp.PtrInfo.Align.BitRange(undefined);1801 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 {...@@ -1798,7 +1818,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1798 },1818 },
17991819
1800 State.Payload => |opt_ctx| {1820 State.Payload => |opt_ctx| {
1801 const token = nextToken(&tok_it, &tree);1821 const token = nextToken(&tok_it, tree);
1802 const token_index = token.index;1822 const token_index = token.index;
1803 const token_ptr = token.ptr;1823 const token_ptr = token.ptr;
1804 if (token_ptr.id != Token.Id.Pipe) {1824 if (token_ptr.id != Token.Id.Pipe) {
...@@ -1812,7 +1832,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1812,7 +1832,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1812 return tree;1832 return tree;
1813 }1833 }
18141834
1815 prevToken(&tok_it, &tree);1835 prevToken(&tok_it, tree);
1816 continue;1836 continue;
1817 }1837 }
18181838
...@@ -1835,7 +1855,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1835,7 +1855,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1835 continue;1855 continue;
1836 },1856 },
1837 State.PointerPayload => |opt_ctx| {1857 State.PointerPayload => |opt_ctx| {
1838 const token = nextToken(&tok_it, &tree);1858 const token = nextToken(&tok_it, tree);
1839 const token_index = token.index;1859 const token_index = token.index;
1840 const token_ptr = token.ptr;1860 const token_ptr = token.ptr;
1841 if (token_ptr.id != Token.Id.Pipe) {1861 if (token_ptr.id != Token.Id.Pipe) {
...@@ -1849,7 +1869,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1849,7 +1869,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1849 return tree;1869 return tree;
1850 }1870 }
18511871
1852 prevToken(&tok_it, &tree);1872 prevToken(&tok_it, tree);
1853 continue;1873 continue;
1854 }1874 }
18551875
...@@ -1879,7 +1899,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1879,7 +1899,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1879 continue;1899 continue;
1880 },1900 },
1881 State.PointerIndexPayload => |opt_ctx| {1901 State.PointerIndexPayload => |opt_ctx| {
1882 const token = nextToken(&tok_it, &tree);1902 const token = nextToken(&tok_it, tree);
1883 const token_index = token.index;1903 const token_index = token.index;
1884 const token_ptr = token.ptr;1904 const token_ptr = token.ptr;
1885 if (token_ptr.id != Token.Id.Pipe) {1905 if (token_ptr.id != Token.Id.Pipe) {
...@@ -1893,7 +1913,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1893,7 +1913,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1893 return tree;1913 return tree;
1894 }1914 }
18951915
1896 prevToken(&tok_it, &tree);1916 prevToken(&tok_it, tree);
1897 continue;1917 continue;
1898 }1918 }
18991919
...@@ -1927,7 +1947,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1927,7 +1947,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1927 },1947 },
19281948
1929 State.Expression => |opt_ctx| {1949 State.Expression => |opt_ctx| {
1930 const token = nextToken(&tok_it, &tree);1950 const token = nextToken(&tok_it, tree);
1931 const token_index = token.index;1951 const token_index = token.index;
1932 const token_ptr = token.ptr;1952 const token_ptr = token.ptr;
1933 switch (token_ptr.id) {1953 switch (token_ptr.id) {
...@@ -1981,7 +2001,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1981,7 +2001,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1981 },2001 },
1982 else => {2002 else => {
1983 if (!try parseBlockExpr(&stack, arena, opt_ctx, token_ptr.*, token_index)) {2003 if (!try parseBlockExpr(&stack, arena, opt_ctx, token_ptr.*, token_index)) {
1984 prevToken(&tok_it, &tree);2004 prevToken(&tok_it, tree);
1985 stack.append(State{ .UnwrapExpressionBegin = opt_ctx }) catch unreachable;2005 stack.append(State{ .UnwrapExpressionBegin = opt_ctx }) catch unreachable;
1986 }2006 }
1987 continue;2007 continue;
...@@ -1996,7 +2016,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1996,7 +2016,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1996 State.RangeExpressionEnd => |opt_ctx| {2016 State.RangeExpressionEnd => |opt_ctx| {
1997 const lhs = opt_ctx.get() orelse continue;2017 const lhs = opt_ctx.get() orelse continue;
19982018
1999 if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {2019 if (eatToken(&tok_it, tree, Token.Id.Ellipsis3)) |ellipsis3| {
2000 const node = try arena.create(ast.Node.InfixOp);2020 const node = try arena.create(ast.Node.InfixOp);
2001 node.* = ast.Node.InfixOp{2021 node.* = ast.Node.InfixOp{
2002 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2022 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
...@@ -2019,7 +2039,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2019,7 +2039,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2019 State.AssignmentExpressionEnd => |opt_ctx| {2039 State.AssignmentExpressionEnd => |opt_ctx| {
2020 const lhs = opt_ctx.get() orelse continue;2040 const lhs = opt_ctx.get() orelse continue;
20212041
2022 const token = nextToken(&tok_it, &tree);2042 const token = nextToken(&tok_it, tree);
2023 const token_index = token.index;2043 const token_index = token.index;
2024 const token_ptr = token.ptr;2044 const token_ptr = token.ptr;
2025 if (tokenIdToAssignment(token_ptr.id)) |ass_id| {2045 if (tokenIdToAssignment(token_ptr.id)) |ass_id| {
...@@ -2036,7 +2056,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2036,7 +2056,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2036 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });2056 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });
2037 continue;2057 continue;
2038 } else {2058 } else {
2039 prevToken(&tok_it, &tree);2059 prevToken(&tok_it, tree);
2040 continue;2060 continue;
2041 }2061 }
2042 },2062 },
...@@ -2050,7 +2070,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2050,7 +2070,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2050 State.UnwrapExpressionEnd => |opt_ctx| {2070 State.UnwrapExpressionEnd => |opt_ctx| {
2051 const lhs = opt_ctx.get() orelse continue;2071 const lhs = opt_ctx.get() orelse continue;
20522072
2053 const token = nextToken(&tok_it, &tree);2073 const token = nextToken(&tok_it, tree);
2054 const token_index = token.index;2074 const token_index = token.index;
2055 const token_ptr = token.ptr;2075 const token_ptr = token.ptr;
2056 if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {2076 if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {
...@@ -2072,7 +2092,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2072,7 +2092,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2072 }2092 }
2073 continue;2093 continue;
2074 } else {2094 } else {
2075 prevToken(&tok_it, &tree);2095 prevToken(&tok_it, tree);
2076 continue;2096 continue;
2077 }2097 }
2078 },2098 },
...@@ -2086,7 +2106,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2086,7 +2106,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2086 State.BoolOrExpressionEnd => |opt_ctx| {2106 State.BoolOrExpressionEnd => |opt_ctx| {
2087 const lhs = opt_ctx.get() orelse continue;2107 const lhs = opt_ctx.get() orelse continue;
20882108
2089 if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| {2109 if (eatToken(&tok_it, tree, Token.Id.Keyword_or)) |or_token| {
2090 const node = try arena.create(ast.Node.InfixOp);2110 const node = try arena.create(ast.Node.InfixOp);
2091 node.* = ast.Node.InfixOp{2111 node.* = ast.Node.InfixOp{
2092 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2112 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
...@@ -2111,7 +2131,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2111,7 +2131,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2111 State.BoolAndExpressionEnd => |opt_ctx| {2131 State.BoolAndExpressionEnd => |opt_ctx| {
2112 const lhs = opt_ctx.get() orelse continue;2132 const lhs = opt_ctx.get() orelse continue;
21132133
2114 if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| {2134 if (eatToken(&tok_it, tree, Token.Id.Keyword_and)) |and_token| {
2115 const node = try arena.create(ast.Node.InfixOp);2135 const node = try arena.create(ast.Node.InfixOp);
2116 node.* = ast.Node.InfixOp{2136 node.* = ast.Node.InfixOp{
2117 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2137 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
...@@ -2136,7 +2156,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2136,7 +2156,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2136 State.ComparisonExpressionEnd => |opt_ctx| {2156 State.ComparisonExpressionEnd => |opt_ctx| {
2137 const lhs = opt_ctx.get() orelse continue;2157 const lhs = opt_ctx.get() orelse continue;
21382158
2139 const token = nextToken(&tok_it, &tree);2159 const token = nextToken(&tok_it, tree);
2140 const token_index = token.index;2160 const token_index = token.index;
2141 const token_ptr = token.ptr;2161 const token_ptr = token.ptr;
2142 if (tokenIdToComparison(token_ptr.id)) |comp_id| {2162 if (tokenIdToComparison(token_ptr.id)) |comp_id| {
...@@ -2153,7 +2173,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2153,7 +2173,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2153 try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2173 try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
2154 continue;2174 continue;
2155 } else {2175 } else {
2156 prevToken(&tok_it, &tree);2176 prevToken(&tok_it, tree);
2157 continue;2177 continue;
2158 }2178 }
2159 },2179 },
...@@ -2167,7 +2187,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2167,7 +2187,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2167 State.BinaryOrExpressionEnd => |opt_ctx| {2187 State.BinaryOrExpressionEnd => |opt_ctx| {
2168 const lhs = opt_ctx.get() orelse continue;2188 const lhs = opt_ctx.get() orelse continue;
21692189
2170 if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| {2190 if (eatToken(&tok_it, tree, Token.Id.Pipe)) |pipe| {
2171 const node = try arena.create(ast.Node.InfixOp);2191 const node = try arena.create(ast.Node.InfixOp);
2172 node.* = ast.Node.InfixOp{2192 node.* = ast.Node.InfixOp{
2173 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2193 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
...@@ -2192,7 +2212,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2192,7 +2212,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2192 State.BinaryXorExpressionEnd => |opt_ctx| {2212 State.BinaryXorExpressionEnd => |opt_ctx| {
2193 const lhs = opt_ctx.get() orelse continue;2213 const lhs = opt_ctx.get() orelse continue;
21942214
2195 if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| {2215 if (eatToken(&tok_it, tree, Token.Id.Caret)) |caret| {
2196 const node = try arena.create(ast.Node.InfixOp);2216 const node = try arena.create(ast.Node.InfixOp);
2197 node.* = ast.Node.InfixOp{2217 node.* = ast.Node.InfixOp{
2198 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2218 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
...@@ -2217,7 +2237,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2217,7 +2237,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2217 State.BinaryAndExpressionEnd => |opt_ctx| {2237 State.BinaryAndExpressionEnd => |opt_ctx| {
2218 const lhs = opt_ctx.get() orelse continue;2238 const lhs = opt_ctx.get() orelse continue;
22192239
2220 if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| {2240 if (eatToken(&tok_it, tree, Token.Id.Ampersand)) |ampersand| {
2221 const node = try arena.create(ast.Node.InfixOp);2241 const node = try arena.create(ast.Node.InfixOp);
2222 node.* = ast.Node.InfixOp{2242 node.* = ast.Node.InfixOp{
2223 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2243 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
...@@ -2242,7 +2262,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2242,7 +2262,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2242 State.BitShiftExpressionEnd => |opt_ctx| {2262 State.BitShiftExpressionEnd => |opt_ctx| {
2243 const lhs = opt_ctx.get() orelse continue;2263 const lhs = opt_ctx.get() orelse continue;
22442264
2245 const token = nextToken(&tok_it, &tree);2265 const token = nextToken(&tok_it, tree);
2246 const token_index = token.index;2266 const token_index = token.index;
2247 const token_ptr = token.ptr;2267 const token_ptr = token.ptr;
2248 if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {2268 if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {
...@@ -2259,7 +2279,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2259,7 +2279,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2259 try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2279 try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
2260 continue;2280 continue;
2261 } else {2281 } else {
2262 prevToken(&tok_it, &tree);2282 prevToken(&tok_it, tree);
2263 continue;2283 continue;
2264 }2284 }
2265 },2285 },
...@@ -2273,7 +2293,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2273,7 +2293,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2273 State.AdditionExpressionEnd => |opt_ctx| {2293 State.AdditionExpressionEnd => |opt_ctx| {
2274 const lhs = opt_ctx.get() orelse continue;2294 const lhs = opt_ctx.get() orelse continue;
22752295
2276 const token = nextToken(&tok_it, &tree);2296 const token = nextToken(&tok_it, tree);
2277 const token_index = token.index;2297 const token_index = token.index;
2278 const token_ptr = token.ptr;2298 const token_ptr = token.ptr;
2279 if (tokenIdToAddition(token_ptr.id)) |add_id| {2299 if (tokenIdToAddition(token_ptr.id)) |add_id| {
...@@ -2290,7 +2310,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2290,7 +2310,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2290 try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2310 try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
2291 continue;2311 continue;
2292 } else {2312 } else {
2293 prevToken(&tok_it, &tree);2313 prevToken(&tok_it, tree);
2294 continue;2314 continue;
2295 }2315 }
2296 },2316 },
...@@ -2304,7 +2324,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2304,7 +2324,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2304 State.MultiplyExpressionEnd => |opt_ctx| {2324 State.MultiplyExpressionEnd => |opt_ctx| {
2305 const lhs = opt_ctx.get() orelse continue;2325 const lhs = opt_ctx.get() orelse continue;
23062326
2307 const token = nextToken(&tok_it, &tree);2327 const token = nextToken(&tok_it, tree);
2308 const token_index = token.index;2328 const token_index = token.index;
2309 const token_ptr = token.ptr;2329 const token_ptr = token.ptr;
2310 if (tokenIdToMultiply(token_ptr.id)) |mult_id| {2330 if (tokenIdToMultiply(token_ptr.id)) |mult_id| {
...@@ -2321,7 +2341,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2321,7 +2341,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2321 try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2341 try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
2322 continue;2342 continue;
2323 } else {2343 } else {
2324 prevToken(&tok_it, &tree);2344 prevToken(&tok_it, tree);
2325 continue;2345 continue;
2326 }2346 }
2327 },2347 },
...@@ -2386,7 +2406,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2386,7 +2406,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2386 State.TypeExprEnd => |opt_ctx| {2406 State.TypeExprEnd => |opt_ctx| {
2387 const lhs = opt_ctx.get() orelse continue;2407 const lhs = opt_ctx.get() orelse continue;
23882408
2389 if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| {2409 if (eatToken(&tok_it, tree, Token.Id.Bang)) |bang| {
2390 const node = try arena.create(ast.Node.InfixOp);2410 const node = try arena.create(ast.Node.InfixOp);
2391 node.* = ast.Node.InfixOp{2411 node.* = ast.Node.InfixOp{
2392 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2412 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
...@@ -2403,7 +2423,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2403,7 +2423,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2403 },2423 },
24042424
2405 State.PrefixOpExpression => |opt_ctx| {2425 State.PrefixOpExpression => |opt_ctx| {
2406 const token = nextToken(&tok_it, &tree);2426 const token = nextToken(&tok_it, tree);
2407 const token_index = token.index;2427 const token_index = token.index;
2408 const token_ptr = token.ptr;2428 const token_ptr = token.ptr;
2409 if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {2429 if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {
...@@ -2435,14 +2455,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2435,14 +2455,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2435 }2455 }
2436 continue;2456 continue;
2437 } else {2457 } else {
2438 prevToken(&tok_it, &tree);2458 prevToken(&tok_it, tree);
2439 stack.append(State{ .SuffixOpExpressionBegin = opt_ctx }) catch unreachable;2459 stack.append(State{ .SuffixOpExpressionBegin = opt_ctx }) catch unreachable;
2440 continue;2460 continue;
2441 }2461 }
2442 },2462 },
24432463
2444 State.SuffixOpExpressionBegin => |opt_ctx| {2464 State.SuffixOpExpressionBegin => |opt_ctx| {
2445 if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| {2465 if (eatToken(&tok_it, tree, Token.Id.Keyword_async)) |async_token| {
2446 const async_node = try arena.create(ast.Node.AsyncAttribute);2466 const async_node = try arena.create(ast.Node.AsyncAttribute);
2447 async_node.* = ast.Node.AsyncAttribute{2467 async_node.* = ast.Node.AsyncAttribute{
2448 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },2468 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
...@@ -2470,7 +2490,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2470,7 +2490,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2470 State.SuffixOpExpressionEnd => |opt_ctx| {2490 State.SuffixOpExpressionEnd => |opt_ctx| {
2471 const lhs = opt_ctx.get() orelse continue;2491 const lhs = opt_ctx.get() orelse continue;
24722492
2473 const token = nextToken(&tok_it, &tree);2493 const token = nextToken(&tok_it, tree);
2474 const token_index = token.index;2494 const token_index = token.index;
2475 const token_ptr = token.ptr;2495 const token_ptr = token.ptr;
2476 switch (token_ptr.id) {2496 switch (token_ptr.id) {
...@@ -2515,7 +2535,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2515,7 +2535,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2515 continue;2535 continue;
2516 },2536 },
2517 Token.Id.Period => {2537 Token.Id.Period => {
2518 if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| {2538 if (eatToken(&tok_it, tree, Token.Id.Asterisk)) |asterisk_token| {
2519 const node = try arena.create(ast.Node.SuffixOp);2539 const node = try arena.create(ast.Node.SuffixOp);
2520 node.* = ast.Node.SuffixOp{2540 node.* = ast.Node.SuffixOp{
2521 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2541 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
...@@ -2527,7 +2547,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2527,7 +2547,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2527 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2547 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2528 continue;2548 continue;
2529 }2549 }
2530 if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| {2550 if (eatToken(&tok_it, tree, Token.Id.QuestionMark)) |question_token| {
2531 const node = try arena.create(ast.Node.SuffixOp);2551 const node = try arena.create(ast.Node.SuffixOp);
2532 node.* = ast.Node.SuffixOp{2552 node.* = ast.Node.SuffixOp{
2533 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2553 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
...@@ -2554,21 +2574,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2554,21 +2574,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2554 continue;2574 continue;
2555 },2575 },
2556 else => {2576 else => {
2557 prevToken(&tok_it, &tree);2577 prevToken(&tok_it, tree);
2558 continue;2578 continue;
2559 },2579 },
2560 }2580 }
2561 },2581 },
25622582
2563 State.PrimaryExpression => |opt_ctx| {2583 State.PrimaryExpression => |opt_ctx| {
2564 const token = nextToken(&tok_it, &tree);2584 const token = nextToken(&tok_it, tree);
2565 switch (token.ptr.id) {2585 switch (token.ptr.id) {
2566 Token.Id.IntegerLiteral => {2586 Token.Id.IntegerLiteral => {
2567 _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.IntegerLiteral, token.index);2587 _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.IntegerLiteral, token.index);
2568 continue;2588 continue;
2569 },2589 },
2570 Token.Id.Period => {2590 Token.Id.Period => {
2571 const name_token = nextToken(&tok_it, &tree);2591 const name_token = nextToken(&tok_it, tree);
2572 if (name_token.ptr.id != Token.Id.Identifier) {2592 if (name_token.ptr.id != Token.Id.Identifier) {
2573 ((try tree.errors.addOne())).* = Error{2593 ((try tree.errors.addOne())).* = Error{
2574 .ExpectedToken = Error.ExpectedToken{2594 .ExpectedToken = Error.ExpectedToken{
...@@ -2624,11 +2644,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2624,11 +2644,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2624 .result = null,2644 .result = null,
2625 };2645 };
2626 opt_ctx.store(&node.base);2646 opt_ctx.store(&node.base);
2627 const next_token = nextToken(&tok_it, &tree);2647 const next_token = nextToken(&tok_it, tree);
2628 const next_token_index = next_token.index;2648 const next_token_index = next_token.index;
2629 const next_token_ptr = next_token.ptr;2649 const next_token_ptr = next_token.ptr;
2630 if (next_token_ptr.id != Token.Id.Arrow) {2650 if (next_token_ptr.id != Token.Id.Arrow) {
2631 prevToken(&tok_it, &tree);2651 prevToken(&tok_it, tree);
2632 continue;2652 continue;
2633 }2653 }
2634 node.result = ast.Node.PromiseType.Result{2654 node.result = ast.Node.PromiseType.Result{
...@@ -2640,7 +2660,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2640,7 +2660,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2640 continue;2660 continue;
2641 },2661 },
2642 Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {2662 Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {
2643 opt_ctx.store((try parseStringLiteral(arena, &tok_it, token.ptr, token.index, &tree)) orelse unreachable);2663 opt_ctx.store((try parseStringLiteral(arena, &tok_it, token.ptr, token.index, tree)) orelse unreachable);
2644 continue;2664 continue;
2645 },2665 },
2646 Token.Id.LParen => {2666 Token.Id.LParen => {
...@@ -2728,7 +2748,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2728,7 +2748,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2728 continue;2748 continue;
2729 },2749 },
2730 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {2750 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
2731 prevToken(&tok_it, &tree);2751 prevToken(&tok_it, tree);
2732 stack.append(State{2752 stack.append(State{
2733 .ContainerKind = ContainerKindCtx{2753 .ContainerKind = ContainerKindCtx{
2734 .opt_ctx = opt_ctx,2754 .opt_ctx = opt_ctx,
...@@ -2845,7 +2865,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2845,7 +2865,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2845 },2865 },
2846 else => {2866 else => {
2847 if (!try parseBlockExpr(&stack, arena, opt_ctx, token.ptr.*, token.index)) {2867 if (!try parseBlockExpr(&stack, arena, opt_ctx, token.ptr.*, token.index)) {
2848 prevToken(&tok_it, &tree);2868 prevToken(&tok_it, tree);
2849 if (opt_ctx != OptionalCtx.Optional) {2869 if (opt_ctx != OptionalCtx.Optional) {
2850 ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token.index } };2870 ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token.index } };
2851 return tree;2871 return tree;
...@@ -2857,7 +2877,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2857,7 +2877,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2857 },2877 },
28582878
2859 State.ErrorTypeOrSetDecl => |ctx| {2879 State.ErrorTypeOrSetDecl => |ctx| {
2860 if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) {2880 if (eatToken(&tok_it, tree, Token.Id.LBrace) == null) {
2861 const node = try arena.create(ast.Node.InfixOp);2881 const node = try arena.create(ast.Node.InfixOp);
2862 node.* = ast.Node.InfixOp{2882 node.* = ast.Node.InfixOp{
2863 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2883 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
...@@ -2895,11 +2915,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2895,11 +2915,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2895 continue;2915 continue;
2896 },2916 },
2897 State.StringLiteral => |opt_ctx| {2917 State.StringLiteral => |opt_ctx| {
2898 const token = nextToken(&tok_it, &tree);2918 const token = nextToken(&tok_it, tree);
2899 const token_index = token.index;2919 const token_index = token.index;
2900 const token_ptr = token.ptr;2920 const token_ptr = token.ptr;
2901 opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) orelse {2921 opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, tree)) orelse {
2902 prevToken(&tok_it, &tree);2922 prevToken(&tok_it, tree);
2903 if (opt_ctx != OptionalCtx.Optional) {2923 if (opt_ctx != OptionalCtx.Optional) {
2904 ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token_index } };2924 ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token_index } };
2905 return tree;2925 return tree;
...@@ -2910,13 +2930,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2910,13 +2930,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2910 },2930 },
29112931
2912 State.Identifier => |opt_ctx| {2932 State.Identifier => |opt_ctx| {
2913 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |ident_token| {2933 if (eatToken(&tok_it, tree, Token.Id.Identifier)) |ident_token| {
2914 _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.Identifier, ident_token);2934 _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.Identifier, ident_token);
2915 continue;2935 continue;
2916 }2936 }
29172937
2918 if (opt_ctx != OptionalCtx.Optional) {2938 if (opt_ctx != OptionalCtx.Optional) {
2919 const token = nextToken(&tok_it, &tree);2939 const token = nextToken(&tok_it, tree);
2920 const token_index = token.index;2940 const token_index = token.index;
2921 const token_ptr = token.ptr;2941 const token_ptr = token.ptr;
2922 ((try tree.errors.addOne())).* = Error{2942 ((try tree.errors.addOne())).* = Error{
...@@ -2930,8 +2950,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2930,8 +2950,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2930 },2950 },
29312951
2932 State.ErrorTag => |node_ptr| {2952 State.ErrorTag => |node_ptr| {
2933 const comments = try eatDocComments(arena, &tok_it, &tree);2953 const comments = try eatDocComments(arena, &tok_it, tree);
2934 const ident_token = nextToken(&tok_it, &tree);2954 const ident_token = nextToken(&tok_it, tree);
2935 const ident_token_index = ident_token.index;2955 const ident_token_index = ident_token.index;
2936 const ident_token_ptr = ident_token.ptr;2956 const ident_token_ptr = ident_token.ptr;
2937 if (ident_token_ptr.id != Token.Id.Identifier) {2957 if (ident_token_ptr.id != Token.Id.Identifier) {
...@@ -2955,7 +2975,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2955,7 +2975,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2955 },2975 },
29562976
2957 State.ExpectToken => |token_id| {2977 State.ExpectToken => |token_id| {
2958 const token = nextToken(&tok_it, &tree);2978 const token = nextToken(&tok_it, tree);
2959 const token_index = token.index;2979 const token_index = token.index;
2960 const token_ptr = token.ptr;2980 const token_ptr = token.ptr;
2961 if (token_ptr.id != token_id) {2981 if (token_ptr.id != token_id) {
...@@ -2970,7 +2990,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2970,7 +2990,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2970 continue;2990 continue;
2971 },2991 },
2972 State.ExpectTokenSave => |expect_token_save| {2992 State.ExpectTokenSave => |expect_token_save| {
2973 const token = nextToken(&tok_it, &tree);2993 const token = nextToken(&tok_it, tree);
2974 const token_index = token.index;2994 const token_index = token.index;
2975 const token_ptr = token.ptr;2995 const token_ptr = token.ptr;
2976 if (token_ptr.id != expect_token_save.id) {2996 if (token_ptr.id != expect_token_save.id) {
...@@ -2986,7 +3006,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2986,7 +3006,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2986 continue;3006 continue;
2987 },3007 },
2988 State.IfToken => |token_id| {3008 State.IfToken => |token_id| {
2989 if (eatToken(&tok_it, &tree, token_id)) |_| {3009 if (eatToken(&tok_it, tree, token_id)) |_| {
2990 continue;3010 continue;
2991 }3011 }
29923012
...@@ -2994,7 +3014,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2994,7 +3014,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2994 continue;3014 continue;
2995 },3015 },
2996 State.IfTokenSave => |if_token_save| {3016 State.IfTokenSave => |if_token_save| {
2997 if (eatToken(&tok_it, &tree, if_token_save.id)) |token_index| {3017 if (eatToken(&tok_it, tree, if_token_save.id)) |token_index| {
2998 (if_token_save.ptr).* = token_index;3018 (if_token_save.ptr).* = token_index;
2999 continue;3019 continue;
3000 }3020 }
...@@ -3003,7 +3023,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -3003,7 +3023,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
3003 continue;3023 continue;
3004 },3024 },
3005 State.OptionalTokenSave => |optional_token_save| {3025 State.OptionalTokenSave => |optional_token_save| {
3006 if (eatToken(&tok_it, &tree, optional_token_save.id)) |token_index| {3026 if (eatToken(&tok_it, tree, optional_token_save.id)) |token_index| {
3007 (optional_token_save.ptr).* = token_index;3027 (optional_token_save.ptr).* = token_index;
3008 continue;3028 continue;
3009 }3029 }
std/zig/parser_test.zig+18-18
...@@ -1,10 +1,3 @@...@@ -1,10 +1,3 @@
1test "temporary trivial example" {
2 try testCanonical(
3 \\const x = true;
4 \\
5 );
6}
7
8test "zig fmt: allowzero pointer" {1test "zig fmt: allowzero pointer" {
9 try testCanonical(2 try testCanonical(
10 \\const T = [*]allowzero const u8;3 \\const T = [*]allowzero const u8;
...@@ -57,14 +50,6 @@ test "zig fmt: linksection" {...@@ -57,14 +50,6 @@ test "zig fmt: linksection" {
57 );50 );
58}51}
5952
60test "zig fmt: shebang line" {
61 try testCanonical(
62 \\#!/usr/bin/env zig
63 \\pub fn main() void {}
64 \\
65 );
66}
67
68test "zig fmt: correctly move doc comments on struct fields" {53test "zig fmt: correctly move doc comments on struct fields" {
69 try testTransform(54 try testTransform(
70 \\pub const section_64 = extern struct {55 \\pub const section_64 = extern struct {
...@@ -2125,6 +2110,21 @@ test "zig fmt: error return" {...@@ -2125,6 +2110,21 @@ test "zig fmt: error return" {
2125 );2110 );
2126}2111}
21272112
2113test "zig fmt: comptime block in container" {
2114 try testCanonical(
2115 \\pub fn container() type {
2116 \\ return struct {
2117 \\ comptime {
2118 \\ if (false) {
2119 \\ unreachable;
2120 \\ }
2121 \\ }
2122 \\ };
2123 \\}
2124 \\
2125 );
2126}
2127
2128const std = @import("std");2128const std = @import("std");
2129const mem = std.mem;2129const mem = std.mem;
2130const warn = std.debug.warn;2130const warn = std.debug.warn;
...@@ -2137,7 +2137,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b...@@ -2137,7 +2137,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
2137 var stderr_file = try io.getStdErr();2137 var stderr_file = try io.getStdErr();
2138 var stderr = &stderr_file.outStream().stream;2138 var stderr = &stderr_file.outStream().stream;
21392139
2140 var tree = try std.zig.parse2(allocator, source);2140 const tree = try std.zig.parse(allocator, source);
2141 defer tree.deinit();2141 defer tree.deinit();
21422142
2143 var error_it = tree.errors.iterator(0);2143 var error_it = tree.errors.iterator(0);
...@@ -2170,7 +2170,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b...@@ -2170,7 +2170,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
2170 errdefer buffer.deinit();2170 errdefer buffer.deinit();
21712171
2172 var buffer_out_stream = io.BufferOutStream.init(&buffer);2172 var buffer_out_stream = io.BufferOutStream.init(&buffer);
2173 anything_changed.* = try std.zig.render(allocator, &buffer_out_stream.stream, &tree);2173 anything_changed.* = try std.zig.render(allocator, &buffer_out_stream.stream, tree);
2174 return buffer.toOwnedSlice();2174 return buffer.toOwnedSlice();
2175}2175}
21762176
...@@ -2215,7 +2215,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {...@@ -2215,7 +2215,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
2215 needed_alloc_count,2215 needed_alloc_count,
2216 failing_allocator.allocated_bytes,2216 failing_allocator.allocated_bytes,
2217 failing_allocator.freed_bytes,2217 failing_allocator.freed_bytes,
2218 failing_allocator.index,2218 failing_allocator.allocations,
2219 failing_allocator.deallocations,2219 failing_allocator.deallocations,
2220 );2220 );
2221 return error.MemoryLeakDetected;2221 return error.MemoryLeakDetected;
std/zig/render.zig+1-6
...@@ -73,11 +73,6 @@ fn renderRoot(...@@ -73,11 +73,6 @@ fn renderRoot(
73) (@typeOf(stream).Child.Error || Error)!void {73) (@typeOf(stream).Child.Error || Error)!void {
74 var tok_it = tree.tokens.iterator(0);74 var tok_it = tree.tokens.iterator(0);
7575
76 // render the shebang line
77 if (tree.root_node.shebang) |shebang| {
78 try stream.write(tree.tokenSlice(shebang));
79 }
80
81 // render all the line comments at the beginning of the file76 // render all the line comments at the beginning of the file
82 while (tok_it.next()) |token| {77 while (tok_it.next()) |token| {
83 if (token.id != Token.Id.LineComment) break;78 if (token.id != Token.Id.LineComment) break;
...@@ -753,7 +748,7 @@ fn renderExpression(...@@ -753,7 +748,7 @@ fn renderExpression(
753 counting_stream.bytes_written = 0;748 counting_stream.bytes_written = 0;
754 var dummy_col: usize = 0;749 var dummy_col: usize = 0;
755 try renderExpression(allocator, &counting_stream.stream, tree, 0, &dummy_col, expr.*, Space.None);750 try renderExpression(allocator, &counting_stream.stream, tree, 0, &dummy_col, expr.*, Space.None);
756 const width = counting_stream.bytes_written;751 const width = @intCast(usize, counting_stream.bytes_written);
757 const col = i % row_size;752 const col = i % row_size;
758 column_widths[col] = std.math.max(column_widths[col], width);753 column_widths[col] = std.math.max(column_widths[col], width);
759 expr_widths[i] = width;754 expr_widths[i] = width;
test/compile_errors.zig+80-33
...@@ -2,6 +2,64 @@ const tests = @import("tests.zig");...@@ -2,6 +2,64 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "peer cast then implicit cast const pointer to mutable C pointer",
7 \\export fn func() void {
8 \\ var strValue: [*c]u8 = undefined;
9 \\ strValue = strValue orelse c"";
10 \\}
11 ,
12 "tmp.zig:3:32: error: cast discards const qualifier",
13 );
14
15 cases.add(
16 "overflow in enum value allocation",
17 \\const Moo = enum(u8) {
18 \\ Last = 255,
19 \\ Over,
20 \\};
21 \\pub fn main() void {
22 \\ var y = Moo.Last;
23 \\}
24 ,
25 "tmp.zig:3:5: error: enumeration value 256 too large for type 'u8'",
26 );
27
28 cases.add(
29 "attempt to cast enum literal to error",
30 \\export fn entry() void {
31 \\ switch (error.Hi) {
32 \\ .Hi => {},
33 \\ }
34 \\}
35 ,
36 "tmp.zig:3:9: error: expected type 'error{Hi}', found '(enum literal)'",
37 );
38
39 cases.add(
40 "@sizeOf bad type",
41 \\export fn entry() void {
42 \\ _ = @sizeOf(@typeOf(null));
43 \\}
44 ,
45 "tmp.zig:2:17: error: no size available for type '(null)'",
46 );
47
48 cases.add(
49 "Generic function where return type is self-referenced",
50 \\fn Foo(comptime T: type) Foo(T) {
51 \\ return struct{ x: T };
52 \\}
53 \\export fn entry() void {
54 \\ const t = Foo(u32) {
55 \\ .x = 1
56 \\ };
57 \\}
58 ,
59 "tmp.zig:1:29: error: evaluation exceeded 1000 backwards branches",
60 "tmp.zig:1:29: note: called from here",
61 );
62
5 cases.add(63 cases.add(
6 "@ptrToInt 0 to non optional pointer",64 "@ptrToInt 0 to non optional pointer",
7 \\export fn entry() void {65 \\export fn entry() void {
...@@ -552,15 +610,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -552,15 +610,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
552 "tmp.zig:1:13: error: threadlocal variable cannot be constant",610 "tmp.zig:1:13: error: threadlocal variable cannot be constant",
553 );611 );
554612
555 cases.add(
556 "threadlocal qualifier on local variable",
557 \\export fn entry() void {
558 \\ threadlocal var x: i32 = 1234;
559 \\}
560 ,
561 "tmp.zig:2:5: error: function-local variable 'x' cannot be threadlocal",
562 );
563
564 cases.add(613 cases.add(
565 "@bitCast same size but bit count mismatch",614 "@bitCast same size but bit count mismatch",
566 \\export fn entry(byte: u8) void {615 \\export fn entry(byte: u8) void {
...@@ -839,7 +888,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -839,7 +888,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
839 \\ _ = &x == null;888 \\ _ = &x == null;
840 \\}889 \\}
841 ,890 ,
842 "tmp.zig:3:12: error: only optionals (not '*i32') can compare to null",891 "tmp.zig:3:12: error: comparison of '*i32' with null",
843 );892 );
844893
845 cases.add(894 cases.add(
...@@ -5347,8 +5396,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5347,8 +5396,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5347 "tmp.zig:12:20: note: referenced here",5396 "tmp.zig:12:20: note: referenced here",
5348 );5397 );
53495398
5350 cases.add(5399 cases.add("specify enum tag type that is too small",
5351 "specify enum tag type that is too small",
5352 \\const Small = enum (u2) {5400 \\const Small = enum (u2) {
5353 \\ One,5401 \\ One,
5354 \\ Two,5402 \\ Two,
...@@ -5360,9 +5408,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5360,9 +5408,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5360 \\export fn entry() void {5408 \\export fn entry() void {
5361 \\ var x = Small.One;5409 \\ var x = Small.One;
5362 \\}5410 \\}
5363 ,5411 , "tmp.zig:6:5: error: enumeration value 4 too large for type 'u2'");
5364 "tmp.zig:1:21: error: 'u2' too small to hold all bits; must be at least 'u3'",
5365 );
53665412
5367 cases.add(5413 cases.add(
5368 "specify non-integer enum tag type",5414 "specify non-integer enum tag type",
...@@ -5412,22 +5458,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5412,22 +5458,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5412 "tmp.zig:10:31: error: expected type 'u2', found 'u3'",5458 "tmp.zig:10:31: error: expected type 'u2', found 'u3'",
5413 );5459 );
54145460
5415 cases.add(
5416 "non unsigned integer enum tag type",
5417 \\const Small = enum(i2) {
5418 \\ One,
5419 \\ Two,
5420 \\ Three,
5421 \\ Four,
5422 \\};
5423 \\
5424 \\export fn entry() void {
5425 \\ var y = Small.Two;
5426 \\}
5427 ,
5428 "tmp.zig:1:20: error: expected unsigned integer, found 'i2'",
5429 );
5430
5431 cases.add(5461 cases.add(
5432 "struct fields with value assignments",5462 "struct fields with value assignments",
5433 \\const MultipleChoice = struct {5463 \\const MultipleChoice = struct {
...@@ -5486,8 +5516,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5486,8 +5516,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5486 \\ var x = MultipleChoice.C;5516 \\ var x = MultipleChoice.C;
5487 \\}5517 \\}
5488 ,5518 ,
5489 "tmp.zig:6:9: error: enum tag value 60 already taken",5519 "tmp.zig:6:5: error: enum tag value 60 already taken",
5490 "tmp.zig:4:9: note: other occurrence here",5520 "tmp.zig:4:5: note: other occurrence here",
5491 );5521 );
54925522
5493 cases.add(5523 cases.add(
...@@ -5892,4 +5922,21 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5892,4 +5922,21 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5892 ,5922 ,
5893 "tmp.zig:3:23: error: expected type '[]u32', found '*const u32'",5923 "tmp.zig:3:23: error: expected type '[]u32', found '*const u32'",
5894 );5924 );
5925
5926 cases.add(
5927 "for loop body expression ignored",
5928 \\fn returns() usize {
5929 \\ return 2;
5930 \\}
5931 \\export fn f1() void {
5932 \\ for ("hello") |_| returns();
5933 \\}
5934 \\export fn f2() void {
5935 \\ var x: anyerror!i32 = error.Bad;
5936 \\ for ("hello") |_| returns() else unreachable;
5937 \\}
5938 ,
5939 "tmp.zig:5:30: error: expression value is ignored",
5940 "tmp.zig:9:30: error: expression value is ignored",
5941 );
5895}5942}
test/runtime_safety.zig+20
...@@ -1,6 +1,26 @@...@@ -1,6 +1,26 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompareOutputContext) void {3pub fn addCases(cases: *tests.CompareOutputContext) void {
4 cases.addRuntimeSafety(".? operator on null pointer",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);
7 \\}
8 \\pub fn main() void {
9 \\ var ptr: ?*i32 = null;
10 \\ var b = ptr.?;
11 \\}
12 );
13
14 cases.addRuntimeSafety(".? operator on C pointer",
15 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
16 \\ @import("std").os.exit(126);
17 \\}
18 \\pub fn main() void {
19 \\ var ptr: [*c]i32 = null;
20 \\ var b = ptr.?;
21 \\}
22 );
23
4 cases.addRuntimeSafety("@ptrToInt address zero to non-optional pointer",24 cases.addRuntimeSafety("@ptrToInt address zero to non-optional pointer",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {25 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);26 \\ @import("std").os.exit(126);
test/stage1/behavior.zig+3
...@@ -20,9 +20,12 @@ comptime {...@@ -20,9 +20,12 @@ comptime {
20 _ = @import("behavior/bugs/1442.zig");20 _ = @import("behavior/bugs/1442.zig");
21 _ = @import("behavior/bugs/1486.zig");21 _ = @import("behavior/bugs/1486.zig");
22 _ = @import("behavior/bugs/1500.zig");22 _ = @import("behavior/bugs/1500.zig");
23 _ = @import("behavior/bugs/1607.zig");
23 _ = @import("behavior/bugs/1851.zig");24 _ = @import("behavior/bugs/1851.zig");
24 _ = @import("behavior/bugs/1914.zig");25 _ = @import("behavior/bugs/1914.zig");
25 _ = @import("behavior/bugs/2006.zig");26 _ = @import("behavior/bugs/2006.zig");
27 _ = @import("behavior/bugs/2114.zig");
28 _ = @import("behavior/bugs/2346.zig");
26 _ = @import("behavior/bugs/394.zig");29 _ = @import("behavior/bugs/394.zig");
27 _ = @import("behavior/bugs/421.zig");30 _ = @import("behavior/bugs/421.zig");
28 _ = @import("behavior/bugs/529.zig");31 _ = @import("behavior/bugs/529.zig");
test/stage1/behavior/bit_shifting.zig+10
...@@ -86,3 +86,13 @@ fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, c...@@ -86,3 +86,13 @@ fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, c
86 expect(table.get(@intCast(Key, i)) == node);86 expect(table.get(@intCast(Key, i)) == node);
87 }87 }
88}88}
89
90// #2225
91test "comptime shr of BigInt" {
92 comptime {
93 var n0 = 0xdeadbeef0000000000000000;
94 std.debug.assert(n0 >> 64 == 0xdeadbeef);
95 var n1 = 17908056155735594659;
96 std.debug.assert(n1 >> 64 == 0);
97 }
98}
test/stage1/behavior/bugs/1607.zig created+15
...@@ -0,0 +1,15 @@
1const std = @import("std");
2const testing = std.testing;
3
4const a = []u8{ 1, 2, 3 };
5
6fn checkAddress(s: []const u8) void {
7 for (s) |*i, j| {
8 testing.expect(i == &a[j]);
9 }
10}
11
12test "slices pointing at the same address as global array." {
13 checkAddress(a);
14 comptime checkAddress(a);
15}
test/stage1/behavior/bugs/2114.zig created+19
...@@ -0,0 +1,19 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const math = std.math;
4
5fn ctz(x: var) usize {
6 return @ctz(x);
7}
8
9test "fixed" {
10 testClz();
11 comptime testClz();
12}
13
14fn testClz() void {
15 expect(ctz(u128(0x40000000000000000000000000000000)) == 126);
16 expect(math.rotl(u128, u128(0x40000000000000000000000000000000), u8(1)) == u128(0x80000000000000000000000000000000));
17 expect(ctz(u128(0x80000000000000000000000000000000)) == 127);
18 expect(ctz(math.rotl(u128, u128(0x40000000000000000000000000000000), u8(1))) == 127);
19}
test/stage1/behavior/bugs/2346.zig created+6
...@@ -0,0 +1,6 @@
1test "fixed" {
2 const a: *void = undefined;
3 const b: *[1]void = a;
4 const c: *[0]u8 = undefined;
5 const d: []u8 = c;
6}
test/stage1/behavior/enum.zig+39
...@@ -923,3 +923,42 @@ test "peer type resolution with enum literal" {...@@ -923,3 +923,42 @@ test "peer type resolution with enum literal" {
923 expect(Items.two == .two);923 expect(Items.two == .two);
924 expect(.two == Items.two);924 expect(.two == Items.two);
925}925}
926
927test "enum literal in array literal" {
928 const Items = enum {
929 one,
930 two,
931 };
932
933 const array = []Items {
934 .one,
935 .two,
936 };
937
938 expect(array[0] == .one);
939 expect(array[1] == .two);
940}
941
942test "signed integer as enum tag" {
943 const SignedEnum = enum(i2) {
944 A0 = -1,
945 A1 = 0,
946 A2 = 1,
947 };
948
949 expect(@enumToInt(SignedEnum.A0) == -1);
950 expect(@enumToInt(SignedEnum.A1) == 0);
951 expect(@enumToInt(SignedEnum.A2) == 1);
952}
953
954test "enum value allocation" {
955 const LargeEnum = enum(u32) {
956 A0 = 0x80000000,
957 A1,
958 A2,
959 };
960
961 expect(@enumToInt(LargeEnum.A0) == 0x80000000);
962 expect(@enumToInt(LargeEnum.A1) == 0x80000001);
963 expect(@enumToInt(LargeEnum.A2) == 0x80000002);
964}
test/stage1/behavior/math.zig+7
...@@ -632,3 +632,10 @@ fn testNanEqNan(comptime F: type) void {...@@ -632,3 +632,10 @@ fn testNanEqNan(comptime F: type) void {
632 expect(!(nan1 < nan2));632 expect(!(nan1 < nan2));
633 expect(!(nan1 <= nan2));633 expect(!(nan1 <= nan2));
634}634}
635
636test "128-bit multiplication" {
637 var a: i128 = 3;
638 var b: i128 = 2;
639 var c = a * b;
640 expect(c == 6);
641}
test/stage1/behavior/pointers.zig+50
...@@ -150,3 +150,53 @@ test "allowzero pointer and slice" {...@@ -150,3 +150,53 @@ test "allowzero pointer and slice" {
150 expect(@typeInfo(@typeOf(ptr)).Pointer.is_allowzero);150 expect(@typeInfo(@typeOf(ptr)).Pointer.is_allowzero);
151 expect(@typeInfo(@typeOf(slice)).Pointer.is_allowzero);151 expect(@typeInfo(@typeOf(slice)).Pointer.is_allowzero);
152}152}
153
154test "assign null directly to C pointer and test null equality" {
155 var x: [*c]i32 = null;
156 expect(x == null);
157 expect(null == x);
158 expect(!(x != null));
159 expect(!(null != x));
160 if (x) |same_x| {
161 @panic("fail");
162 }
163 var otherx: i32 = undefined;
164 expect((x orelse &otherx) == &otherx);
165
166 const y: [*c]i32 = null;
167 comptime expect(y == null);
168 comptime expect(null == y);
169 comptime expect(!(y != null));
170 comptime expect(!(null != y));
171 if (y) |same_y| @panic("fail");
172 const othery: i32 = undefined;
173 comptime expect((y orelse &othery) == &othery);
174
175 var n: i32 = 1234;
176 var x1: [*c]i32 = &n;
177 expect(!(x1 == null));
178 expect(!(null == x1));
179 expect(x1 != null);
180 expect(null != x1);
181 expect(x1.?.* == 1234);
182 if (x1) |same_x1| {
183 expect(same_x1.* == 1234);
184 } else {
185 @panic("fail");
186 }
187 expect((x1 orelse &otherx) == x1);
188
189 const nc: i32 = 1234;
190 const y1: [*c]const i32 = &nc;
191 comptime expect(!(y1 == null));
192 comptime expect(!(null == y1));
193 comptime expect(y1 != null);
194 comptime expect(null != y1);
195 comptime expect(y1.?.* == 1234);
196 if (y1) |same_y1| {
197 expect(same_y1.* == 1234);
198 } else {
199 @compileError("fail");
200 }
201 comptime expect((y1 orelse &othery) == y1);
202}
test/stage1/behavior/sizeof_and_typeof.zig+7
...@@ -67,3 +67,10 @@ test "@bitOffsetOf" {...@@ -67,3 +67,10 @@ test "@bitOffsetOf" {
67 expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));67 expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
68 expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));68 expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
69}69}
70
71test "@sizeOf on compile-time types" {
72 expect(@sizeOf(comptime_int) == 0);
73 expect(@sizeOf(comptime_float) == 0);
74 expect(@sizeOf(@typeOf(.hi)) == 0);
75 expect(@sizeOf(@typeOf(type)) == 0);
76}
test/stage1/behavior/struct.zig+20-2
...@@ -2,8 +2,7 @@ const std = @import("std");...@@ -2,8 +2,7 @@ const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;3const expectEqualSlices = std.testing.expectEqualSlices;
4const builtin = @import("builtin");4const builtin = @import("builtin");
5const maxInt = std.math.maxInt;5const maxInt = std.math.maxInt;
6
7const StructWithNoFields = struct {6const StructWithNoFields = struct {
8 fn add(a: i32, b: i32) i32 {7 fn add(a: i32, b: i32) i32 {
9 return a + b;8 return a + b;
...@@ -505,3 +504,22 @@ test "packed struct with u0 field access" {...@@ -505,3 +504,22 @@ test "packed struct with u0 field access" {
505 var s = S{ .f0 = 0 };504 var s = S{ .f0 = 0 };
506 comptime expect(s.f0 == 0);505 comptime expect(s.f0 == 0);
507}506}
507
508const S0 = struct{
509 bar: S1,
510
511 pub const S1 = struct{
512 value: u8,
513 };
514
515 fn init() @This() {
516 return S0{ .bar = S1{ .value = 123 } };
517 }
518};
519
520var g_foo: S0 = S0.init();
521
522test "access to global struct fields" {
523 g_foo.bar.value = 42;
524 expect(g_foo.bar.value == 42);
525}
test/stage1/behavior/syntax.zig+8
...@@ -1,6 +1,14 @@...@@ -1,6 +1,14 @@
1// Test trailing comma syntax1// Test trailing comma syntax
2// zig fmt: off2// zig fmt: off
33
4extern var a: c_int;
5extern "c" var b: c_int;
6export var c: c_int = 0;
7threadlocal var d: c_int;
8extern threadlocal var e: c_int;
9extern "c" threadlocal var f: c_int;
10export threadlocal var g: c_int = 0;
11
4const struct_trailing_comma = struct { x: i32, y: i32, };12const struct_trailing_comma = struct { x: i32, y: i32, };
5const struct_no_comma = struct { x: i32, y: i32 };13const struct_no_comma = struct { x: i32, y: i32 };
6const struct_fn_no_comma = struct { fn m() void {} y: i32 };14const struct_fn_no_comma = struct { fn m() void {} y: i32 };
test/stage1/behavior/union.zig+37
...@@ -365,3 +365,40 @@ test "@enumToInt works on unions" {...@@ -365,3 +365,40 @@ test "@enumToInt works on unions" {
365 expect(@enumToInt(b) == 1);365 expect(@enumToInt(b) == 1);
366 expect(@enumToInt(c) == 2);366 expect(@enumToInt(c) == 2);
367}367}
368
369const Attribute = union(enum) {
370 A: bool,
371 B: u8,
372};
373
374fn setAttribute(attr: Attribute) void {}
375
376fn Setter(attr: Attribute) type {
377 return struct{
378 fn set() void {
379 setAttribute(attr);
380 }
381 };
382}
383
384test "comptime union field value equality" {
385 const a0 = Setter(Attribute{ .A = false });
386 const a1 = Setter(Attribute{ .A = true });
387 const a2 = Setter(Attribute{ .A = false });
388
389 const b0 = Setter(Attribute{ .B = 5 });
390 const b1 = Setter(Attribute{ .B = 9 });
391 const b2 = Setter(Attribute{ .B = 5 });
392
393 expect(a0 == a0);
394 expect(a1 == a1);
395 expect(a0 == a2);
396
397 expect(b0 == b0);
398 expect(b1 == b1);
399 expect(b0 == b2);
400
401 expect(a0 != b0);
402 expect(a0 != a1);
403 expect(b0 != b1);
404}
test/tests.zig+34-2
...@@ -903,6 +903,7 @@ pub const TranslateCContext = struct {...@@ -903,6 +903,7 @@ pub const TranslateCContext = struct {
903 sources: ArrayList(SourceFile),903 sources: ArrayList(SourceFile),
904 expected_lines: ArrayList([]const u8),904 expected_lines: ArrayList([]const u8),
905 allow_warnings: bool,905 allow_warnings: bool,
906 stage2: bool,
906907
907 const SourceFile = struct {908 const SourceFile = struct {
908 filename: []const u8,909 filename: []const u8,
...@@ -955,7 +956,8 @@ pub const TranslateCContext = struct {...@@ -955,7 +956,8 @@ pub const TranslateCContext = struct {
955 var zig_args = ArrayList([]const u8).init(b.allocator);956 var zig_args = ArrayList([]const u8).init(b.allocator);
956 zig_args.append(b.zig_exe) catch unreachable;957 zig_args.append(b.zig_exe) catch unreachable;
957958
958 zig_args.append("translate-c") catch unreachable;959 const translate_c_cmd = if (self.case.stage2) "translate-c-2" else "translate-c";
960 zig_args.append(translate_c_cmd) catch unreachable;
959 zig_args.append(b.pathFromRoot(root_src)) catch unreachable;961 zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
960962
961 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);963 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
...@@ -1052,6 +1054,7 @@ pub const TranslateCContext = struct {...@@ -1052,6 +1054,7 @@ pub const TranslateCContext = struct {
1052 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),1054 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
1053 .expected_lines = ArrayList([]const u8).init(self.b.allocator),1055 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
1054 .allow_warnings = allow_warnings,1056 .allow_warnings = allow_warnings,
1057 .stage2 = false,
1055 };1058 };
10561059
1057 tc.addSourceFile(filename, source);1060 tc.addSourceFile(filename, source);
...@@ -1072,6 +1075,34 @@ pub const TranslateCContext = struct {...@@ -1072,6 +1075,34 @@ pub const TranslateCContext = struct {
1072 self.addCase(tc);1075 self.addCase(tc);
1073 }1076 }
10741077
1078 pub fn add_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1079 for ([]bool{ false, true }) |stage2| {
1080 const tc = self.create(false, "source.h", name, source, expected_lines);
1081 tc.stage2 = stage2;
1082 self.addCase(tc);
1083 }
1084 }
1085
1086 pub fn addC_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1087 for ([]bool{ false, true }) |stage2| {
1088 const tc = self.create(false, "source.c", name, source, expected_lines);
1089 tc.stage2 = stage2;
1090 self.addCase(tc);
1091 }
1092 }
1093
1094 pub fn add_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1095 const tc = self.create(false, "source.h", name, source, expected_lines);
1096 tc.stage2 = true;
1097 self.addCase(tc);
1098 }
1099
1100 pub fn addC_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1101 const tc = self.create(false, "source.c", name, source, expected_lines);
1102 tc.stage2 = true;
1103 self.addCase(tc);
1104 }
1105
1075 pub fn addAllowWarnings(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {1106 pub fn addAllowWarnings(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1076 const tc = self.create(true, "source.h", name, source, expected_lines);1107 const tc = self.create(true, "source.h", name, source, expected_lines);
1077 self.addCase(tc);1108 self.addCase(tc);
...@@ -1080,7 +1111,8 @@ pub const TranslateCContext = struct {...@@ -1080,7 +1111,8 @@ pub const TranslateCContext = struct {
1080 pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {1111 pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
1081 const b = self.b;1112 const b = self.b;
10821113
1083 const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable;1114 const translate_c_cmd = if (case.stage2) "translate-c-2" else "translate-c";
1115 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", translate_c_cmd, case.name) catch unreachable;
1084 if (self.test_filter) |filter| {1116 if (self.test_filter) |filter| {
1085 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;1117 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
1086 }1118 }
test/translate_c.zig+167-48
...@@ -1,7 +1,66 @@...@@ -1,7 +1,66 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4// add_both - test for stage1 and stage2, in #include mode
5// add - test stage1 only, in #include mode
6// add_2 - test stage2 only, in #include mode
7// addC_both - test for stage1 and stage2, in -c mode
8// addC - test stage1 only, in -c mode
9// addC_2 - test stage2 only, in -c mode
10
4pub fn addCases(cases: *tests.TranslateCContext) void {11pub fn addCases(cases: *tests.TranslateCContext) void {
12 /////////////// Cases that pass for both stage1/stage2 ////////////////
13 cases.add_both("simple function prototypes",
14 \\void __attribute__((noreturn)) foo(void);
15 \\int bar(void);
16 ,
17 \\pub extern fn foo() noreturn;
18 \\pub extern fn bar() c_int;
19 );
20
21 /////////////// Cases that pass for only stage2 ////////////////
22 cases.add_2("Parameterless function prototypes",
23 \\void a() {}
24 \\void b(void) {}
25 \\void c();
26 \\void d(void);
27 ,
28 \\pub export fn a() void {}
29 \\pub export fn b() void {}
30 \\pub extern fn c(...) void;
31 \\pub extern fn d() void;
32 );
33
34 cases.add_2("simple function definition",
35 \\void foo(void) {}
36 \\static void bar(void) {}
37 ,
38 \\pub export fn foo() void {}
39 \\pub extern fn bar() void {}
40 );
41
42 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
43
44 cases.add("macro with left shift",
45 \\#define REDISMODULE_READ (1<<0)
46 ,
47 \\pub const REDISMODULE_READ = 1 << 0;
48 );
49
50 cases.add("casting pointers to ints and ints to pointers",
51 \\void foo(void);
52 \\void bar(void) {
53 \\ void *func_ptr = foo;
54 \\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
55 \\}
56 ,
57 \\pub extern fn foo() void;
58 \\pub fn bar() void {
59 \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
60 \\ var typed_func_ptr: ?extern fn() void = @intToPtr(?extern fn() void, c_ulong(@ptrToInt(func_ptr)));
61 \\}
62 );
63
5 if (builtin.os != builtin.Os.windows) {64 if (builtin.os != builtin.Os.windows) {
6 // Windows treats this as an enum with type c_int65 // Windows treats this as an enum with type c_int
7 cases.add("big negative enum init values when C ABI supports long long enums",66 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 {...@@ -72,7 +131,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
72 \\ _ = c"void foo(void)";131 \\ _ = c"void foo(void)";
73 \\}132 \\}
74 );133 );
75 134
76 cases.add("ignore result",135 cases.add("ignore result",
77 \\void foo() {136 \\void foo() {
78 \\ int a;137 \\ int a;
...@@ -648,11 +707,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -648,11 +707,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
648 ,707 ,
649 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {708 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
650 \\ if ((a != 0) and (b != 0)) return 0;709 \\ if ((a != 0) and (b != 0)) return 0;
651 \\ if ((b != 0) and (c != 0)) return 1;710 \\ if ((b != 0) and (c != null)) return 1;
652 \\ if ((a != 0) and (c != 0)) return 2;711 \\ if ((a != 0) and (c != null)) return 2;
653 \\ if ((a != 0) or (b != 0)) return 3;712 \\ if ((a != 0) or (b != 0)) return 3;
654 \\ if ((b != 0) or (c != 0)) return 4;713 \\ if ((b != 0) or (c != null)) return 4;
655 \\ if ((a != 0) or (c != 0)) return 5;714 \\ if ((a != 0) or (c != null)) return 5;
656 \\ return 6;715 \\ return 6;
657 \\}716 \\}
658 );717 );
...@@ -832,7 +891,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -832,7 +891,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
832 \\}891 \\}
833 ,892 ,
834 \\pub export fn foo() [*c]c_int {893 \\pub export fn foo() [*c]c_int {
835 \\ return 0;894 \\ return null;
836 \\}895 \\}
837 );896 );
838897
...@@ -1334,7 +1393,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1334,7 +1393,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1334 \\}1393 \\}
1335 ,1394 ,
1336 \\fn ptrcast(a: [*c]c_int) [*c]f32 {1395 \\fn ptrcast(a: [*c]c_int) [*c]f32 {
1337 \\ return @ptrCast([*c]f32, a);1396 \\ return @ptrCast([*c]f32, @alignCast(@alignOf(f32), a));
1338 \\}1397 \\}
1339 );1398 );
13401399
...@@ -1360,7 +1419,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1360,7 +1419,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1360 \\ return !(a == 0);1419 \\ return !(a == 0);
1361 \\ return !(a != 0);1420 \\ return !(a != 0);
1362 \\ return !(b != 0);1421 \\ return !(b != 0);
1363 \\ return !(c != 0);1422 \\ return !(c != null);
1364 \\}1423 \\}
1365 );1424 );
13661425
...@@ -1417,7 +1476,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1417,7 +1476,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1417 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {1476 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
1418 \\ if (a != 0) return 0;1477 \\ if (a != 0) return 0;
1419 \\ if (b != 0) return 1;1478 \\ if (b != 0) return 1;
1420 \\ if (c != 0) return 2;1479 \\ if (c != null) return 2;
1421 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;1480 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
1422 \\ return 4;1481 \\ return 4;
1423 \\}1482 \\}
...@@ -1434,7 +1493,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1434,7 +1493,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1434 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {1493 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1435 \\ while (a != 0) return 0;1494 \\ while (a != 0) return 0;
1436 \\ while (b != 0) return 1;1495 \\ while (b != 0) return 1;
1437 \\ while (c != 0) return 2;1496 \\ while (c != null) return 2;
1438 \\ return 3;1497 \\ return 3;
1439 \\}1498 \\}
1440 );1499 );
...@@ -1450,7 +1509,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1450,7 +1509,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1450 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {1509 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1451 \\ while (a != 0) return 0;1510 \\ while (a != 0) return 0;
1452 \\ while (b != 0) return 1;1511 \\ while (b != 0) return 1;
1453 \\ while (c != 0) return 2;1512 \\ while (c != null) return 2;
1454 \\ return 3;1513 \\ return 3;
1455 \\}1514 \\}
1456 );1515 );
...@@ -1497,14 +1556,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1497,14 +1556,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1497 \\}1556 \\}
1498 );1557 );
14991558
1500 cases.addC("Parameterless function prototypes",
1501 \\void foo() {}
1502 \\void bar(void) {}
1503 ,
1504 \\pub export fn foo() void {}
1505 \\pub export fn bar() void {}
1506 );
1507
1508 cases.addC(1559 cases.addC(
1509 "u integer suffix after 0 (zero) in macro definition",1560 "u integer suffix after 0 (zero) in macro definition",
1510 "#define ZERO 0U",1561 "#define ZERO 0U",
...@@ -1553,33 +1604,101 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1553,33 +1604,101 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1553 "pub const NOT_ZERO = ~c_uint(0);",1604 "pub const NOT_ZERO = ~c_uint(0);",
1554 );1605 );
15551606
1556 // cases.add("empty array with initializer",1607 cases.addC("implicit casts",
1557 // "int a[4] = {};"1608 \\#include <stdbool.h>
1558 // ,1609 \\
1559 // "pub var a: [4]c_int = [1]c_int{0} ** 4;"1610 \\void fn_int(int x);
1560 // );1611 \\void fn_f32(float x);
15611612 \\void fn_f64(double x);
1562 // cases.add("array with initialization",1613 \\void fn_char(char x);
1563 // "int a[4] = {1, 2, 3, 4};"1614 \\void fn_bool(bool x);
1564 // ,1615 \\void fn_ptr(void *x);
1565 // "pub var a: [4]c_int = [4]c_int{1, 2, 3, 4};"1616 \\
1566 // );1617 \\void call(int q) {
15671618 \\ fn_int(3.0f);
1568 // cases.add("array with incomplete initialization",1619 \\ fn_int(3.0);
1569 // "int a[4] = {3, 4};"1620 \\ fn_int(3.0L);
1570 // ,1621 \\ fn_int('ABCD');
1571 // "pub var a: [4]c_int = [2]c_int{3, 4} ++ ([1]c_int{0} ** 2);"1622 \\ fn_f32(3);
1572 // );1623 \\ fn_f64(3);
15731624 \\ fn_char('3');
1574 // cases.add("2D array with initialization",1625 \\ fn_char('\x1');
1575 // "int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };"1626 \\ fn_char(0);
1576 // ,1627 \\ fn_f32(3.0f);
1577 // "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}};"1628 \\ fn_f64(3.0);
1578 // );1629 \\ fn_bool(123);
15791630 \\ fn_bool(0);
1580 // cases.add("2D array with incomplete initialization",1631 \\ fn_bool(&fn_int);
1581 // "int a[3][3] = { {1, 2}, {4, 5, 6} };"1632 \\ fn_int(&fn_int);
1582 // ,1633 \\ fn_ptr(42);
1583 // "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};"1634 \\}
1584 // );1635 ,
1636 \\pub extern fn fn_int(x: c_int) void;
1637 \\pub extern fn fn_f32(x: f32) void;
1638 \\pub extern fn fn_f64(x: f64) void;
1639 \\pub extern fn fn_char(x: u8) void;
1640 \\pub extern fn fn_bool(x: bool) void;
1641 \\pub extern fn fn_ptr(x: ?*c_void) void;
1642 \\pub export fn call(q: c_int) void {
1643 \\ fn_int(@floatToInt(c_int, 3.000000));
1644 \\ fn_int(@floatToInt(c_int, 3.000000));
1645 \\ fn_int(@floatToInt(c_int, 3.000000));
1646 \\ fn_int(1094861636);
1647 \\ fn_f32(@intToFloat(f32, 3));
1648 \\ fn_f64(@intToFloat(f64, 3));
1649 \\ fn_char(u8('3'));
1650 \\ fn_char(u8('\x01'));
1651 \\ fn_char(u8(0));
1652 \\ fn_f32(3.000000);
1653 \\ fn_f64(3.000000);
1654 \\ fn_bool(true);
1655 \\ fn_bool(false);
1656 \\ fn_bool(@ptrToInt(&fn_int) != 0);
1657 \\ fn_int(@intCast(c_int, @ptrToInt(&fn_int)));
1658 \\ fn_ptr(@intToPtr(?*c_void, 42));
1659 \\}
1660 );
1661
1662 cases.addC("pointer conversion with different alignment",
1663 \\void test_ptr_cast() {
1664 \\ void *p;
1665 \\ {
1666 \\ char *to_char = (char *)p;
1667 \\ short *to_short = (short *)p;
1668 \\ int *to_int = (int *)p;
1669 \\ long long *to_longlong = (long long *)p;
1670 \\ }
1671 \\ {
1672 \\ char *to_char = p;
1673 \\ short *to_short = p;
1674 \\ int *to_int = p;
1675 \\ long long *to_longlong = p;
1676 \\ }
1677 \\}
1678 ,
1679 \\pub export fn test_ptr_cast() void {
1680 \\ var p: ?*c_void = undefined;
1681 \\ {
1682 \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p));
1683 \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p));
1684 \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p));
1685 \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p));
1686 \\ }
1687 \\ {
1688 \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p));
1689 \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p));
1690 \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p));
1691 \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p));
1692 \\ }
1693 \\}
1694 );
1695
1696 /////////////// Cases for only stage1 because stage2 behavior is better ////////////////
1697 cases.addC("Parameterless function prototypes",
1698 \\void foo() {}
1699 \\void bar(void) {}
1700 ,
1701 \\pub export fn foo() void {}
1702 \\pub export fn bar() void {}
1703 );
1585}1704}