| author | |
| committer | |
| log | 3787f3428625e830fd852a8f5a40c7d8a2d429f6 |
| tree | 23fb493b9d2f07c7abe57955874682959936319a |
| parent | 16aee1f58a80295f7599a8290d764a5c7040c373 |
| parent | edcc7c72d1a684a8a16ca23ad26689f2cce4e803 |
| signature | Commit is signed but in an unrecognized format. |
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 | 15 | |
| 16 | 16 | |
| 17 | 17 | set(ZIG_VERSION_MAJOR 0) |
| 18 | set(ZIG_VERSION_MINOR 3) | |
| 18 | set(ZIG_VERSION_MINOR 4) | |
| 19 | 19 | set(ZIG_VERSION_PATCH 0) |
| 20 | 20 | set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}") |
| 21 | 21 | |
| ... | ... | @@ -50,10 +50,6 @@ option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead |
| 50 | 50 | find_package(llvm) |
| 51 | 51 | find_package(clang) |
| 52 | 52 | |
| 53 | if(MINGW) | |
| 54 | find_package(z3) | |
| 55 | endif() | |
| 56 | ||
| 57 | 53 | if(APPLE AND ZIG_STATIC) |
| 58 | 54 | list(REMOVE_ITEM LLVM_LIBRARIES "-lz") |
| 59 | 55 | find_library(ZLIB NAMES z zlib libz) |
| ... | ... | @@ -62,6 +58,16 @@ endif() |
| 62 | 58 | |
| 63 | 59 | set(ZIG_CPP_LIB_DIR "${CMAKE_BINARY_DIR}/zig_cpp") |
| 64 | 60 | |
| 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. | |
| 63 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ZIG_CPP_LIB_DIR}) | |
| 64 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ZIG_CPP_LIB_DIR}) | |
| 65 | foreach(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}) | |
| 69 | endforeach(CONFIG_TYPE CMAKE_CONFIGURATION_TYPES) | |
| 70 | ||
| 65 | 71 | if(ZIG_FORCE_EXTERNAL_LLD) |
| 66 | 72 | find_package(lld) |
| 67 | 73 | include_directories(${LLVM_INCLUDE_DIRS}) |
| ... | ... | @@ -196,7 +202,7 @@ else() |
| 196 | 202 | if(MSVC) |
| 197 | 203 | set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w") |
| 198 | 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 | 206 | if(MINGW) |
| 201 | 207 | set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format") |
| 202 | 208 | endif() |
| ... | ... | @@ -257,7 +263,6 @@ else() |
| 257 | 263 | embedded_lld_wasm |
| 258 | 264 | 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}") | |
| 261 | 266 | endif() |
| 262 | 267 | |
| 263 | 268 | # No patches have been applied to SoftFloat-3e |
| ... | ... | @@ -407,6 +412,12 @@ set(SOFTFLOAT_LIBRARIES embedded_softfloat) |
| 407 | 412 | |
| 408 | 413 | find_package(Threads) |
| 409 | 414 | |
| 415 | # CMake doesn't let us create an empty executable, so we hang on to this one separately. | |
| 416 | set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp") | |
| 417 | ||
| 418 | # This is our shim which will be replaced by libuserland written in Zig. | |
| 419 | set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp") | |
| 420 | ||
| 410 | 421 | set(ZIG_SOURCES |
| 411 | 422 | "${CMAKE_SOURCE_DIR}/src/analyze.cpp" |
| 412 | 423 | "${CMAKE_SOURCE_DIR}/src/ast_render.cpp" |
| ... | ... | @@ -423,7 +434,6 @@ set(ZIG_SOURCES |
| 423 | 434 | "${CMAKE_SOURCE_DIR}/src/ir_print.cpp" |
| 424 | 435 | "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp" |
| 425 | 436 | "${CMAKE_SOURCE_DIR}/src/link.cpp" |
| 426 | "${CMAKE_SOURCE_DIR}/src/main.cpp" | |
| 427 | 437 | "${CMAKE_SOURCE_DIR}/src/os.cpp" |
| 428 | 438 | "${CMAKE_SOURCE_DIR}/src/parser.cpp" |
| 429 | 439 | "${CMAKE_SOURCE_DIR}/src/range_set.cpp" |
| ... | ... | @@ -477,6 +487,7 @@ set(ZIG_STD_FILES |
| 477 | 487 | "crypto/x25519.zig" |
| 478 | 488 | "cstr.zig" |
| 479 | 489 | "debug.zig" |
| 490 | "debug/leb128.zig" | |
| 480 | 491 | "debug/failing_allocator.zig" |
| 481 | 492 | "dwarf.zig" |
| 482 | 493 | "dynamic_library.zig" |
| ... | ... | @@ -507,6 +518,7 @@ set(ZIG_STD_FILES |
| 507 | 518 | "heap.zig" |
| 508 | 519 | "io.zig" |
| 509 | 520 | "io/seekable_stream.zig" |
| 521 | "io/c_out_stream.zig" | |
| 510 | 522 | "json.zig" |
| 511 | 523 | "lazy_init.zig" |
| 512 | 524 | "linked_list.zig" |
| ... | ... | @@ -521,6 +533,7 @@ set(ZIG_STD_FILES |
| 521 | 533 | "math/atanh.zig" |
| 522 | 534 | "math/big.zig" |
| 523 | 535 | "math/big/int.zig" |
| 536 | "math/big/rational.zig" | |
| 524 | 537 | "math/cbrt.zig" |
| 525 | 538 | "math/ceil.zig" |
| 526 | 539 | "math/complex.zig" |
| ... | ... | @@ -599,6 +612,7 @@ set(ZIG_STD_FILES |
| 599 | 612 | "os/linux.zig" |
| 600 | 613 | "os/linux/arm64.zig" |
| 601 | 614 | "os/linux/errno.zig" |
| 615 | "os/linux/tls.zig" | |
| 602 | 616 | "os/linux/vdso.zig" |
| 603 | 617 | "os/linux/x86_64.zig" |
| 604 | 618 | "os/netbsd.zig" |
| ... | ... | @@ -606,6 +620,8 @@ set(ZIG_STD_FILES |
| 606 | 620 | "os/path.zig" |
| 607 | 621 | "os/time.zig" |
| 608 | 622 | "os/uefi.zig" |
| 623 | "os/wasi.zig" | |
| 624 | "os/wasi/core.zig" | |
| 609 | 625 | "os/windows.zig" |
| 610 | 626 | "os/windows/advapi32.zig" |
| 611 | 627 | "os/windows/error.zig" |
| ... | ... | @@ -615,6 +631,7 @@ set(ZIG_STD_FILES |
| 615 | 631 | "os/windows/shell32.zig" |
| 616 | 632 | "os/windows/util.zig" |
| 617 | 633 | "os/zen.zig" |
| 634 | "packed_int_array.zig" | |
| 618 | 635 | "pdb.zig" |
| 619 | 636 | "priority_queue.zig" |
| 620 | 637 | "rand.zig" |
| ... | ... | @@ -628,10 +645,15 @@ set(ZIG_STD_FILES |
| 628 | 645 | "special/build_runner.zig" |
| 629 | 646 | "special/builtin.zig" |
| 630 | 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 | 651 | "special/compiler_rt/addXf3.zig" |
| 632 | 652 | "special/compiler_rt/aulldiv.zig" |
| 633 | 653 | "special/compiler_rt/aullrem.zig" |
| 634 | 654 | "special/compiler_rt/comparetf2.zig" |
| 655 | "special/compiler_rt/comparedf2.zig" | |
| 656 | "special/compiler_rt/comparesf2.zig" | |
| 635 | 657 | "special/compiler_rt/divsf3.zig" |
| 636 | 658 | "special/compiler_rt/divdf3.zig" |
| 637 | 659 | "special/compiler_rt/divti3.zig" |
| ... | ... | @@ -656,9 +678,13 @@ set(ZIG_STD_FILES |
| 656 | 678 | "special/compiler_rt/fixunstfdi.zig" |
| 657 | 679 | "special/compiler_rt/fixunstfsi.zig" |
| 658 | 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 | 684 | "special/compiler_rt/floattidf.zig" |
| 660 | 685 | "special/compiler_rt/floattisf.zig" |
| 661 | 686 | "special/compiler_rt/floattitf.zig" |
| 687 | "special/compiler_rt/floatundidf.zig" | |
| 662 | 688 | "special/compiler_rt/floatunditf.zig" |
| 663 | 689 | "special/compiler_rt/floatunsitf.zig" |
| 664 | 690 | "special/compiler_rt/floatuntidf.zig" |
| ... | ... | @@ -667,7 +693,11 @@ set(ZIG_STD_FILES |
| 667 | 693 | "special/compiler_rt/modti3.zig" |
| 668 | 694 | "special/compiler_rt/mulXf3.zig" |
| 669 | 695 | "special/compiler_rt/muloti4.zig" |
| 696 | "special/compiler_rt/mulodi4.zig" | |
| 670 | 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 | 701 | "special/compiler_rt/negXf2.zig" |
| 672 | 702 | "special/compiler_rt/popcountdi2.zig" |
| 673 | 703 | "special/compiler_rt/truncXfYf2.zig" |
| ... | ... | @@ -676,7 +706,6 @@ set(ZIG_STD_FILES |
| 676 | 706 | "special/compiler_rt/udivmodti4.zig" |
| 677 | 707 | "special/compiler_rt/udivti3.zig" |
| 678 | 708 | "special/compiler_rt/umodti3.zig" |
| 679 | "special/fmt_runner.zig" | |
| 680 | 709 | "special/init-exe/build.zig" |
| 681 | 710 | "special/init-exe/src/main.zig" |
| 682 | 711 | "special/init-lib/build.zig" |
| ... | ... | @@ -6604,7 +6633,7 @@ endif() |
| 6604 | 6633 | if(MSVC) |
| 6605 | 6634 | set(EXE_CFLAGS "${EXE_CFLAGS}") |
| 6606 | 6635 | else() |
| 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 | 6637 | if(MINGW) |
| 6609 | 6638 | set(EXE_CFLAGS "${EXE_CFLAGS} -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format") |
| 6610 | 6639 | endif() |
| ... | ... | @@ -6639,13 +6668,12 @@ set_target_properties(opt_c_util PROPERTIES |
| 6639 | 6668 | COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}" |
| 6640 | 6669 | ) |
| 6641 | 6670 | |
| 6642 | add_executable(zig ${ZIG_SOURCES}) | |
| 6643 | set_target_properties(zig PROPERTIES | |
| 6671 | add_library(compiler STATIC ${ZIG_SOURCES}) | |
| 6672 | set_target_properties(compiler PROPERTIES | |
| 6644 | 6673 | COMPILE_FLAGS ${EXE_CFLAGS} |
| 6645 | 6674 | LINK_FLAGS ${EXE_LDFLAGS} |
| 6646 | 6675 | ) |
| 6647 | ||
| 6648 | target_link_libraries(zig LINK_PUBLIC | |
| 6676 | target_link_libraries(compiler LINK_PUBLIC | |
| 6649 | 6677 | zig_cpp |
| 6650 | 6678 | opt_c_util |
| 6651 | 6679 | ${SOFTFLOAT_LIBRARIES} |
| ... | ... | @@ -6654,24 +6682,63 @@ target_link_libraries(zig LINK_PUBLIC |
| 6654 | 6682 | ${LLVM_LIBRARIES} |
| 6655 | 6683 | ${CMAKE_THREAD_LIBS_INIT} |
| 6656 | 6684 | ) |
| 6657 | ||
| 6658 | 6685 | if(NOT MSVC) |
| 6659 | target_link_libraries(zig LINK_PUBLIC ${LIBXML2}) | |
| 6686 | target_link_libraries(compiler LINK_PUBLIC ${LIBXML2}) | |
| 6660 | 6687 | endif() |
| 6661 | 6688 | |
| 6662 | 6689 | if(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}) | |
| 6664 | 6692 | endif() |
| 6665 | 6693 | |
| 6666 | 6694 | if(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}) | |
| 6668 | 6696 | endif() |
| 6669 | 6697 | |
| 6670 | 6698 | if(MSVC OR MINGW) |
| 6671 | target_link_libraries(zig LINK_PUBLIC version) | |
| 6699 | target_link_libraries(compiler LINK_PUBLIC version) | |
| 6672 | 6700 | endif() |
| 6701 | ||
| 6702 | add_executable(zig0 "${ZIG_MAIN_SRC}" "${ZIG0_SHIM_SRC}") | |
| 6703 | set_target_properties(zig0 PROPERTIES | |
| 6704 | COMPILE_FLAGS ${EXE_CFLAGS} | |
| 6705 | LINK_FLAGS ${EXE_LDFLAGS} | |
| 6706 | ) | |
| 6707 | target_link_libraries(zig0 compiler) | |
| 6708 | ||
| 6709 | if(WIN32) | |
| 6710 | set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib") | |
| 6711 | elseif(APPLE) | |
| 6712 | set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.o") | |
| 6713 | else() | |
| 6714 | set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a") | |
| 6715 | endif() | |
| 6716 | add_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 | ) | |
| 6729 | add_custom_target(userland_target DEPENDS "${LIBUSERLAND}") | |
| 6730 | add_executable(zig "${ZIG_MAIN_SRC}") | |
| 6731 | if(MINGW) | |
| 6732 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -fstack-protector") | |
| 6733 | endif() | |
| 6734 | set_target_properties(zig PROPERTIES | |
| 6735 | COMPILE_FLAGS ${EXE_CFLAGS} | |
| 6736 | LINK_FLAGS ${EXE_LDFLAGS} | |
| 6737 | ) | |
| 6738 | target_link_libraries(zig compiler "${LIBUSERLAND}") | |
| 6739 | add_dependencies(zig userland_target) | |
| 6673 | 6740 | install(TARGETS zig DESTINATION bin) |
| 6674 | install(TARGETS zig_cpp DESTINATION "${ZIG_CPP_LIB_DIR}") | |
| 6741 | ||
| 6675 | 6742 | |
| 6676 | 6743 | foreach(file ${ZIG_C_HEADER_FILES}) |
| 6677 | 6744 | get_filename_component(file_dir "${C_HEADERS_DEST}/${file}" DIRECTORY) |
| ... | ... | @@ -6697,7 +6764,3 @@ foreach(file ${ZIG_LIBCXX_FILES}) |
| 6697 | 6764 | get_filename_component(file_dir "${LIBCXX_FILES_DEST}/${file}" DIRECTORY) |
| 6698 | 6765 | install(FILES "${CMAKE_SOURCE_DIR}/libcxx/${file}" DESTINATION "${file_dir}") |
| 6699 | 6766 | endforeach() |
| 6700 | ||
| 6701 | install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/arg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/") | |
| 6702 | install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/main.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/") | |
| 6703 | install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/errmsg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/") |
README.md+104-138| ... | ... | @@ -1,140 +1,15 @@ |
| 1 | 1 |  |
| 2 | 2 | |
| 3 | A programming language designed for robustness, optimality, and | |
| 4 | clarity. | |
| 5 | ||
| 6 | [Download & Documentation](https://ziglang.org/download/) | |
| 7 | ||
| 8 | ## Feature Highlights | |
| 9 | ||
| 10 | * Small, simple language. Focus on debugging your application rather than | |
| 11 | debugging knowledge of your programming language. | |
| 12 | * Ships with a build system that obviates the need for a configure script | |
| 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 | |
| 3 | Zig is an open-source programming language designed for **robustness**, | |
| 4 | **optimality**, and **maintainability**. | |
| 5 | ||
| 6 | ## Resources | |
| 7 | ||
| 8 | * [Introduction](https://ziglang.org/#Introduction) | |
| 9 | * [Download & Documentation](https://ziglang.org/download) | |
| 10 | * [Community](https://github.com/ziglang/zig/wiki/Community) | |
| 11 | ||
| 12 | ## Building from Source | |
| 138 | 13 | |
| 139 | 14 | [](https://dev.azure.com/ziglang/zig/_build/latest?definitionId=1&branchName=master) |
| 140 | 15 | |
| ... | ... | @@ -150,12 +25,14 @@ Note that you can |
| 150 | 25 | * cmake >= 2.8.5 |
| 151 | 26 | * gcc >= 5.0.0 or clang >= 3.6.0 |
| 152 | 27 | * 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). | |
| 153 | 29 | |
| 154 | 30 | ##### Windows |
| 155 | 31 | |
| 156 | 32 | * cmake >= 2.8.5 |
| 157 | 33 | * Microsoft Visual Studio 2017 (version 15.8) |
| 158 | 34 | * 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). | |
| 159 | 36 | |
| 160 | 37 | #### Instructions |
| 161 | 38 | |
| ... | ... | @@ -165,9 +42,7 @@ Note that you can |
| 165 | 42 | mkdir build |
| 166 | 43 | cd build |
| 167 | 44 | cmake .. |
| 168 | make | |
| 169 | 45 | make install |
| 170 | bin/zig build --build-file ../build.zig test | |
| 171 | 46 | ``` |
| 172 | 47 | |
| 173 | 48 | ##### MacOS |
| ... | ... | @@ -179,7 +54,6 @@ mkdir build |
| 179 | 54 | cd build |
| 180 | 55 | cmake .. -DCMAKE_PREFIX_PATH=/usr/local/Cellar/llvm/8.0.0 |
| 181 | 56 | make install |
| 182 | bin/zig build --build-file ../build.zig test | |
| 183 | 57 | ``` |
| 184 | 58 | |
| 185 | 59 | ##### Windows |
| ... | ... | @@ -222,3 +96,95 @@ use stage 1. |
| 222 | 96 | ``` |
| 223 | 97 | ./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast |
| 224 | 98 | ``` |
| 99 | ||
| 100 | ## Contributing | |
| 101 | ||
| 102 | ### Start a Project Using Zig | |
| 103 | ||
| 104 | One of the best ways you can contribute to Zig is to start using it for a | |
| 105 | personal 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 | ||
| 111 | Without fail, these projects lead to discovering bugs and helping flesh out use | |
| 112 | cases, which lead to further design iterations of Zig. Importantly, each issue | |
| 113 | found this way comes with real world motivations, so it is easy to explain | |
| 114 | your reasoning behind proposals and feature requests. | |
| 115 | ||
| 116 | Ideally, such a project will help you to learn new skills and add something | |
| 117 | to your personal portfolio at the same time. | |
| 118 | ||
| 119 | ### Spread the Word | |
| 120 | ||
| 121 | Another way to contribute is to write about Zig, or speak about Zig at a | |
| 122 | conference, or do either of those things for your project which uses Zig. | |
| 123 | Here 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 | ||
| 128 | Zig is a brand new language, with no advertising budget. Word of mouth is the | |
| 129 | only way people find out about the project, and the more people hear about it, | |
| 130 | the more people will use it, and the better chance we have to take over the | |
| 131 | world. | |
| 132 | ||
| 133 | ### Finding Contributor Friendly Issues | |
| 134 | ||
| 135 | Please note that issues labeled | |
| 136 | [Proposal](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aproposal) | |
| 137 | but do not also have the | |
| 138 | [Accepted](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aaccepted) | |
| 139 | label are still under consideration, and efforts to implement such a proposal | |
| 140 | have a high risk of being wasted. If you are interested in a proposal which is | |
| 141 | still under consideration, please express your interest in the issue tracker, | |
| 142 | providing extra insights and considerations that others have not yet expressed. | |
| 143 | The most highly regarded argument in such a discussion is a real world use case. | |
| 144 | ||
| 145 | The issue label | |
| 146 | [Contributor Friendly](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3A%22contributor+friendly%22) | |
| 147 | exists to help contributors find issues that are "limited in scope and/or | |
| 148 | knowledge of Zig internals." | |
| 149 | ||
| 150 | ### Editing Source Code | |
| 151 | ||
| 152 | First, build the Stage 1 compiler as described in [the Building section](#building). | |
| 153 | ||
| 154 | When 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 | |
| 156 | new file to the standard library, you must also add the file path in | |
| 157 | CMakeLists.txt. | |
| 158 | ||
| 159 | To test changes, do the following from the build directory: | |
| 160 | ||
| 161 | 1. Run `make install` (on POSIX) or | |
| 162 | `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows). | |
| 163 | 2. `bin/zig build --build-file ../build.zig test` (on POSIX) or | |
| 164 | `bin\zig.exe build --build-file ..\build.zig test` (on Windows). | |
| 165 | ||
| 166 | That runs the whole test suite, which does a lot of extra testing that you | |
| 167 | likely won't always need, and can take upwards of 2 hours. This is what the | |
| 168 | CI server runs when you make a pull request. | |
| 169 | ||
| 170 | To save time, you can add the `--help` option to the `zig build` command and | |
| 171 | see 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 | |
| 173 | the time down from around 2 hours to about 6 minutes, and this is a good | |
| 174 | enough amount of testing before making a pull request. | |
| 175 | ||
| 176 | Another 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 | |
| 178 | not the other ones. Combining this suggestion with the previous one, you could | |
| 179 | do 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 | ||
| 184 | This will run only the standard library tests, in debug mode only, for all | |
| 185 | targets (it will cross-compile the tests for non-native targets but not run | |
| 186 | them). | |
| 187 | ||
| 188 | When making changes to the compiler source code, the most helpful test step to | |
| 189 | run is `test-behavior`. When editing documentation it is `docs`. You can find | |
| 190 | this information and more in the `--help` menu. |
build.zig+27| ... | ... | @@ -65,6 +65,8 @@ pub fn build(b: *Builder) !void { |
| 65 | 65 | |
| 66 | 66 | b.default_step.dependOn(&exe.step); |
| 67 | 67 | |
| 68 | addLibUserlandStep(b); | |
| 69 | ||
| 68 | 70 | const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false; |
| 69 | 71 | const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release; |
| 70 | 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 | 382 | dia_guids_lib: []const u8, |
| 381 | 383 | llvm: LibraryDep, |
| 382 | 384 | }; |
| 385 | ||
| 386 | fn 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 | 6 | if [ "${BUILD_REASON}" != "PullRequest" ]; then |
| 7 | 7 | cd "$ZIGBUILDDIR" |
| 8 | 8 | |
| 9 | rm release/*.lib | |
| 9 | rm release/*.exe | |
| 10 | 10 | mv ../LICENSE release/ |
| 11 | 11 | mv ../zig-cache/langref.html release/ |
| 12 | 12 | mv release/bin/zig.exe release/ |
cmake/Findclang.cmake+1-1| ... | ... | @@ -44,7 +44,7 @@ else() |
| 44 | 44 | /usr/local/llvm80/include |
| 45 | 45 | /mingw64/include) |
| 46 | 46 | |
| 47 | macro(FIND_AND_ADD_CLANG_LIB _libname_) | |
| 47 | macro(FIND_AND_ADD_CLANG_LIB _libname_) | |
| 48 | 48 | string(TOUPPER ${_libname_} _prettylibname_) |
| 49 | 49 | find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_} |
| 50 | 50 | PATHS |
deps/lld/wasm/OutputSections.cpp+6-6| ... | ... | @@ -111,8 +111,8 @@ void CodeSection::writeTo(uint8_t *Buf) { |
| 111 | 111 | memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size()); |
| 112 | 112 | |
| 113 | 113 | // Write code section bodies |
| 114 | parallelForEach(Functions, | |
| 115 | [&](const InputChunk *Chunk) { Chunk->writeTo(Buf); }); | |
| 114 | for (const InputChunk *Chunk : Functions) | |
| 115 | Chunk->writeTo(Buf); | |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 | uint32_t CodeSection::numRelocations() const { |
| ... | ... | @@ -176,7 +176,7 @@ void DataSection::writeTo(uint8_t *Buf) { |
| 176 | 176 | // Write data section headers |
| 177 | 177 | memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size()); |
| 178 | 178 | |
| 179 | parallelForEach(Segments, [&](const OutputSegment *Segment) { | |
| 179 | for (const OutputSegment *Segment : Segments) { | |
| 180 | 180 | // Write data segment header |
| 181 | 181 | uint8_t *SegStart = Buf + Segment->SectionOffset; |
| 182 | 182 | memcpy(SegStart, Segment->Header.data(), Segment->Header.size()); |
| ... | ... | @@ -184,7 +184,7 @@ void DataSection::writeTo(uint8_t *Buf) { |
| 184 | 184 | // Write segment data payload |
| 185 | 185 | for (const InputChunk *Chunk : Segment->InputSegments) |
| 186 | 186 | Chunk->writeTo(Buf); |
| 187 | }); | |
| 187 | } | |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | 190 | uint32_t DataSection::numRelocations() const { |
| ... | ... | @@ -232,8 +232,8 @@ void CustomSection::writeTo(uint8_t *Buf) { |
| 232 | 232 | Buf += NameData.size(); |
| 233 | 233 | |
| 234 | 234 | // Write custom sections payload |
| 235 | parallelForEach(InputSections, | |
| 236 | [&](const InputSection *Section) { Section->writeTo(Buf); }); | |
| 235 | for (const InputSection *Section : InputSections) | |
| 236 | Section->writeTo(Buf); | |
| 237 | 237 | } |
| 238 | 238 | |
| 239 | 239 | uint32_t CustomSection::numRelocations() const { |
doc/docgen.zig+54-1| ... | ... | @@ -265,6 +265,7 @@ const SeeAlsoItem = struct { |
| 265 | 265 | const ExpectedOutcome = enum { |
| 266 | 266 | Succeed, |
| 267 | 267 | Fail, |
| 268 | BuildFail, | |
| 268 | 269 | }; |
| 269 | 270 | |
| 270 | 271 | const Code = struct { |
| ... | ... | @@ -468,6 +469,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { |
| 468 | 469 | code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Succeed }; |
| 469 | 470 | } else if (mem.eql(u8, code_kind_str, "exe_err")) { |
| 470 | 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 | 474 | } else if (mem.eql(u8, code_kind_str, "test")) { |
| 472 | 475 | code_kind_id = Code.Id.Test; |
| 473 | 476 | } else if (mem.eql(u8, code_kind_str, "test_err")) { |
| ... | ... | @@ -509,6 +512,10 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { |
| 509 | 512 | target_str = "x86_64-windows"; |
| 510 | 513 | } else if (mem.eql(u8, end_tag_name, "target_linux_x86_64")) { |
| 511 | 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 | 519 | } else if (mem.eql(u8, end_tag_name, "link_libc")) { |
| 513 | 520 | link_libc = true; |
| 514 | 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 | 1032 | tmp_dir_name, |
| 1026 | 1033 | "--name", |
| 1027 | 1034 | code.name, |
| 1035 | "--color", | |
| 1036 | "on", | |
| 1028 | 1037 | }); |
| 1029 | 1038 | try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name); |
| 1030 | 1039 | switch (code.mode) { |
| ... | ... | @@ -1059,14 +1068,52 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 1059 | 1068 | } |
| 1060 | 1069 | if (code.target_str) |triple| { |
| 1061 | 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 | 1108 | _ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile"); |
| 1064 | 1109 | |
| 1065 | 1110 | if (code.target_str) |triple| { |
| 1066 | if (mem.startsWith(u8, triple, "x86_64-linux") and | |
| 1111 | if (mem.startsWith(u8, triple, "wasm32") or | |
| 1112 | mem.startsWith(u8, triple, "x86_64-linux") and | |
| 1067 | 1113 | (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64)) |
| 1068 | 1114 | { |
| 1069 | 1115 | // skip execution |
| 1116 | try out.print("</code></pre>\n"); | |
| 1070 | 1117 | break :code_block; |
| 1071 | 1118 | } |
| 1072 | 1119 | } |
| ... | ... | @@ -1130,6 +1177,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 1130 | 1177 | } |
| 1131 | 1178 | if (code.target_str) |triple| { |
| 1132 | 1179 | try test_args.appendSlice([][]const u8{ "-target", triple }); |
| 1180 | try out.print(" -target {}", triple); | |
| 1133 | 1181 | } |
| 1134 | 1182 | const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed"); |
| 1135 | 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 | 1358 | }, |
| 1311 | 1359 | } |
| 1312 | 1360 | |
| 1361 | if (code.target_str) |triple| { | |
| 1362 | try build_args.appendSlice([][]const u8{ "-target", triple }); | |
| 1363 | try out.print(" -target {}", triple); | |
| 1364 | } | |
| 1365 | ||
| 1313 | 1366 | if (maybe_error_match) |error_match| { |
| 1314 | 1367 | const result = try os.ChildProcess.exec(allocator, build_args.toSliceConst(), null, &env_map, max_doc_file_size); |
| 1315 | 1368 | switch (result.term) { |
doc/langref.html.in+74-35| ... | ... | @@ -4,11 +4,12 @@ |
| 4 | 4 | <meta charset="utf-8"> |
| 5 | 5 | <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> |
| 6 | 6 | <title>Documentation - The Zig Programming Language</title> |
| 7 | <link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNSAxMCIgZmlsbD0iI2Y3YTQxZCI+PHBhdGggZD0iTTAsMSBIMy41IFYzIEgyIFY3IEgzLjY4MiBMMS44ODEsOSBIMCBaIE0xNSw5IEgxMS41IFY3IEgxMyBWMyBIMTEuMzE4IEwxMy4xMTksMSBIMTUgWiBNNCwxIEg5LjkxMiBMMTMuMzI4LDAuMDIxIEw3LjA0NSw3IEgxMSBWOSBINS4wODggTDEuNjcyLDkuOTc5IEw3Ljk1NSwzIEg0IFoiLz48L3N2Zz4="/> | |
| 7 | 8 | <style type="text/css"> |
| 8 | 9 | body{ |
| 9 | 10 | font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif; |
| 10 | 11 | } |
| 11 | a { | |
| 12 | a:not(:hover) { | |
| 12 | 13 | text-decoration: none; |
| 13 | 14 | } |
| 14 | 15 | table, th, td { |
| ... | ... | @@ -158,13 +159,15 @@ |
| 158 | 159 | <div id="contents"> |
| 159 | 160 | {#header_open|Introduction#} |
| 160 | 161 | <p> |
| 161 | Zig is an open-source programming language designed for <strong>robustness</strong>, | |
| 162 | <strong>optimality</strong>, and <strong>clarity</strong>. | |
| 162 | Zig is a general-purpose programming language designed for <strong>robustness</strong>, | |
| 163 | <strong>optimality</strong>, and <strong>maintainability</strong>. | |
| 163 | 164 | </p> |
| 164 | 165 | <ul> |
| 165 | 166 | <li><strong>Robust</strong> - behavior is correct even for edge cases such as out of memory.</li> |
| 166 | 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 | 171 | </ul> |
| 169 | 172 | <p> |
| 170 | 173 | Often the most efficient way to learn something new is to see examples, so |
| ... | ... | @@ -3125,7 +3128,7 @@ test "while null capture" { |
| 3125 | 3128 | while (eventuallyNullSequence()) |value| { |
| 3126 | 3129 | sum2 += value; |
| 3127 | 3130 | } else { |
| 3128 | assert(sum1 == 3); | |
| 3131 | assert(sum2 == 3); | |
| 3129 | 3132 | } |
| 3130 | 3133 | } |
| 3131 | 3134 | |
| ... | ... | @@ -7180,14 +7183,6 @@ pub const FloatMode = enum { |
| 7180 | 7183 | {#see_also|Floating Point Operations#} |
| 7181 | 7184 | {#header_close#} |
| 7182 | 7185 | |
| 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 | 7186 | {#header_open|@setRuntimeSafety#} |
| 7192 | 7187 | <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre> |
| 7193 | 7188 | <p> |
| ... | ... | @@ -7217,6 +7212,8 @@ test "@setRuntimeSafety" { |
| 7217 | 7212 | } |
| 7218 | 7213 | } |
| 7219 | 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> | |
| 7220 | 7217 | |
| 7221 | 7218 | {#header_close#} |
| 7222 | 7219 | |
| ... | ... | @@ -7272,6 +7269,10 @@ test "@setRuntimeSafety" { |
| 7272 | 7269 | consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or |
| 7273 | 7270 | {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}. |
| 7274 | 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 | 7276 | {#see_also|@typeInfo#} |
| 7276 | 7277 | {#header_close#} |
| 7277 | 7278 | |
| ... | ... | @@ -7360,20 +7361,30 @@ fn List(comptime T: type) type { |
| 7360 | 7361 | <pre>{#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}</pre> |
| 7361 | 7362 | <p> |
| 7362 | 7363 | This function truncates bits from an integer type, resulting in a smaller |
| 7363 | integer type. | |
| 7364 | or same-sized integer type. | |
| 7364 | 7365 | </p> |
| 7365 | 7366 | <p> |
| 7366 | The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in | |
| 7367 | {#link|ReleaseFast#} mode: | |
| 7367 | The following produces safety-checked {#link|Undefined Behavior#}: | |
| 7368 | 7368 | </p> |
| 7369 | <pre>{#syntax#}const a: u16 = 0xabcd; | |
| 7370 | const b: u8 = u8(a);{#endsyntax#}</pre> | |
| 7369 | {#code_begin|test_err|cast truncated bits#} | |
| 7370 | test "integer cast panic" { | |
| 7371 | var a: u16 = 0xabcd; | |
| 7372 | var b: u8 = @intCast(u8, a); | |
| 7373 | } | |
| 7374 | {#code_end#} | |
| 7371 | 7375 | <p> |
| 7372 | 7376 | However this is well defined and working code: |
| 7373 | 7377 | </p> |
| 7374 | <pre>{#syntax#}const a: u16 = 0xabcd; | |
| 7375 | const b: u8 = @truncate(u8, a); | |
| 7376 | // b is now 0xcd{#endsyntax#}</pre> | |
| 7378 | {#code_begin|test|truncate#} | |
| 7379 | const std = @import("std"); | |
| 7380 | const assert = std.debug.assert; | |
| 7381 | ||
| 7382 | test "integer truncation" { | |
| 7383 | var a: u16 = 0xabcd; | |
| 7384 | var b: u8 = @truncate(u8, a); | |
| 7385 | assert(b == 0xcd); | |
| 7386 | } | |
| 7387 | {#code_end#} | |
| 7377 | 7388 | <p> |
| 7378 | 7389 | This function always truncates the significant bits of the integer, regardless |
| 7379 | 7390 | of endianness on the target platform. |
| ... | ... | @@ -8840,20 +8851,21 @@ export fn add(a: i32, b: i32) i32 { |
| 8840 | 8851 | return a + b; |
| 8841 | 8852 | } |
| 8842 | 8853 | {#code_end#} |
| 8843 | <p>To make a shared library:</p> | |
| 8854 | <p>To make a static library:</p> | |
| 8844 | 8855 | <pre><code class="shell">$ zig build-lib mathtest.zig |
| 8845 | 8856 | </code></pre> |
| 8846 | <p>To make a static library:</p> | |
| 8847 | <pre><code class="shell">$ zig build-lib mathtest.zig --static | |
| 8857 | <p>To make a shared library:</p> | |
| 8858 | <pre><code class="shell">$ zig build-lib mathtest.zig -dynamic | |
| 8848 | 8859 | </code></pre> |
| 8849 | 8860 | <p>Here is an example with the {#link|Zig Build System#}:</p> |
| 8850 | 8861 | <p class="file">test.c</p> |
| 8851 | 8862 | <pre><code class="cpp">// This header is generated by zig from mathtest.zig |
| 8852 | 8863 | #include "mathtest.h" |
| 8853 | #include &lt;assert.h&gt; | |
| 8864 | #include &lt;stdio.h&gt; | |
| 8854 | 8865 | |
| 8855 | 8866 | int main(int argc, char **argv) { |
| 8856 | assert(add(42, 1337) == 1379); | |
| 8867 | int32_t result = add(42, 1337); | |
| 8868 | printf("%d\n", result); | |
| 8857 | 8869 | return 0; |
| 8858 | 8870 | }</code></pre> |
| 8859 | 8871 | <p class="file">build.zig</p> |
| ... | ... | @@ -8863,10 +8875,10 @@ const Builder = @import("std").build.Builder; |
| 8863 | 8875 | pub fn build(b: *Builder) void { |
| 8864 | 8876 | const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); |
| 8865 | 8877 | |
| 8866 | const exe = b.addCExecutable("test"); | |
| 8867 | exe.addCompileFlags([][]const u8{"-std=c99"}); | |
| 8868 | exe.addSourceFile("test.c"); | |
| 8878 | const exe = b.addExecutable("test", null); | |
| 8879 | exe.addCSourceFile("test.c", [][]const u8{"-std=c99"}); | |
| 8869 | 8880 | exe.linkLibrary(lib); |
| 8881 | exe.linkSystemLibrary("c"); | |
| 8870 | 8882 | |
| 8871 | 8883 | b.default_step.dependOn(&exe.step); |
| 8872 | 8884 | |
| ... | ... | @@ -8877,10 +8889,9 @@ pub fn build(b: *Builder) void { |
| 8877 | 8889 | } |
| 8878 | 8890 | {#code_end#} |
| 8879 | 8891 | <p class="file">terminal</p> |
| 8880 | <pre><code class="shell">$ zig build | |
| 8881 | $ ./test | |
| 8882 | $ echo $? | |
| 8883 | 0</code></pre> | |
| 8892 | <pre><code class="shell">$ zig build test | |
| 8893 | 1379 | |
| 8894 | </code></pre> | |
| 8884 | 8895 | {#see_also|export#} |
| 8885 | 8896 | {#header_close#} |
| 8886 | 8897 | {#header_open|Mixing Object Files#} |
| ... | ... | @@ -8947,6 +8958,33 @@ all your base are belong to us</code></pre> |
| 8947 | 8958 | {#see_also|Targets|Zig Build System#} |
| 8948 | 8959 | {#header_close#} |
| 8949 | 8960 | {#header_close#} |
| 8961 | {#header_open|WebAssembly#} | |
| 8962 | {#header_open|Freestanding#} | |
| 8963 | {#code_begin|exe|wasm#} | |
| 8964 | {#target_wasm#} | |
| 8965 | extern fn print(i32) void; | |
| 8966 | ||
| 8967 | export 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#} | |
| 8975 | const std = @import("std"); | |
| 8976 | ||
| 8977 | pub 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 | 8988 | {#header_open|Targets#} |
| 8951 | 8989 | <p> |
| 8952 | 8990 | Zig supports generating code for all targets that LLVM supports. Here is |
| ... | ... | @@ -9430,8 +9468,6 @@ PrimaryExpr |
| 9430 | 9468 | |
| 9431 | 9469 | IfExpr &lt;- IfPrefix Expr (KEYWORD_else Payload? Expr)? |
| 9432 | 9470 | |
| 9433 | LabeledExpr &lt;- BlockLabel? (Block / LoopExpr) | |
| 9434 | ||
| 9435 | 9471 | Block &lt;- LBRACE Statement* RBRACE |
| 9436 | 9472 | |
| 9437 | 9473 | LoopExpr &lt;- KEYWORD_inline? (ForExpr / WhileExpr) |
| ... | ... | @@ -9440,6 +9476,8 @@ ForExpr &lt;- ForPrefix Expr (KEYWORD_else Expr)? |
| 9440 | 9476 | |
| 9441 | 9477 | WhileExpr &lt;- WhilePrefix Expr (KEYWORD_else Payload? Expr)? |
| 9442 | 9478 | |
| 9479 | CurlySuffixExpr &lt;- TypeExpr InitList? | |
| 9480 | ||
| 9443 | 9481 | InitList |
| 9444 | 9482 | &lt;- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE |
| 9445 | 9483 | / LBRACE Expr (COMMA Expr)* COMMA? RBRACE |
| ... | ... | @@ -9457,6 +9495,7 @@ PrimaryTypeExpr |
| 9457 | 9495 | &lt;- BUILTINIDENTIFIER FnCallArguments |
| 9458 | 9496 | / CHAR_LITERAL |
| 9459 | 9497 | / ContainerDecl |
| 9498 | / DOT IDENTIFIER | |
| 9460 | 9499 | / ErrorSetDecl |
| 9461 | 9500 | / FLOAT |
| 9462 | 9501 | / FnProto |
src-self-hosted/clang.zig created+866| ... | ... | @@ -0,0 +1,866 @@ |
| 1 | pub const struct_ZigClangAPValue = @OpaqueType(); | |
| 2 | pub const struct_ZigClangAPSInt = @OpaqueType(); | |
| 3 | pub const struct_ZigClangASTContext = @OpaqueType(); | |
| 4 | pub const struct_ZigClangASTUnit = @OpaqueType(); | |
| 5 | pub const struct_ZigClangArraySubscriptExpr = @OpaqueType(); | |
| 6 | pub const struct_ZigClangArrayType = @OpaqueType(); | |
| 7 | pub const struct_ZigClangAttributedType = @OpaqueType(); | |
| 8 | pub const struct_ZigClangBinaryOperator = @OpaqueType(); | |
| 9 | pub const struct_ZigClangBreakStmt = @OpaqueType(); | |
| 10 | pub const struct_ZigClangBuiltinType = @OpaqueType(); | |
| 11 | pub const struct_ZigClangCStyleCastExpr = @OpaqueType(); | |
| 12 | pub const struct_ZigClangCallExpr = @OpaqueType(); | |
| 13 | pub const struct_ZigClangCaseStmt = @OpaqueType(); | |
| 14 | pub const struct_ZigClangCompoundAssignOperator = @OpaqueType(); | |
| 15 | pub const ZigClangCompoundStmt = @OpaqueType(); | |
| 16 | pub const struct_ZigClangConditionalOperator = @OpaqueType(); | |
| 17 | pub const struct_ZigClangConstantArrayType = @OpaqueType(); | |
| 18 | pub const struct_ZigClangContinueStmt = @OpaqueType(); | |
| 19 | pub const struct_ZigClangDecayedType = @OpaqueType(); | |
| 20 | pub const struct_ZigClangDecl = @OpaqueType(); | |
| 21 | pub const struct_ZigClangDeclRefExpr = @OpaqueType(); | |
| 22 | pub const struct_ZigClangDeclStmt = @OpaqueType(); | |
| 23 | pub const struct_ZigClangDefaultStmt = @OpaqueType(); | |
| 24 | pub const struct_ZigClangDiagnosticOptions = @OpaqueType(); | |
| 25 | pub const struct_ZigClangDiagnosticsEngine = @OpaqueType(); | |
| 26 | pub const struct_ZigClangDoStmt = @OpaqueType(); | |
| 27 | pub const struct_ZigClangElaboratedType = @OpaqueType(); | |
| 28 | pub const struct_ZigClangEnumConstantDecl = @OpaqueType(); | |
| 29 | pub const struct_ZigClangEnumDecl = @OpaqueType(); | |
| 30 | pub const struct_ZigClangEnumType = @OpaqueType(); | |
| 31 | pub const struct_ZigClangExpr = @OpaqueType(); | |
| 32 | pub const struct_ZigClangFieldDecl = @OpaqueType(); | |
| 33 | pub const struct_ZigClangFileID = @OpaqueType(); | |
| 34 | pub const struct_ZigClangForStmt = @OpaqueType(); | |
| 35 | pub const struct_ZigClangFullSourceLoc = @OpaqueType(); | |
| 36 | pub const ZigClangFunctionDecl = @OpaqueType(); | |
| 37 | pub const struct_ZigClangFunctionProtoType = @OpaqueType(); | |
| 38 | pub const struct_ZigClangIfStmt = @OpaqueType(); | |
| 39 | pub const struct_ZigClangImplicitCastExpr = @OpaqueType(); | |
| 40 | pub const struct_ZigClangIncompleteArrayType = @OpaqueType(); | |
| 41 | pub const struct_ZigClangIntegerLiteral = @OpaqueType(); | |
| 42 | pub const struct_ZigClangMacroDefinitionRecord = @OpaqueType(); | |
| 43 | pub const struct_ZigClangMemberExpr = @OpaqueType(); | |
| 44 | pub const struct_ZigClangNamedDecl = @OpaqueType(); | |
| 45 | pub const struct_ZigClangNone = @OpaqueType(); | |
| 46 | pub const struct_ZigClangPCHContainerOperations = @OpaqueType(); | |
| 47 | pub const struct_ZigClangParenExpr = @OpaqueType(); | |
| 48 | pub const struct_ZigClangParenType = @OpaqueType(); | |
| 49 | pub const struct_ZigClangParmVarDecl = @OpaqueType(); | |
| 50 | pub const struct_ZigClangPointerType = @OpaqueType(); | |
| 51 | pub const struct_ZigClangPreprocessedEntity = @OpaqueType(); | |
| 52 | pub const struct_ZigClangRecordDecl = @OpaqueType(); | |
| 53 | pub const struct_ZigClangRecordType = @OpaqueType(); | |
| 54 | pub const struct_ZigClangReturnStmt = @OpaqueType(); | |
| 55 | pub const struct_ZigClangSkipFunctionBodiesScope = @OpaqueType(); | |
| 56 | pub const struct_ZigClangSourceManager = @OpaqueType(); | |
| 57 | pub const struct_ZigClangSourceRange = @OpaqueType(); | |
| 58 | pub const struct_ZigClangStmt = @OpaqueType(); | |
| 59 | pub const struct_ZigClangStringLiteral = @OpaqueType(); | |
| 60 | pub const struct_ZigClangStringRef = @OpaqueType(); | |
| 61 | pub const struct_ZigClangSwitchStmt = @OpaqueType(); | |
| 62 | pub const struct_ZigClangTagDecl = @OpaqueType(); | |
| 63 | pub const struct_ZigClangType = @OpaqueType(); | |
| 64 | pub const struct_ZigClangTypedefNameDecl = @OpaqueType(); | |
| 65 | pub const struct_ZigClangTypedefType = @OpaqueType(); | |
| 66 | pub const struct_ZigClangUnaryExprOrTypeTraitExpr = @OpaqueType(); | |
| 67 | pub const struct_ZigClangUnaryOperator = @OpaqueType(); | |
| 68 | pub const struct_ZigClangValueDecl = @OpaqueType(); | |
| 69 | pub const struct_ZigClangVarDecl = @OpaqueType(); | |
| 70 | pub const struct_ZigClangWhileStmt = @OpaqueType(); | |
| 71 | pub const ZigClangFunctionType = @OpaqueType(); | |
| 72 | ||
| 73 | pub 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 | ||
| 109 | pub 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 | ||
| 126 | pub 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 | ||
| 176 | pub 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 | ||
| 376 | pub 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 | ||
| 438 | pub 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 | ||
| 453 | pub extern fn ZigClangSourceManager_getSpellingLoc(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation; | |
| 454 | pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*]const u8; | |
| 455 | pub extern fn ZigClangSourceManager_getSpellingLineNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; | |
| 456 | pub extern fn ZigClangSourceManager_getSpellingColumnNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; | |
| 457 | pub extern fn ZigClangSourceManager_getCharacterData(arg0: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8; | |
| 458 | pub extern fn ZigClangASTContext_getPointerType(arg0: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType; | |
| 459 | pub extern fn ZigClangASTUnit_getASTContext(arg0: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext; | |
| 460 | pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager; | |
| 461 | pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool; | |
| 462 | pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) ?*const struct_ZigClangRecordDecl; | |
| 463 | pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl; | |
| 464 | pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl; | |
| 465 | pub extern fn ZigClangEnumDecl_getCanonicalDecl(arg0: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl; | |
| 466 | pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(arg0: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl; | |
| 467 | pub extern fn ZigClangRecordDecl_getDefinition(arg0: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangRecordDecl; | |
| 468 | pub extern fn ZigClangEnumDecl_getDefinition(arg0: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangEnumDecl; | |
| 469 | pub extern fn ZigClangRecordDecl_getLocation(arg0: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation; | |
| 470 | pub extern fn ZigClangEnumDecl_getLocation(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangSourceLocation; | |
| 471 | pub extern fn ZigClangTypedefNameDecl_getLocation(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangSourceLocation; | |
| 472 | pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSourceLocation; | |
| 473 | pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool; | |
| 474 | pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool; | |
| 475 | pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool; | |
| 476 | pub extern fn ZigClangEnumDecl_getIntegerType(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType; | |
| 477 | pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8; | |
| 478 | pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool; | |
| 479 | pub extern fn ZigClangTypedefType_getDecl(arg0: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl; | |
| 480 | pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType; | |
| 481 | pub extern fn ZigClangQualType_getCanonicalType(arg0: struct_ZigClangQualType) struct_ZigClangQualType; | |
| 482 | pub extern fn ZigClangQualType_getTypePtr(self: struct_ZigClangQualType) *const struct_ZigClangType; | |
| 483 | pub extern fn ZigClangQualType_addConst(arg0: [*c]struct_ZigClangQualType) void; | |
| 484 | pub extern fn ZigClangQualType_eq(arg0: struct_ZigClangQualType, arg1: struct_ZigClangQualType) bool; | |
| 485 | pub extern fn ZigClangQualType_isConstQualified(arg0: struct_ZigClangQualType) bool; | |
| 486 | pub extern fn ZigClangQualType_isVolatileQualified(arg0: struct_ZigClangQualType) bool; | |
| 487 | pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType) bool; | |
| 488 | pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass; | |
| 489 | pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; | |
| 490 | pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8; | |
| 491 | pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation; | |
| 492 | pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass; | |
| 493 | pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool; | |
| 494 | pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass; | |
| 495 | pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType; | |
| 496 | pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation; | |
| 497 | pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind; | |
| 498 | pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt; | |
| 499 | pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint; | |
| 500 | pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) ?*const struct_ZigClangAPValue; | |
| 501 | pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPValue; | |
| 502 | pub extern fn ZigClangAPValue_getArraySize(self: ?*const struct_ZigClangAPValue) c_uint; | |
| 503 | pub extern fn ZigClangAPValue_getLValueBase(self: ?*const struct_ZigClangAPValue) struct_ZigClangAPValueLValueBase; | |
| 504 | pub extern fn ZigClangAPSInt_isSigned(self: ?*const struct_ZigClangAPSInt) bool; | |
| 505 | pub extern fn ZigClangAPSInt_isNegative(self: ?*const struct_ZigClangAPSInt) bool; | |
| 506 | pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const struct_ZigClangAPSInt; | |
| 507 | pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void; | |
| 508 | pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64; | |
| 509 | pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint; | |
| 510 | pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr; | |
| 511 | pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void; | |
| 512 | ||
| 513 | pub extern fn ZigClangFunctionDecl_getType(self: *const ZigClangFunctionDecl) struct_ZigClangQualType; | |
| 514 | pub extern fn ZigClangFunctionDecl_getLocation(self: *const ZigClangFunctionDecl) struct_ZigClangSourceLocation; | |
| 515 | pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bool; | |
| 516 | pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass; | |
| 517 | pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl; | |
| 518 | pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt; | |
| 519 | ||
| 520 | pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind; | |
| 521 | ||
| 522 | pub extern fn ZigClangFunctionType_getNoReturnAttr(self: *const ZigClangFunctionType) bool; | |
| 523 | pub extern fn ZigClangFunctionType_getCallConv(self: *const ZigClangFunctionType) ZigClangCallingConv; | |
| 524 | pub extern fn ZigClangFunctionType_getReturnType(self: *const ZigClangFunctionType) ZigClangQualType; | |
| 525 | ||
| 526 | pub extern fn ZigClangFunctionProtoType_isVariadic(self: *const struct_ZigClangFunctionProtoType) bool; | |
| 527 | pub extern fn ZigClangFunctionProtoType_getNumParams(self: *const struct_ZigClangFunctionProtoType) c_uint; | |
| 528 | pub extern fn ZigClangFunctionProtoType_getParamType(self: *const struct_ZigClangFunctionProtoType, i: c_uint) ZigClangQualType; | |
| 529 | ||
| 530 | pub const ZigClangSourceLocation = struct_ZigClangSourceLocation; | |
| 531 | pub const ZigClangQualType = struct_ZigClangQualType; | |
| 532 | pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase; | |
| 533 | pub const ZigClangAPValue = struct_ZigClangAPValue; | |
| 534 | pub const ZigClangAPSInt = struct_ZigClangAPSInt; | |
| 535 | pub const ZigClangASTContext = struct_ZigClangASTContext; | |
| 536 | pub const ZigClangASTUnit = struct_ZigClangASTUnit; | |
| 537 | pub const ZigClangArraySubscriptExpr = struct_ZigClangArraySubscriptExpr; | |
| 538 | pub const ZigClangArrayType = struct_ZigClangArrayType; | |
| 539 | pub const ZigClangAttributedType = struct_ZigClangAttributedType; | |
| 540 | pub const ZigClangBinaryOperator = struct_ZigClangBinaryOperator; | |
| 541 | pub const ZigClangBreakStmt = struct_ZigClangBreakStmt; | |
| 542 | pub const ZigClangBuiltinType = struct_ZigClangBuiltinType; | |
| 543 | pub const ZigClangCStyleCastExpr = struct_ZigClangCStyleCastExpr; | |
| 544 | pub const ZigClangCallExpr = struct_ZigClangCallExpr; | |
| 545 | pub const ZigClangCaseStmt = struct_ZigClangCaseStmt; | |
| 546 | pub const ZigClangCompoundAssignOperator = struct_ZigClangCompoundAssignOperator; | |
| 547 | pub const ZigClangConditionalOperator = struct_ZigClangConditionalOperator; | |
| 548 | pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType; | |
| 549 | pub const ZigClangContinueStmt = struct_ZigClangContinueStmt; | |
| 550 | pub const ZigClangDecayedType = struct_ZigClangDecayedType; | |
| 551 | pub const ZigClangDecl = struct_ZigClangDecl; | |
| 552 | pub const ZigClangDeclRefExpr = struct_ZigClangDeclRefExpr; | |
| 553 | pub const ZigClangDeclStmt = struct_ZigClangDeclStmt; | |
| 554 | pub const ZigClangDefaultStmt = struct_ZigClangDefaultStmt; | |
| 555 | pub const ZigClangDiagnosticOptions = struct_ZigClangDiagnosticOptions; | |
| 556 | pub const ZigClangDiagnosticsEngine = struct_ZigClangDiagnosticsEngine; | |
| 557 | pub const ZigClangDoStmt = struct_ZigClangDoStmt; | |
| 558 | pub const ZigClangElaboratedType = struct_ZigClangElaboratedType; | |
| 559 | pub const ZigClangEnumConstantDecl = struct_ZigClangEnumConstantDecl; | |
| 560 | pub const ZigClangEnumDecl = struct_ZigClangEnumDecl; | |
| 561 | pub const ZigClangEnumType = struct_ZigClangEnumType; | |
| 562 | pub const ZigClangExpr = struct_ZigClangExpr; | |
| 563 | pub const ZigClangFieldDecl = struct_ZigClangFieldDecl; | |
| 564 | pub const ZigClangFileID = struct_ZigClangFileID; | |
| 565 | pub const ZigClangForStmt = struct_ZigClangForStmt; | |
| 566 | pub const ZigClangFullSourceLoc = struct_ZigClangFullSourceLoc; | |
| 567 | pub const ZigClangFunctionProtoType = struct_ZigClangFunctionProtoType; | |
| 568 | pub const ZigClangIfStmt = struct_ZigClangIfStmt; | |
| 569 | pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr; | |
| 570 | pub const ZigClangIncompleteArrayType = struct_ZigClangIncompleteArrayType; | |
| 571 | pub const ZigClangIntegerLiteral = struct_ZigClangIntegerLiteral; | |
| 572 | pub const ZigClangMacroDefinitionRecord = struct_ZigClangMacroDefinitionRecord; | |
| 573 | pub const ZigClangMemberExpr = struct_ZigClangMemberExpr; | |
| 574 | pub const ZigClangNamedDecl = struct_ZigClangNamedDecl; | |
| 575 | pub const ZigClangNone = struct_ZigClangNone; | |
| 576 | pub const ZigClangPCHContainerOperations = struct_ZigClangPCHContainerOperations; | |
| 577 | pub const ZigClangParenExpr = struct_ZigClangParenExpr; | |
| 578 | pub const ZigClangParenType = struct_ZigClangParenType; | |
| 579 | pub const ZigClangParmVarDecl = struct_ZigClangParmVarDecl; | |
| 580 | pub const ZigClangPointerType = struct_ZigClangPointerType; | |
| 581 | pub const ZigClangPreprocessedEntity = struct_ZigClangPreprocessedEntity; | |
| 582 | pub const ZigClangRecordDecl = struct_ZigClangRecordDecl; | |
| 583 | pub const ZigClangRecordType = struct_ZigClangRecordType; | |
| 584 | pub const ZigClangReturnStmt = struct_ZigClangReturnStmt; | |
| 585 | pub const ZigClangSkipFunctionBodiesScope = struct_ZigClangSkipFunctionBodiesScope; | |
| 586 | pub const ZigClangSourceManager = struct_ZigClangSourceManager; | |
| 587 | pub const ZigClangSourceRange = struct_ZigClangSourceRange; | |
| 588 | pub const ZigClangStmt = struct_ZigClangStmt; | |
| 589 | pub const ZigClangStringLiteral = struct_ZigClangStringLiteral; | |
| 590 | pub const ZigClangStringRef = struct_ZigClangStringRef; | |
| 591 | pub const ZigClangSwitchStmt = struct_ZigClangSwitchStmt; | |
| 592 | pub const ZigClangTagDecl = struct_ZigClangTagDecl; | |
| 593 | pub const ZigClangType = struct_ZigClangType; | |
| 594 | pub const ZigClangTypedefNameDecl = struct_ZigClangTypedefNameDecl; | |
| 595 | pub const ZigClangTypedefType = struct_ZigClangTypedefType; | |
| 596 | pub const ZigClangUnaryExprOrTypeTraitExpr = struct_ZigClangUnaryExprOrTypeTraitExpr; | |
| 597 | pub const ZigClangUnaryOperator = struct_ZigClangUnaryOperator; | |
| 598 | pub const ZigClangValueDecl = struct_ZigClangValueDecl; | |
| 599 | pub const ZigClangVarDecl = struct_ZigClangVarDecl; | |
| 600 | pub const ZigClangWhileStmt = struct_ZigClangWhileStmt; | |
| 601 | ||
| 602 | pub const struct_ZigClangSourceLocation = extern struct { | |
| 603 | ID: c_uint, | |
| 604 | }; | |
| 605 | ||
| 606 | pub 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 | }; | |
| 620 | pub extern fn ZigClangErrorMsg_delete(ptr: [*c]Stage2ErrorMsg, len: usize) void; | |
| 621 | ||
| 622 | pub 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 | ||
| 630 | pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind; | |
| 631 | pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*]const u8; | |
| 632 | ||
| 633 | pub 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 | ||
| 710 | pub const struct_ZigClangQualType = extern struct { | |
| 711 | ptr: ?*c_void, | |
| 712 | }; | |
| 713 | ||
| 714 | pub 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 | ||
| 833 | pub 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 | ||
| 854 | pub const ZigClangStorageClass = extern enum { | |
| 855 | None, | |
| 856 | Extern, | |
| 857 | Static, | |
| 858 | PrivateExtern, | |
| 859 | Auto, | |
| 860 | Register, | |
| 861 | }; | |
| 862 | ||
| 863 | pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt; | |
| 864 | ||
| 865 | pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator; | |
| 866 | pub 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 | 569 | 'i', 'u' => blk: { |
| 570 | 570 | for (name[1..]) |byte| |
| 571 | 571 | switch (byte) { |
| 572 | '0'...'9' => {}, | |
| 573 | else => break :blk, | |
| 574 | }; | |
| 572 | '0'...'9' => {}, | |
| 573 | else => break :blk, | |
| 574 | }; | |
| 575 | 575 | const is_signed = name[0] == 'i'; |
| 576 | 576 | const bit_count = std.fmt.parseUnsigned(u32, name[1..], 10) catch |err| switch (err) { |
| 577 | 577 | error.Overflow => return error.Overflow, |
| ... | ... | @@ -841,11 +841,9 @@ pub const Compilation = struct { |
| 841 | 841 | }; |
| 842 | 842 | errdefer self.gpa().free(source_code); |
| 843 | 843 | |
| 844 | const tree = try self.gpa().create(ast.Tree); | |
| 845 | tree.* = try std.zig.parse(self.gpa(), source_code); | |
| 844 | const tree = try std.zig.parse(self.gpa(), source_code); | |
| 846 | 845 | errdefer { |
| 847 | 846 | tree.deinit(); |
| 848 | self.gpa().destroy(tree); | |
| 849 | 847 | } |
| 850 | 848 | |
| 851 | 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 | 625 | const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size); |
| 626 | 626 | defer allocator.free(source_code); |
| 627 | 627 | |
| 628 | var tree = std.zig.parse(allocator, source_code) catch |err| { | |
| 628 | const tree = std.zig.parse(allocator, source_code) catch |err| { | |
| 629 | 629 | try stderr.print("error parsing stdin: {}\n", err); |
| 630 | 630 | os.exit(1); |
| 631 | 631 | }; |
| ... | ... | @@ -633,7 +633,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 633 | 633 | |
| 634 | 634 | var error_it = tree.errors.iterator(0); |
| 635 | 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 | 637 | defer msg.destroy(); |
| 638 | 638 | |
| 639 | 639 | try msg.printToFile(stderr_file, color); |
| ... | ... | @@ -642,12 +642,12 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 642 | 642 | os.exit(1); |
| 643 | 643 | } |
| 644 | 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 | 646 | const code = if (anything_changed) u8(1) else u8(0); |
| 647 | 647 | os.exit(code); |
| 648 | 648 | } |
| 649 | 649 | |
| 650 | _ = try std.zig.render(allocator, stdout, &tree); | |
| 650 | _ = try std.zig.render(allocator, stdout, tree); | |
| 651 | 651 | return; |
| 652 | 652 | } |
| 653 | 653 | |
| ... | ... | @@ -768,7 +768,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro |
| 768 | 768 | }; |
| 769 | 769 | defer fmt.loop.allocator.free(source_code); |
| 770 | 770 | |
| 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 | 772 | try stderr.print("error parsing file '{}': {}\n", file_path, err); |
| 773 | 773 | fmt.any_error = true; |
| 774 | 774 | return; |
| ... | ... | @@ -777,7 +777,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro |
| 777 | 777 | |
| 778 | 778 | var error_it = tree.errors.iterator(0); |
| 779 | 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 | 781 | defer fmt.loop.allocator.destroy(msg); |
| 782 | 782 | |
| 783 | 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 | 788 | } |
| 789 | 789 | |
| 790 | 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 | 792 | if (anything_changed) { |
| 793 | 793 | try stderr.print("{}\n", file_path); |
| 794 | 794 | fmt.any_error = true; |
| ... | ... | @@ -798,7 +798,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro |
| 798 | 798 | const baf = try io.BufferedAtomicFile.create(fmt.loop.allocator, file_path); |
| 799 | 799 | defer baf.destroy(); |
| 800 | 800 | |
| 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 | 802 | if (anything_changed) { |
| 803 | 803 | try stderr.print("{}\n", file_path); |
| 804 | 804 | try baf.finish(); |
| ... | ... | @@ -858,7 +858,7 @@ fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { |
| 858 | 858 | try stdout.write(usage); |
| 859 | 859 | } |
| 860 | 860 | |
| 861 | const info_zen = | |
| 861 | pub const info_zen = | |
| 862 | 862 | \\ |
| 863 | 863 | \\ * Communicate intent precisely. |
| 864 | 864 | \\ * Edge cases matter. |
src-self-hosted/scope.zig-1| ... | ... | @@ -163,7 +163,6 @@ pub const Scope = struct { |
| 163 | 163 | pub fn destroy(self: *AstTree, comp: *Compilation) void { |
| 164 | 164 | comp.gpa().free(self.tree.source); |
| 165 | 165 | self.tree.deinit(); |
| 166 | comp.gpa().destroy(self.tree); | |
| 167 | 166 | comp.gpa().destroy(self); |
| 168 | 167 | } |
| 169 | 168 |
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 | ||
| 4 | const std = @import("std"); | |
| 5 | const builtin = @import("builtin"); | |
| 6 | ||
| 7 | // ABI warning | |
| 8 | export 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 | |
| 15 | export fn stage2_panic(ptr: [*]const u8, len: usize) void { | |
| 16 | @panic(ptr[0..len]); | |
| 17 | } | |
| 18 | ||
| 19 | // ABI warning | |
| 20 | const TranslateMode = extern enum { | |
| 21 | import, | |
| 22 | translate, | |
| 23 | }; | |
| 24 | ||
| 25 | // ABI warning | |
| 26 | const 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 | ||
| 74 | const FILE = std.c.FILE; | |
| 75 | const ast = std.zig.ast; | |
| 76 | const translate_c = @import("translate_c.zig"); | |
| 77 | ||
| 78 | /// Args should have a null terminating last arg. | |
| 79 | export 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 | ||
| 104 | export 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 | ||
| 108 | export 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. | |
| 126 | export 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 | ||
| 138 | fn 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 | ||
| 235 | const 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 | ||
| 256 | fn 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 | ||
| 319 | const 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 | ||
| 328 | fn 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 | ||
| 382 | const os = std.os; | |
| 383 | const io = std.io; | |
| 384 | const mem = std.mem; | |
| 385 | const Allocator = mem.Allocator; | |
| 386 | const ArrayList = std.ArrayList; | |
| 387 | const Buffer = std.Buffer; | |
| 388 | ||
| 389 | const arg = @import("arg.zig"); | |
| 390 | const self_hosted_main = @import("main.zig"); | |
| 391 | const Args = arg.Args; | |
| 392 | const Flag = arg.Flag; | |
| 393 | const errmsg = @import("errmsg.zig"); | |
| 394 | ||
| 395 | var stderr_file: os.File = undefined; | |
| 396 | var stderr: *io.OutStream(os.File.WriteError) = undefined; | |
| 397 | var 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 | ||
| 4 | const std = @import("std"); | |
| 5 | const builtin = @import("builtin"); | |
| 6 | const assert = std.debug.assert; | |
| 7 | const ast = std.zig.ast; | |
| 8 | const Token = std.zig.Token; | |
| 9 | use @import("clang.zig"); | |
| 10 | ||
| 11 | pub const Mode = enum { | |
| 12 | import, | |
| 13 | translate, | |
| 14 | }; | |
| 15 | ||
| 16 | // TODO merge with Type.Fn.CallingConvention | |
| 17 | const CallingConvention = builtin.TypeInfo.CallingConvention; | |
| 18 | ||
| 19 | pub const ClangErrMsg = Stage2ErrorMsg; | |
| 20 | ||
| 21 | pub const Error = error{ | |
| 22 | OutOfMemory, | |
| 23 | UnsupportedType, | |
| 24 | }; | |
| 25 | pub const TransError = error{ | |
| 26 | OutOfMemory, | |
| 27 | UnsupportedTranslation, | |
| 28 | }; | |
| 29 | ||
| 30 | const DeclTable = std.HashMap(usize, void, addrHash, addrEql); | |
| 31 | ||
| 32 | fn 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 | ||
| 42 | fn addrEql(a: usize, b: usize) bool { | |
| 43 | return a == b; | |
| 44 | } | |
| 45 | ||
| 46 | const 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 | ||
| 101 | const TransResult = struct { | |
| 102 | node: *ast.Node, | |
| 103 | node_scope: *Scope, | |
| 104 | child_scope: *Scope, | |
| 105 | }; | |
| 106 | ||
| 107 | const 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 | ||
| 137 | pub 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 | ||
| 216 | extern 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 | ||
| 225 | fn 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 | ||
| 249 | fn 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 | ||
| 311 | const ResultUsed = enum { | |
| 312 | used, | |
| 313 | unused, | |
| 314 | }; | |
| 315 | ||
| 316 | const LRValue = enum { | |
| 317 | l_value, | |
| 318 | r_value, | |
| 319 | }; | |
| 320 | ||
| 321 | fn 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 | ||
| 343 | fn 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 | ||
| 364 | fn 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 | ||
| 376 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { | |
| 377 | try c.tree.root_node.decls.push(decl_node); | |
| 378 | } | |
| 379 | ||
| 380 | fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) Error!*ast.Node { | |
| 381 | return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc); | |
| 382 | } | |
| 383 | ||
| 384 | fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType { | |
| 385 | const canon = ZigClangQualType_getCanonicalType(qt); | |
| 386 | return ZigClangQualType_getTypePtr(canon); | |
| 387 | } | |
| 388 | ||
| 389 | const 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 | ||
| 400 | fn 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 | ||
| 408 | fn 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 | ||
| 447 | const FnDeclContext = struct { | |
| 448 | fn_name: []const u8, | |
| 449 | has_body: bool, | |
| 450 | storage_class: ZigClangStorageClass, | |
| 451 | scope: **Scope, | |
| 452 | is_export: bool, | |
| 453 | }; | |
| 454 | ||
| 455 | fn 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 | ||
| 468 | fn 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 | ||
| 486 | fn 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 | ||
| 497 | fn 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 | ||
| 578 | fn 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 | ||
| 590 | fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []const u8, args: ...) !void { | |
| 591 | _ = try appendTokenFmt(c, .LineComment, "// {}: warning: " ++ format, c.locStr(loc), args); | |
| 592 | } | |
| 593 | ||
| 594 | fn 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 | ||
| 641 | fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex { | |
| 642 | return appendTokenFmt(c, token_id, "{}", bytes); | |
| 643 | } | |
| 644 | ||
| 645 | fn 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 | ||
| 670 | fn 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 | ||
| 680 | pub 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 | 538 | switch (self.base.typ.id) { |
| 539 | 539 | Type.Id.Int => { |
| 540 | 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 | 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 | 545 | break :blk llvm.ConstInt(type_ref, self.big_int.limbs[0], @boolToInt(false)); |
| 546 | 546 | } else if (@sizeOf(std.math.big.Limb) == @sizeOf(u64)) blk: { |
| 547 | 547 | break :blk llvm.ConstIntOfArbitraryPrecision( |
| 548 | 548 | type_ref, |
| 549 | @intCast(c_uint, self.big_int.len), | |
| 549 | @intCast(c_uint, self.big_int.len()), | |
| 550 | 550 | @ptrCast([*]u64, self.big_int.limbs.ptr), |
| 551 | 551 | ); |
| 552 | 552 | } else { |
| 553 | 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 | 557 | Type.Id.ComptimeInt => unreachable, |
| 558 | 558 | else => unreachable, |
src/all_types.hpp+12-1| ... | ... | @@ -55,7 +55,7 @@ struct IrExecutable { |
| 55 | 55 | size_t mem_slot_count; |
| 56 | 56 | size_t next_debug_id; |
| 57 | 57 | size_t *backward_branch_count; |
| 58 | size_t backward_branch_quota; | |
| 58 | size_t *backward_branch_quota; | |
| 59 | 59 | ZigFn *fn_entry; |
| 60 | 60 | Buf *c_import_buf; |
| 61 | 61 | AstNode *source_node; |
| ... | ... | @@ -1350,6 +1350,7 @@ struct ZigFn { |
| 1350 | 1350 | IrExecutable ir_executable; |
| 1351 | 1351 | IrExecutable analyzed_executable; |
| 1352 | 1352 | size_t prealloc_bbc; |
| 1353 | size_t prealloc_backward_branch_quota; | |
| 1353 | 1354 | AstNode **param_source_nodes; |
| 1354 | 1355 | Buf **param_names; |
| 1355 | 1356 | |
| ... | ... | @@ -1855,10 +1856,13 @@ struct CodeGen { |
| 1855 | 1856 | bool strip_debug_symbols; |
| 1856 | 1857 | bool is_test_build; |
| 1857 | 1858 | bool is_single_threaded; |
| 1859 | bool want_single_threaded; | |
| 1858 | 1860 | bool linker_rdynamic; |
| 1859 | 1861 | bool each_lib_rpath; |
| 1860 | 1862 | bool is_dummy_so; |
| 1861 | 1863 | bool disable_gen_h; |
| 1864 | bool bundle_compiler_rt; | |
| 1865 | bool disable_stack_probing; | |
| 1862 | 1866 | |
| 1863 | 1867 | Buf *mmacosx_version_min; |
| 1864 | 1868 | Buf *mios_version_min; |
| ... | ... | @@ -2291,6 +2295,7 @@ enum IrInstructionId { |
| 2291 | 2295 | IrInstructionIdVectorToArray, |
| 2292 | 2296 | IrInstructionIdArrayToVector, |
| 2293 | 2297 | IrInstructionIdAssertZero, |
| 2298 | IrInstructionIdAssertNonNull, | |
| 2294 | 2299 | }; |
| 2295 | 2300 | |
| 2296 | 2301 | struct IrInstruction { |
| ... | ... | @@ -3480,6 +3485,12 @@ struct IrInstructionAssertZero { |
| 3480 | 3485 | IrInstruction *target; |
| 3481 | 3486 | }; |
| 3482 | 3487 | |
| 3488 | struct IrInstructionAssertNonNull { | |
| 3489 | IrInstruction base; | |
| 3490 | ||
| 3491 | IrInstruction *target; | |
| 3492 | }; | |
| 3493 | ||
| 3483 | 3494 | static const size_t slice_ptr_index = 0; |
| 3484 | 3495 | static const size_t slice_len_index = 1; |
| 3485 | 3496 |
src/analyze.cpp+94-59| ... | ... | @@ -969,8 +969,9 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no |
| 969 | 969 | Buf *type_name) |
| 970 | 970 | { |
| 971 | 971 | size_t backward_branch_count = 0; |
| 972 | size_t backward_branch_quota = default_backward_branch_quota; | |
| 972 | 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 | 975 | nullptr, nullptr, node, type_name, nullptr, nullptr); |
| 975 | 976 | } |
| 976 | 977 | |
| ... | ... | @@ -1907,6 +1908,18 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { |
| 1907 | 1908 | return ErrorNone; |
| 1908 | 1909 | } |
| 1909 | 1910 | |
| 1911 | static 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 | ||
| 1910 | 1923 | static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 1911 | 1924 | assert(enum_type->id == ZigTypeIdEnum); |
| 1912 | 1925 | |
| ... | ... | @@ -1964,7 +1977,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 1964 | 1977 | enum_type->abi_size = tag_int_type->abi_size; |
| 1965 | 1978 | enum_type->abi_align = tag_int_type->abi_align; |
| 1966 | 1979 | |
| 1967 | // TODO: Are extern enums allowed to have an init_arg_expr? | |
| 1968 | 1980 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { |
| 1969 | 1981 | ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); |
| 1970 | 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 | 1985 | enum_type->data.enumeration.is_invalid = true; |
| 1974 | 1986 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| 1975 | 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) { | |
| 1977 | enum_type->data.enumeration.is_invalid = true; | |
| 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) { | |
| 1988 | } else if (enum_type->data.enumeration.layout == ContainerLayoutExtern && | |
| 1989 | !type_is_valid_extern_enum_tag(g, wanted_tag_int_type)) { | |
| 1981 | 1990 | enum_type->data.enumeration.is_invalid = true; |
| 1982 | 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'", | |
| 1984 | buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name))); | |
| 1991 | ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr, | |
| 1992 | buf_sprintf("'%s' is not a valid tag type for an extern enum", | |
| 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 | 1996 | } else { |
| 1986 | 1997 | tag_int_type = wanted_tag_int_type; |
| 1987 | 1998 | } |
| 1988 | 1999 | } |
| 2000 | ||
| 1989 | 2001 | enum_type->data.enumeration.tag_int_type = tag_int_type; |
| 1990 | 2002 | enum_type->size_in_bits = tag_int_type->size_in_bits; |
| 1991 | 2003 | enum_type->abi_size = tag_int_type->abi_size; |
| 1992 | 2004 | enum_type->abi_align = tag_int_type->abi_align; |
| 1993 | 2005 | |
| 2006 | BigInt bi_one; | |
| 2007 | bigint_init_unsigned(&bi_one, 1); | |
| 2008 | ||
| 2009 | TypeEnumField *last_enum_field = nullptr; | |
| 2010 | ||
| 1994 | 2011 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 1995 | 2012 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| 1996 | 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 | 2033 | |
| 2017 | 2034 | AstNode *tag_value = field_node->data.struct_field.value; |
| 2018 | 2035 | |
| 2019 | // In this first pass we resolve explicit tag values. | |
| 2020 | // In a second pass we will fill in the unspecified ones. | |
| 2021 | 2036 | if (tag_value != nullptr) { |
| 2037 | // A user-specified value is available | |
| 2022 | 2038 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); |
| 2023 | 2039 | if (type_is_invalid(result->type)) { |
| 2024 | 2040 | enum_type->data.enumeration.is_invalid = true; |
| 2025 | 2041 | continue; |
| 2026 | 2042 | } |
| 2043 | ||
| 2027 | 2044 | assert(result->special != ConstValSpecialRuntime); |
| 2028 | assert(result->type->id == ZigTypeIdInt || | |
| 2029 | result->type->id == ZigTypeIdComptimeInt); | |
| 2030 | auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); | |
| 2031 | if (entry == nullptr) { | |
| 2032 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); | |
| 2045 | assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt); | |
| 2046 | ||
| 2047 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); | |
| 2048 | } else { | |
| 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 | 2053 | } else { |
| 2034 | Buf *val_buf = buf_alloc(); | |
| 2035 | bigint_append_buf(val_buf, &result->data.x_bigint, 10); | |
| 2054 | bigint_init_unsigned(&type_enum_field->value, 0); | |
| 2055 | } | |
| 2036 | 2056 | |
| 2037 | ErrorMsg *msg = add_node_error(g, tag_value, | |
| 2038 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | |
| 2039 | add_error_note(g, msg, entry->value, | |
| 2040 | buf_sprintf("other occurrence here")); | |
| 2057 | // Make sure we can represent this number with tag_int_type | |
| 2058 | if (!bigint_fits_in_bits(&type_enum_field->value, | |
| 2059 | tag_int_type->size_in_bits, | |
| 2060 | tag_int_type->data.integral.is_signed)) { | |
| 2041 | 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 | } | |
| 2046 | 2072 | |
| 2047 | // Now iterate again and populate the unspecified tag values | |
| 2048 | uint32_t next_maybe_unoccupied_index = 0; | |
| 2073 | // Make sure the value is unique | |
| 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; | |
| 2049 | 2077 | |
| 2050 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | |
| 2051 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | |
| 2052 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | |
| 2053 | AstNode *tag_value = field_node->data.struct_field.value; | |
| 2078 | Buf *val_buf = buf_alloc(); | |
| 2079 | bigint_append_buf(val_buf, &type_enum_field->value, 10); | |
| 2054 | 2080 | |
| 2055 | if (tag_value == nullptr) { | |
| 2056 | if (occupied_tag_values.size() == 0) { | |
| 2057 | bigint_init_unsigned(&type_enum_field->value, next_maybe_unoccupied_index); | |
| 2058 | next_maybe_unoccupied_index += 1; | |
| 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 | } | |
| 2081 | ErrorMsg *msg = add_node_error(g, field_node, | |
| 2082 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | |
| 2083 | add_error_note(g, msg, entry->value, | |
| 2084 | buf_sprintf("other occurrence here")); | |
| 2072 | 2085 | } |
| 2086 | ||
| 2087 | last_enum_field = type_enum_field; | |
| 2073 | 2088 | } |
| 2074 | 2089 | |
| 2075 | 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 | 2622 | return ErrorNone; |
| 2608 | 2623 | } |
| 2609 | 2624 | |
| 2610 | static void get_fully_qualified_decl_name(Buf *buf, Tld *tld) { | |
| 2625 | static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, bool is_test) { | |
| 2611 | 2626 | buf_resize(buf, 0); |
| 2612 | 2627 | |
| 2613 | 2628 | Scope *scope = tld->parent_scope; |
| ... | ... | @@ -2617,15 +2632,23 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld) { |
| 2617 | 2632 | ScopeDecls *decls_scope = reinterpret_cast<ScopeDecls *>(scope); |
| 2618 | 2633 | buf_append_buf(buf, &decls_scope->container_type->name); |
| 2619 | 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 | } |
| 2622 | 2643 | |
| 2623 | 2644 | ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) { |
| 2624 | 2645 | ZigFn *fn_entry = allocate<ZigFn>(1); |
| 2625 | 2646 | |
| 2647 | fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota; | |
| 2648 | ||
| 2626 | 2649 | fn_entry->codegen = g; |
| 2627 | 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 | 2652 | fn_entry->analyzed_executable.fn_entry = fn_entry; |
| 2630 | 2653 | fn_entry->ir_executable.fn_entry = fn_entry; |
| 2631 | 2654 | fn_entry->fn_inline = inline_value; |
| ... | ... | @@ -2726,7 +2749,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2726 | 2749 | if (fn_proto->is_export || is_extern) { |
| 2727 | 2750 | buf_init_from_buf(&fn_table_entry->symbol_name, tld_fn->base.name); |
| 2728 | 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 | } |
| 2731 | 2754 | |
| 2732 | 2755 | if (fn_proto->is_export) { |
| ... | ... | @@ -2787,7 +2810,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2787 | 2810 | } else if (source_node->type == NodeTypeTestDecl) { |
| 2788 | 2811 | ZigFn *fn_table_entry = create_fn_raw(g, FnInlineAuto); |
| 2789 | 2812 | |
| 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); | |
| 2791 | 2814 | |
| 2792 | 2815 | tld_fn->fn_entry = fn_table_entry; |
| 2793 | 2816 | |
| ... | ... | @@ -3722,7 +3745,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { |
| 3722 | 3745 | } |
| 3723 | 3746 | if (g->verbose_ir) { |
| 3724 | 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 | 3749 | fprintf(stderr, "\n{ // (IR)\n"); |
| 3727 | 3750 | ir_print(g, stderr, &fn_table_entry->ir_executable, 4); |
| 3728 | 3751 | fprintf(stderr, "}\n"); |
| ... | ... | @@ -5155,11 +5178,10 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5155 | 5178 | if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) { |
| 5156 | 5179 | TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag); |
| 5157 | 5180 | assert(field != nullptr); |
| 5158 | if (type_has_bits(field->type_entry)) { | |
| 5159 | zig_panic("TODO const expr analyze union field value for equality"); | |
| 5160 | } else { | |
| 5181 | if (!type_has_bits(field->type_entry)) | |
| 5161 | 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 | 5186 | return false; |
| 5165 | 5187 | } |
| ... | ... | @@ -6070,7 +6092,7 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents) { |
| 6070 | 6092 | if (g->enable_cache) { |
| 6071 | 6093 | return cache_add_file_fetch(&g->cache_hash, resolved_path, contents); |
| 6072 | 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 | } |
| 6076 | 6098 | |
| ... | ... | @@ -7222,3 +7244,16 @@ ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type) { |
| 7222 | 7244 | assertNoError(type_resolve(g, type, ResolveStatusLLVMFull)); |
| 7223 | 7245 | return type->llvm_di_type; |
| 7224 | 7246 | } |
| 7247 | ||
| 7248 | void 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 | 247 | LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type); |
| 248 | 248 | ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type); |
| 249 | 249 | |
| 250 | void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c); | |
| 251 | ||
| 252 | void src_assert(bool ok, AstNode *source_node); | |
| 253 | ||
| 250 | 254 | #endif |
src/ast_render.cpp+2-4| ... | ... | @@ -296,7 +296,6 @@ void ast_print(FILE *f, AstNode *node, int indent) { |
| 296 | 296 | |
| 297 | 297 | |
| 298 | 298 | struct AstRender { |
| 299 | CodeGen *codegen; | |
| 300 | 299 | int indent; |
| 301 | 300 | int indent_size; |
| 302 | 301 | FILE *f; |
| ... | ... | @@ -633,7 +632,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 633 | 632 | if (is_printable(c)) { |
| 634 | 633 | fprintf(ar->f, "'%c'", c); |
| 635 | 634 | } else { |
| 636 | fprintf(ar->f, "'\\x%x'", (int)c); | |
| 635 | fprintf(ar->f, "'\\x%02x'", (int)c); | |
| 637 | 636 | } |
| 638 | 637 | break; |
| 639 | 638 | } |
| ... | ... | @@ -1170,9 +1169,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 1170 | 1169 | } |
| 1171 | 1170 | |
| 1172 | 1171 | |
| 1173 | void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size) { | |
| 1172 | void ast_render(FILE *f, AstNode *node, int indent_size) { | |
| 1174 | 1173 | AstRender ar = {0}; |
| 1175 | ar.codegen = codegen; | |
| 1176 | 1174 | ar.f = f; |
| 1177 | 1175 | ar.indent_size = indent_size; |
| 1178 | 1176 | ar.indent = 0; |
src/ast_render.hpp+1-1| ... | ... | @@ -15,6 +15,6 @@ |
| 15 | 15 | |
| 16 | 16 | void ast_print(FILE *f, AstNode *node, int indent); |
| 17 | 17 | |
| 18 | void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size); | |
| 18 | void ast_render(FILE *f, AstNode *node, int indent_size); | |
| 19 | 19 | |
| 20 | 20 | #endif |
src/bigint.cpp+10-3| ... | ... | @@ -1395,7 +1395,7 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 1395 | 1395 | uint64_t shift_amt = bigint_as_unsigned(op2); |
| 1396 | 1396 | |
| 1397 | 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 | 1399 | dest->digit_count = 1; |
| 1400 | 1400 | dest->is_negative = op1->is_negative; |
| 1401 | 1401 | bigint_normalize(dest); |
| ... | ... | @@ -1410,12 +1410,19 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 1410 | 1410 | } |
| 1411 | 1411 | |
| 1412 | 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 | 1421 | uint64_t carry = 0; |
| 1415 | 1422 | for (size_t op_digit_index = op1->digit_count - 1;;) { |
| 1416 | 1423 | uint64_t digit = op1_digits[op_digit_index]; |
| 1417 | 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 | 1426 | carry = digit << (64 - leftover_shift_count); |
| 1420 | 1427 | |
| 1421 | 1428 | if (dest_digit_index == 0) { break; } |
src/buffer.hpp-1| ... | ... | @@ -10,7 +10,6 @@ |
| 10 | 10 | |
| 11 | 11 | #include "list.hpp" |
| 12 | 12 | |
| 13 | #include <assert.h> | |
| 14 | 13 | #include <stdint.h> |
| 15 | 14 | #include <ctype.h> |
| 16 | 15 | #include <stdarg.h> |
src/c_tokenizer.cpp+20| ... | ... | @@ -124,6 +124,8 @@ static void begin_token(CTokenize *ctok, CTokId id) { |
| 124 | 124 | case CTokIdAsterisk: |
| 125 | 125 | case CTokIdBang: |
| 126 | 126 | case CTokIdTilde: |
| 127 | case CTokIdShl: | |
| 128 | case CTokIdLt: | |
| 127 | 129 | break; |
| 128 | 130 | } |
| 129 | 131 | } |
| ... | ... | @@ -223,6 +225,10 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) { |
| 223 | 225 | begin_token(ctok, CTokIdDot); |
| 224 | 226 | end_token(ctok); |
| 225 | 227 | break; |
| 228 | case '<': | |
| 229 | begin_token(ctok, CTokIdLt); | |
| 230 | ctok->state = CTokStateGotLt; | |
| 231 | break; | |
| 226 | 232 | case '(': |
| 227 | 233 | begin_token(ctok, CTokIdLParen); |
| 228 | 234 | end_token(ctok); |
| ... | ... | @@ -251,6 +257,19 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) { |
| 251 | 257 | return mark_error(ctok); |
| 252 | 258 | } |
| 253 | 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 | 273 | case CTokStateFloat: |
| 255 | 274 | switch (*c) { |
| 256 | 275 | case '.': |
| ... | ... | @@ -791,6 +810,7 @@ found_end_of_macro: |
| 791 | 810 | case CTokStateNumLitIntSuffixL: |
| 792 | 811 | case CTokStateNumLitIntSuffixUL: |
| 793 | 812 | case CTokStateNumLitIntSuffixLL: |
| 813 | case CTokStateGotLt: | |
| 794 | 814 | end_token(ctok); |
| 795 | 815 | break; |
| 796 | 816 | case CTokStateFloat: |
src/c_tokenizer.hpp+3| ... | ... | @@ -25,6 +25,8 @@ enum CTokId { |
| 25 | 25 | CTokIdAsterisk, |
| 26 | 26 | CTokIdBang, |
| 27 | 27 | CTokIdTilde, |
| 28 | CTokIdShl, | |
| 29 | CTokIdLt, | |
| 28 | 30 | }; |
| 29 | 31 | |
| 30 | 32 | enum CNumLitSuffix { |
| ... | ... | @@ -78,6 +80,7 @@ enum CTokState { |
| 78 | 80 | CTokStateNumLitIntSuffixL, |
| 79 | 81 | CTokStateNumLitIntSuffixLL, |
| 80 | 82 | CTokStateNumLitIntSuffixUL, |
| 83 | CTokStateGotLt, | |
| 81 | 84 | }; |
| 82 | 85 | |
| 83 | 86 | struct CTokenize { |
src/cache_hash.cpp+14-14| ... | ... | @@ -256,10 +256,10 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | 258 | if ((err = hash_file(chf->bin_digest, this_file, contents))) { |
| 259 | os_file_close(this_file); | |
| 259 | os_file_close(&this_file); | |
| 260 | 260 | return err; |
| 261 | 261 | } |
| 262 | os_file_close(this_file); | |
| 262 | os_file_close(&this_file); | |
| 263 | 263 | |
| 264 | 264 | blake2b_update(&ch->blake, chf->bin_digest, 48); |
| 265 | 265 | |
| ... | ... | @@ -300,7 +300,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 300 | 300 | Buf line_buf = BUF_INIT; |
| 301 | 301 | buf_resize(&line_buf, 512); |
| 302 | 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 | 304 | return err; |
| 305 | 305 | } |
| 306 | 306 | |
| ... | ... | @@ -389,14 +389,14 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 389 | 389 | OsFileAttr actual_attr; |
| 390 | 390 | if ((err = os_file_open_r(chf->path, &this_file, &actual_attr))) { |
| 391 | 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 | 393 | return ErrorCacheUnavailable; |
| 394 | 394 | } |
| 395 | 395 | if (chf->attr.mtime.sec == actual_attr.mtime.sec && |
| 396 | 396 | chf->attr.mtime.nsec == actual_attr.mtime.nsec && |
| 397 | 397 | chf->attr.inode == actual_attr.inode) |
| 398 | 398 | { |
| 399 | os_file_close(this_file); | |
| 399 | os_file_close(&this_file); | |
| 400 | 400 | } else { |
| 401 | 401 | // we have to recompute the digest. |
| 402 | 402 | // 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 | 411 | |
| 412 | 412 | uint8_t actual_digest[48]; |
| 413 | 413 | if ((err = hash_file(actual_digest, this_file, nullptr))) { |
| 414 | os_file_close(this_file); | |
| 415 | os_file_close(ch->manifest_file); | |
| 414 | os_file_close(&this_file); | |
| 415 | os_file_close(&ch->manifest_file); | |
| 416 | 416 | return err; |
| 417 | 417 | } |
| 418 | os_file_close(this_file); | |
| 418 | os_file_close(&this_file); | |
| 419 | 419 | if (memcmp(chf->bin_digest, actual_digest, 48) != 0) { |
| 420 | 420 | memcpy(chf->bin_digest, actual_digest, 48); |
| 421 | 421 | // keep going until we have the input file digests |
| ... | ... | @@ -433,12 +433,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 433 | 433 | CacheHashFile *chf = &ch->files.at(file_i); |
| 434 | 434 | if ((err = populate_file_hash(ch, chf, nullptr))) { |
| 435 | 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 | 437 | return ErrorCacheUnavailable; |
| 438 | 438 | } |
| 439 | 439 | } |
| 440 | if (return_code != ErrorNone) { | |
| 441 | os_file_close(ch->manifest_file); | |
| 440 | if (return_code != ErrorNone && return_code != ErrorInvalidFormat) { | |
| 441 | os_file_close(&ch->manifest_file); | |
| 442 | 442 | } |
| 443 | 443 | return return_code; |
| 444 | 444 | } |
| ... | ... | @@ -453,7 +453,7 @@ Error cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents) { |
| 453 | 453 | CacheHashFile *chf = ch->files.add_one(); |
| 454 | 454 | chf->path = resolved_path; |
| 455 | 455 | if ((err = populate_file_hash(ch, chf, contents))) { |
| 456 | os_file_close(ch->manifest_file); | |
| 456 | os_file_close(&ch->manifest_file); | |
| 457 | 457 | return err; |
| 458 | 458 | } |
| 459 | 459 | |
| ... | ... | @@ -469,7 +469,7 @@ Error cache_add_file(CacheHash *ch, Buf *path) { |
| 469 | 469 | Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) { |
| 470 | 470 | Error err; |
| 471 | 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 | 473 | if (verbose) { |
| 474 | 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 | 586 | } |
| 587 | 587 | } |
| 588 | 588 | |
| 589 | os_file_close(ch->manifest_file); | |
| 589 | os_file_close(&ch->manifest_file); | |
| 590 | 590 | } |
| 591 | 591 |
src/codegen.cpp+353-156| ... | ... | @@ -19,6 +19,7 @@ |
| 19 | 19 | #include "target.hpp" |
| 20 | 20 | #include "util.hpp" |
| 21 | 21 | #include "zig_llvm.h" |
| 22 | #include "userland.h" | |
| 22 | 23 | |
| 23 | 24 | #include <stdio.h> |
| 24 | 25 | #include <errno.h> |
| ... | ... | @@ -92,7 +93,7 @@ static const char *symbols_that_llvm_depends_on[] = { |
| 92 | 93 | }; |
| 93 | 94 | |
| 94 | 95 | CodeGen *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 | 97 | ZigLibCInstallation *libc, Buf *cache_dir) |
| 97 | 98 | { |
| 98 | 99 | CodeGen *g = allocate<CodeGen>(1); |
| ... | ... | @@ -100,19 +101,24 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget |
| 100 | 101 | codegen_add_time_event(g, "Initialize"); |
| 101 | 102 | |
| 102 | 103 | g->libc = libc; |
| 103 | g->zig_lib_dir = zig_lib_dir; | |
| 104 | 104 | g->zig_target = target; |
| 105 | 105 | g->cache_dir = cache_dir; |
| 106 | 106 | |
| 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 | 113 | if (override_std_dir == nullptr) { |
| 108 | 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 | 116 | } else { |
| 111 | 117 | g->zig_std_dir = override_std_dir; |
| 112 | 118 | } |
| 113 | 119 | |
| 114 | 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); | |
| 116 | 122 | |
| 117 | 123 | g->build_mode = build_mode; |
| 118 | 124 | g->out_type = out_type; |
| ... | ... | @@ -393,6 +399,15 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { |
| 393 | 399 | } |
| 394 | 400 | } |
| 395 | 401 | |
| 402 | static 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 | ||
| 396 | 411 | static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 397 | 412 | switch (id) { |
| 398 | 413 | case GlobalLinkageIdInternal: |
| ... | ... | @@ -424,7 +439,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { |
| 424 | 439 | } |
| 425 | 440 | |
| 426 | 441 | static 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 | 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 | 510 | auto entry = g->exported_symbol_names.maybe_get(symbol_name); |
| 496 | 511 | if (entry == nullptr) { |
| 497 | 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 | 521 | } else { |
| 499 | 522 | assert(entry->value->id == TldIdFn); |
| 500 | 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 | 596 | addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong"); |
| 574 | 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 | 602 | } else { |
| 578 | 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 | 1008 | LLVMBuildUnreachable(g->builder); |
| 984 | 1009 | } |
| 985 | 1010 | |
| 1011 | // TODO update most callsites to call gen_assertion instead of this | |
| 986 | 1012 | static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) { |
| 987 | 1013 | gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr); |
| 988 | 1014 | } |
| 989 | 1015 | |
| 1016 | static 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 | ||
| 990 | 1024 | static LLVMValueRef get_stacksave_fn_val(CodeGen *g) { |
| 991 | 1025 | if (g->stacksave_fn_val) |
| 992 | 1026 | return g->stacksave_fn_val; |
| ... | ... | @@ -1022,7 +1056,7 @@ static LLVMValueRef get_write_register_fn_val(CodeGen *g) { |
| 1022 | 1056 | // !0 = !{!"sp\00"} |
| 1023 | 1057 | |
| 1024 | 1058 | LLVMTypeRef param_types[] = { |
| 1025 | LLVMMetadataTypeInContext(LLVMGetGlobalContext()), | |
| 1059 | LLVMMetadataTypeInContext(LLVMGetGlobalContext()), | |
| 1026 | 1060 | LLVMIntType(g->pointer_size_bytes * 8), |
| 1027 | 1061 | }; |
| 1028 | 1062 | |
| ... | ... | @@ -1541,11 +1575,19 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 1541 | 1575 | LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_array, offset_ptr_indices, 2); |
| 1542 | 1576 | |
| 1543 | 1577 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false); |
| 1544 | LLVMTypeRef arg_types[] = { | |
| 1545 | get_llvm_type(g, g->ptr_to_stack_trace_type), | |
| 1546 | get_llvm_type(g, g->err_tag_type), | |
| 1547 | }; | |
| 1548 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false); | |
| 1578 | LLVMTypeRef fn_type_ref; | |
| 1579 | if (g->have_err_ret_tracing) { | |
| 1580 | LLVMTypeRef arg_types[] = { | |
| 1581 | get_llvm_type(g, g->ptr_to_stack_trace_type), | |
| 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 | 1591 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); |
| 1550 | 1592 | addLLVMFnAttr(fn_val, "noreturn"); |
| 1551 | 1593 | addLLVMFnAttr(fn_val, "cold"); |
| ... | ... | @@ -1567,7 +1609,15 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 1567 | 1609 | LLVMPositionBuilderAtEnd(g->builder, entry_block); |
| 1568 | 1610 | ZigLLVMClearCurrentDebugLocation(g->builder); |
| 1569 | 1611 | |
| 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 | } | |
| 1571 | 1621 | |
| 1572 | 1622 | LLVMValueRef err_table_indices[] = { |
| 1573 | 1623 | LLVMConstNull(g->builtin_types.entry_usize->llvm_type), |
| ... | ... | @@ -1589,7 +1639,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 1589 | 1639 | LLVMValueRef global_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, global_slice, slice_len_index, ""); |
| 1590 | 1640 | gen_store(g, full_buf_len, global_slice_len_field_ptr, u8_ptr_type); |
| 1591 | 1641 | |
| 1592 | gen_panic(g, global_slice, LLVMGetParam(fn_val, 0)); | |
| 1642 | gen_panic(g, global_slice, err_ret_trace_arg); | |
| 1593 | 1643 | |
| 1594 | 1644 | LLVMPositionBuilderAtEnd(g->builder, prev_block); |
| 1595 | 1645 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); |
| ... | ... | @@ -1625,17 +1675,26 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) { |
| 1625 | 1675 | |
| 1626 | 1676 | static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) { |
| 1627 | 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); | |
| 1629 | if (err_ret_trace_val == nullptr) { | |
| 1630 | ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g); | |
| 1631 | err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type)); | |
| 1678 | LLVMValueRef call_instruction; | |
| 1679 | if (g->have_err_ret_tracing) { | |
| 1680 | LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope); | |
| 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 | 1698 | LLVMSetTailCall(call_instruction, true); |
| 1640 | 1699 | LLVMBuildUnreachable(g->builder); |
| 1641 | 1700 | } |
| ... | ... | @@ -3452,6 +3511,15 @@ static bool want_valgrind_support(CodeGen *g) { |
| 3452 | 3511 | zig_unreachable(); |
| 3453 | 3512 | } |
| 3454 | 3513 | |
| 3514 | static 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 | ||
| 3455 | 3523 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) { |
| 3456 | 3524 | assert(type_has_bits(value_type)); |
| 3457 | 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 | 3534 | ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false); |
| 3467 | 3535 | // then tell valgrind that the memory is undefined even though we just memset it |
| 3468 | 3536 | if (want_valgrind_support(g)) { |
| 3469 | static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; | |
| 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); | |
| 3537 | gen_valgrind_undef(g, dest_ptr, byte_count); | |
| 3474 | 3538 | } |
| 3475 | 3539 | } |
| 3476 | 3540 | |
| ... | ... | @@ -3480,14 +3544,14 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir |
| 3480 | 3544 | if (!type_has_bits(ptr_type)) |
| 3481 | 3545 | return nullptr; |
| 3482 | 3546 | |
| 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 | 3548 | if (have_init_expr) { |
| 3485 | 3549 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); |
| 3486 | 3550 | LLVMValueRef value = ir_llvm_value(g, instruction->value); |
| 3487 | 3551 | gen_assign_raw(g, ptr, ptr_type, value); |
| 3488 | 3552 | } else if (ir_want_runtime_safety(g, &instruction->base)) { |
| 3489 | 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 | 3556 | return nullptr; |
| 3493 | 3557 | } |
| ... | ... | @@ -3690,7 +3754,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3690 | 3754 | } |
| 3691 | 3755 | FnWalk fn_walk = {}; |
| 3692 | 3756 | fn_walk.id = FnWalkIdCall; |
| 3693 | fn_walk.data.call.inst = instruction; | |
| 3757 | fn_walk.data.call.inst = instruction; | |
| 3694 | 3758 | fn_walk.data.call.is_var_args = is_var_args; |
| 3695 | 3759 | fn_walk.data.call.gen_param_values = &gen_param_values; |
| 3696 | 3760 | walk_function_params(g, fn_type, &fn_walk); |
| ... | ... | @@ -3710,7 +3774,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3710 | 3774 | |
| 3711 | 3775 | LLVMCallConv llvm_cc = get_llvm_cc(g, cc); |
| 3712 | 3776 | LLVMValueRef result; |
| 3713 | ||
| 3777 | ||
| 3714 | 3778 | if (instruction->new_stack == nullptr) { |
| 3715 | 3779 | result = ZigLLVMBuildCall(g->builder, fn_val, |
| 3716 | 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 | 4032 | } |
| 3969 | 4033 | |
| 3970 | 4034 | static 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 | 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 | 4040 | return maybe_handle; |
| 3975 | } else { | |
| 3976 | bool is_scalar = !handle_is_ptr(maybe_type); | |
| 3977 | if (is_scalar) { | |
| 3978 | return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), ""); | |
| 3979 | } else { | |
| 3980 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); | |
| 3981 | return gen_load_untyped(g, maybe_field_ptr, 0, false, ""); | |
| 3982 | } | |
| 3983 | } | |
| 4041 | ||
| 4042 | bool is_scalar = !handle_is_ptr(maybe_type); | |
| 4043 | if (is_scalar) | |
| 4044 | return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), ""); | |
| 4045 | ||
| 4046 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); | |
| 4047 | return gen_load_untyped(g, maybe_field_ptr, 0, false, ""); | |
| 3984 | 4048 | } |
| 3985 | 4049 | |
| 3986 | 4050 | static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable, |
| ... | ... | @@ -4001,8 +4065,8 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec |
| 4001 | 4065 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) { |
| 4002 | 4066 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); |
| 4003 | 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 | 4068 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail"); |
| 4069 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk"); | |
| 4006 | 4070 | LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block); |
| 4007 | 4071 | |
| 4008 | 4072 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| ... | ... | @@ -4190,7 +4254,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { |
| 4190 | 4254 | LLVMTypeRef tag_int_llvm_type = get_llvm_type(g, tag_int_type); |
| 4191 | 4255 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0), |
| 4192 | 4256 | &tag_int_llvm_type, 1, false); |
| 4193 | ||
| 4257 | ||
| 4194 | 4258 | Buf *fn_name = get_mangled_name(g, buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name)), false); |
| 4195 | 4259 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); |
| 4196 | 4260 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); |
| ... | ... | @@ -4490,17 +4554,27 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrI |
| 4490 | 4554 | |
| 4491 | 4555 | static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrInstructionMemset *instruction) { |
| 4492 | 4556 | LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); |
| 4493 | LLVMValueRef char_val = ir_llvm_value(g, instruction->byte); | |
| 4494 | 4557 | LLVMValueRef len_val = ir_llvm_value(g, instruction->count); |
| 4495 | 4558 | |
| 4496 | 4559 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 4497 | ||
| 4498 | 4560 | LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, ""); |
| 4499 | 4561 | |
| 4500 | 4562 | ZigType *ptr_type = instruction->dest_ptr->value.type; |
| 4501 | 4563 | assert(ptr_type->id == ZigTypeIdPointer); |
| 4502 | 4564 | |
| 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 | 4578 | return nullptr; |
| 4505 | 4579 | } |
| 4506 | 4580 | |
| ... | ... | @@ -5422,6 +5496,31 @@ static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, |
| 5422 | 5496 | return nullptr; |
| 5423 | 5497 | } |
| 5424 | 5498 | |
| 5499 | static 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 | ||
| 5425 | 5524 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 5426 | 5525 | AstNode *source_node = instruction->source_node; |
| 5427 | 5526 | Scope *scope = instruction->scope; |
| ... | ... | @@ -5676,6 +5775,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5676 | 5775 | return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction); |
| 5677 | 5776 | case IrInstructionIdAssertZero: |
| 5678 | 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 | 5780 | case IrInstructionIdResizeSlice: |
| 5680 | 5781 | return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction); |
| 5681 | 5782 | } |
| ... | ... | @@ -6585,7 +6686,7 @@ static void validate_inline_fns(CodeGen *g) { |
| 6585 | 6686 | } |
| 6586 | 6687 | |
| 6587 | 6688 | static 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 | 6690 | LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel); |
| 6590 | 6691 | } |
| 6591 | 6692 | } |
| ... | ... | @@ -6905,7 +7006,7 @@ static void do_code_gen(CodeGen *g) { |
| 6905 | 7006 | ir_render(g, fn_table_entry); |
| 6906 | 7007 | |
| 6907 | 7008 | } |
| 6908 | ||
| 7009 | ||
| 6909 | 7010 | assert(!g->errors.length); |
| 6910 | 7011 | |
| 6911 | 7012 | if (buf_len(&g->global_asm) != 0) { |
| ... | ... | @@ -6942,6 +7043,11 @@ static void zig_llvm_emit_output(CodeGen *g) { |
| 6942 | 7043 | } |
| 6943 | 7044 | validate_inline_fns(g); |
| 6944 | 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 | 7051 | break; |
| 6946 | 7052 | |
| 6947 | 7053 | case EmitFileTypeAssembly: |
| ... | ... | @@ -7337,9 +7443,26 @@ static bool detect_pic(CodeGen *g) { |
| 7337 | 7443 | zig_unreachable(); |
| 7338 | 7444 | } |
| 7339 | 7445 | |
| 7446 | static 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 | ||
| 7455 | static 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 | ||
| 7340 | 7461 | Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7341 | 7462 | g->have_dynamic_link = detect_dynamic_link(g); |
| 7342 | 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); | |
| 7343 | 7466 | |
| 7344 | 7467 | Buf *contents = buf_alloc(); |
| 7345 | 7468 | |
| ... | ... | @@ -7696,7 +7819,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7696 | 7819 | assert(ContainerLayoutAuto == 0); |
| 7697 | 7820 | assert(ContainerLayoutExtern == 1); |
| 7698 | 7821 | assert(ContainerLayoutPacked == 2); |
| 7699 | ||
| 7822 | ||
| 7700 | 7823 | assert(CallingConventionUnspecified == 0); |
| 7701 | 7824 | assert(CallingConventionC == 1); |
| 7702 | 7825 | assert(CallingConventionCold == 2); |
| ... | ... | @@ -7814,7 +7937,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 7814 | 7937 | Buf *contents; |
| 7815 | 7938 | if (hit) { |
| 7816 | 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 | 7941 | fprintf(stderr, "Unable to open '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err)); |
| 7819 | 7942 | exit(1); |
| 7820 | 7943 | } |
| ... | ... | @@ -7844,6 +7967,12 @@ static void init(CodeGen *g) { |
| 7844 | 7967 | |
| 7845 | 7968 | g->have_dynamic_link = detect_dynamic_link(g); |
| 7846 | 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 | } | |
| 7847 | 7976 | |
| 7848 | 7977 | if (g->is_test_build) { |
| 7849 | 7978 | g->subsystem = TargetSubsystemConsole; |
| ... | ... | @@ -7953,8 +8082,6 @@ static void init(CodeGen *g) { |
| 7953 | 8082 | } |
| 7954 | 8083 | } |
| 7955 | 8084 | |
| 7956 | g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease && g->build_mode != BuildModeSmallRelease; | |
| 7957 | ||
| 7958 | 8085 | define_builtin_fns(g); |
| 7959 | 8086 | Error err; |
| 7960 | 8087 | if ((err = define_builtin_compile_vars(g))) { |
| ... | ... | @@ -8093,7 +8220,126 @@ static void detect_libc(CodeGen *g) { |
| 8093 | 8220 | } |
| 8094 | 8221 | } |
| 8095 | 8222 | |
| 8096 | AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) { | |
| 8223 | // does not add the "cc" arg | |
| 8224 | void 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 | ||
| 8341 | void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation) { | |
| 8342 | Error err; | |
| 8097 | 8343 | Buf *src_basename = buf_alloc(); |
| 8098 | 8344 | Buf *src_dirname = buf_alloc(); |
| 8099 | 8345 | os_path_split(full_path, src_dirname, src_basename); |
| ... | ... | @@ -8105,13 +8351,47 @@ AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) { |
| 8105 | 8351 | |
| 8106 | 8352 | init(g); |
| 8107 | 8353 | |
| 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 | 8377 | AstNode *root_node; |
| 8110 | Error err = parse_h_file(&root_node, &errors, buf_ptr(full_path), g, nullptr); | |
| 8111 | 8378 | |
| 8112 | if (err == ErrorCCompileErrors && errors.length > 0) { | |
| 8113 | for (size_t i = 0; i < errors.length; i += 1) { | |
| 8114 | ErrorMsg *err_msg = errors.at(i); | |
| 8379 | if (use_userland_implementation) { | |
| 8380 | err = stage2_translate_c(&ast, &errors_ptr, &errors_len, | |
| 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 | 8395 | print_err_msg(err_msg, g->err_color); |
| 8116 | 8396 | } |
| 8117 | 8397 | exit(1); |
| ... | ... | @@ -8122,7 +8402,12 @@ AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) { |
| 8122 | 8402 | exit(1); |
| 8123 | 8403 | } |
| 8124 | 8404 | |
| 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 | } |
| 8127 | 8412 | |
| 8128 | 8413 | static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) { |
| ... | ... | @@ -8233,7 +8518,7 @@ static void gen_root_source(CodeGen *g) { |
| 8233 | 8518 | Error err; |
| 8234 | 8519 | // No need for using the caching system for this file fetch because it is handled |
| 8235 | 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 | 8522 | fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(resolved_path), err_str(err)); |
| 8238 | 8523 | exit(1); |
| 8239 | 8524 | } |
| ... | ... | @@ -8308,7 +8593,7 @@ static void gen_global_asm(CodeGen *g) { |
| 8308 | 8593 | Buf *asm_file = g->assembly_files.at(i); |
| 8309 | 8594 | // No need to use the caching system for these fetches because they |
| 8310 | 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 | 8597 | zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err)); |
| 8313 | 8598 | } |
| 8314 | 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 | 8726 | args.append("cc"); |
| 8442 | 8727 | |
| 8443 | 8728 | Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path)); |
| 8444 | args.append("-MD"); | |
| 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 | } | |
| 8729 | add_cc_args(g, args, buf_ptr(out_dep_path), false); | |
| 8528 | 8730 | |
| 8529 | 8731 | args.append("-o"); |
| 8530 | 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 | 8734 | args.append("-c"); |
| 8533 | 8735 | args.append(buf_ptr(c_source_file)); |
| 8534 | 8736 | |
| 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 | 8737 | for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) { |
| 8544 | 8738 | args.append(c_file->args.at(arg_i)); |
| 8545 | 8739 | } |
| 8546 | 8740 | |
| 8547 | ||
| 8548 | 8741 | if (g->verbose_cc) { |
| 8549 | 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 | 9351 | cache_bool(ch, g->linker_rdynamic); |
| 9159 | 9352 | cache_bool(ch, g->each_lib_rpath); |
| 9160 | 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 | 9356 | cache_bool(ch, want_valgrind_support(g)); |
| 9162 | 9357 | cache_bool(ch, g->have_pic); |
| 9163 | 9358 | cache_bool(ch, g->have_dynamic_link); |
| ... | ... | @@ -9268,6 +9463,8 @@ void codegen_build_and_link(CodeGen *g) { |
| 9268 | 9463 | |
| 9269 | 9464 | g->have_dynamic_link = detect_dynamic_link(g); |
| 9270 | 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 | 9468 | detect_libc(g); |
| 9272 | 9469 | detect_dynamic_linker(g); |
| 9273 | 9470 |
src/codegen.hpp+3-1| ... | ... | @@ -12,6 +12,7 @@ |
| 12 | 12 | #include "errmsg.hpp" |
| 13 | 13 | #include "target.hpp" |
| 14 | 14 | #include "libc_installation.hpp" |
| 15 | #include "userland.h" | |
| 15 | 16 | |
| 16 | 17 | #include <stdio.h> |
| 17 | 18 | |
| ... | ... | @@ -43,6 +44,7 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc |
| 43 | 44 | void codegen_add_time_event(CodeGen *g, const char *name); |
| 44 | 45 | void codegen_print_timing_report(CodeGen *g, FILE *f); |
| 45 | 46 | void codegen_link(CodeGen *g); |
| 47 | void zig_link_add_compiler_rt(CodeGen *g); | |
| 46 | 48 | void codegen_build_and_link(CodeGen *g); |
| 47 | 49 | |
| 48 | 50 | ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path, |
| ... | ... | @@ -50,7 +52,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c |
| 50 | 52 | void codegen_add_assembly(CodeGen *g, Buf *path); |
| 51 | 53 | void codegen_add_object(CodeGen *g, Buf *object_path); |
| 52 | 54 | |
| 53 | AstNode *codegen_translate_c(CodeGen *g, Buf *path); | |
| 55 | void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation); | |
| 54 | 56 | |
| 55 | 57 | Buf *codegen_generate_builtin_source(CodeGen *g); |
| 56 | 58 |
src/compiler.cpp+4-4| ... | ... | @@ -179,24 +179,24 @@ Buf *get_zig_lib_dir(void) { |
| 179 | 179 | return &saved_lib_dir; |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | Buf *get_zig_std_dir() { | |
| 182 | Buf *get_zig_std_dir(Buf *zig_lib_dir) { | |
| 183 | 183 | if (saved_std_dir.list.length != 0) { |
| 184 | 184 | return &saved_std_dir; |
| 185 | 185 | } |
| 186 | 186 | buf_resize(&saved_std_dir, 0); |
| 187 | 187 | |
| 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); | |
| 189 | 189 | |
| 190 | 190 | return &saved_std_dir; |
| 191 | 191 | } |
| 192 | 192 | |
| 193 | Buf *get_zig_special_dir() { | |
| 193 | Buf *get_zig_special_dir(Buf *zig_lib_dir) { | |
| 194 | 194 | if (saved_special_dir.list.length != 0) { |
| 195 | 195 | return &saved_special_dir; |
| 196 | 196 | } |
| 197 | 197 | buf_resize(&saved_special_dir, 0); |
| 198 | 198 | |
| 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); | |
| 200 | 200 | |
| 201 | 201 | return &saved_special_dir; |
| 202 | 202 | } |
src/compiler.hpp+2-2| ... | ... | @@ -16,7 +16,7 @@ Error get_compiler_id(Buf **result); |
| 16 | 16 | Buf *get_self_dynamic_linker_path(void); |
| 17 | 17 | |
| 18 | 18 | Buf *get_zig_lib_dir(void); |
| 19 | Buf *get_zig_special_dir(void); | |
| 20 | Buf *get_zig_std_dir(void); | |
| 19 | Buf *get_zig_special_dir(Buf *zig_lib_dir); | |
| 20 | Buf *get_zig_std_dir(Buf *zig_lib_dir); | |
| 21 | 21 | |
| 22 | 22 | #endif |
src/error.cpp+4| ... | ... | @@ -50,6 +50,10 @@ const char *err_str(Error err) { |
| 50 | 50 | case ErrorUnexpectedWriteFailure: return "unexpected write failure"; |
| 51 | 51 | case ErrorUnexpectedSeekFailure: return "unexpected seek failure"; |
| 52 | 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 | 58 | return "(invalid error)"; |
| 55 | 59 | } |
src/error.hpp+2-48| ... | ... | @@ -8,56 +8,10 @@ |
| 8 | 8 | #ifndef ERROR_HPP |
| 9 | 9 | #define ERROR_HPP |
| 10 | 10 | |
| 11 | #include <assert.h> | |
| 12 | ||
| 13 | enum 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 | }; | |
| 11 | #include "userland.h" | |
| 56 | 12 | |
| 57 | 13 | const char *err_str(Error err); |
| 58 | 14 | |
| 59 | static inline void assertNoError(Error err) { | |
| 60 | assert(err == ErrorNone); | |
| 61 | } | |
| 15 | #define assertNoError(err) assert((err) == ErrorNone); | |
| 62 | 16 | |
| 63 | 17 | #endif |
src/ir.cpp+291-88| ... | ... | @@ -188,6 +188,19 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c |
| 188 | 188 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| 189 | 189 | assert(const_val->special == ConstValSpecialStatic); |
| 190 | 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 | 204 | switch (const_val->data.x_ptr.special) { |
| 192 | 205 | case ConstPtrSpecialInvalid: |
| 193 | 206 | zig_unreachable(); |
| ... | ... | @@ -356,6 +369,18 @@ static void ir_ref_var(ZigVar *var) { |
| 356 | 369 | var->ref_count += 1; |
| 357 | 370 | } |
| 358 | 371 | |
| 372 | ZigType *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 | ||
| 359 | 384 | static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) { |
| 360 | 385 | IrBasicBlock *result = allocate<IrBasicBlock>(1); |
| 361 | 386 | result->scope = scope; |
| ... | ... | @@ -978,6 +1003,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertZero *) { |
| 978 | 1003 | return IrInstructionIdAssertZero; |
| 979 | 1004 | } |
| 980 | 1005 | |
| 1006 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *) { | |
| 1007 | return IrInstructionIdAssertNonNull; | |
| 1008 | } | |
| 1009 | ||
| 981 | 1010 | template<typename T> |
| 982 | 1011 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 983 | 1012 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -3012,6 +3041,19 @@ static IrInstruction *ir_build_assert_zero(IrAnalyze *ira, IrInstruction *source |
| 3012 | 3041 | return &instruction->base; |
| 3013 | 3042 | } |
| 3014 | 3043 | |
| 3044 | static 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 | ||
| 3015 | 3057 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 3016 | 3058 | results[ReturnKindUnconditional] = 0; |
| 3017 | 3059 | results[ReturnKindError] = 0; |
| ... | ... | @@ -5391,10 +5433,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5391 | 5433 | add_node_error(irb->codegen, variable_declaration->section_expr, |
| 5392 | 5434 | buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); |
| 5393 | 5435 | } |
| 5394 | if (variable_declaration->threadlocal_tok != nullptr) { | |
| 5395 | add_token_error(irb->codegen, node->owner, variable_declaration->threadlocal_tok, | |
| 5396 | buf_sprintf("function-local variable '%s' cannot be threadlocal", buf_ptr(variable_declaration->symbol))); | |
| 5397 | } | |
| 5436 | ||
| 5437 | // Parser should ensure that this never happens | |
| 5438 | assert(variable_declaration->threadlocal_tok == nullptr); | |
| 5398 | 5439 | |
| 5399 | 5440 | // Temporarily set the name of the IrExecutable to the VariableDeclaration |
| 5400 | 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 | 5808 | |
| 5768 | 5809 | IrInstruction *body_result = ir_gen_node(irb, body_node, &loop_scope->base); |
| 5769 | 5810 | |
| 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 | 5813 | ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); |
| 5814 | } | |
| 5772 | 5815 | |
| 5773 | 5816 | ir_set_cursor_at_end_and_append_block(irb, continue_block); |
| 5774 | 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 | 7934 | return ir_add_error_node(ira, source_instruction->source_node, msg); |
| 7892 | 7935 | } |
| 7893 | 7936 | |
| 7937 | static void ir_assert(bool ok, IrInstruction *source_instruction) { | |
| 7938 | if (ok) return; | |
| 7939 | src_assert(ok, source_instruction->source_node); | |
| 7940 | } | |
| 7941 | ||
| 7894 | 7942 | // This function takes a comptime ptr and makes the child const value conform to the type |
| 7895 | 7943 | // described by the pointer. |
| 7896 | 7944 | static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, |
| ... | ... | @@ -7943,7 +7991,7 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec |
| 7943 | 7991 | return &codegen->invalid_instruction->value; |
| 7944 | 7992 | } |
| 7945 | 7993 | } |
| 7946 | return &codegen->invalid_instruction->value; | |
| 7994 | zig_unreachable(); | |
| 7947 | 7995 | } |
| 7948 | 7996 | |
| 7949 | 7997 | static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) { |
| ... | ... | @@ -8088,6 +8136,8 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) { |
| 8088 | 8136 | case 64: |
| 8089 | 8137 | dest_val->data.x_f64 = bigfloat_to_f64(bigfloat); |
| 8090 | 8138 | break; |
| 8139 | case 80: | |
| 8140 | zig_panic("TODO"); | |
| 8091 | 8141 | case 128: |
| 8092 | 8142 | dest_val->data.x_f128 = bigfloat_to_f128(bigfloat); |
| 8093 | 8143 | break; |
| ... | ... | @@ -9904,6 +9954,7 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *t |
| 9904 | 9954 | |
| 9905 | 9955 | static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) { |
| 9906 | 9956 | ConstGlobalRefs *global_refs = dest->global_refs; |
| 9957 | assert(!same_global_refs || src->global_refs != nullptr); | |
| 9907 | 9958 | *dest = *src; |
| 9908 | 9959 | if (!same_global_refs) { |
| 9909 | 9960 | dest->global_refs = global_refs; |
| ... | ... | @@ -9949,6 +10000,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 9949 | 10000 | case 64: |
| 9950 | 10001 | const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat); |
| 9951 | 10002 | break; |
| 10003 | case 80: | |
| 10004 | zig_panic("TODO"); | |
| 9952 | 10005 | case 128: |
| 9953 | 10006 | const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat); |
| 9954 | 10007 | break; |
| ... | ... | @@ -9978,6 +10031,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 9978 | 10031 | case 64: |
| 9979 | 10032 | const_val->data.x_f64 = bigfloat_to_f64(&bigfloat); |
| 9980 | 10033 | break; |
| 10034 | case 80: | |
| 10035 | zig_panic("TODO"); | |
| 9981 | 10036 | case 128: |
| 9982 | 10037 | const_val->data.x_f128 = bigfloat_to_f128(&bigfloat); |
| 9983 | 10038 | break; |
| ... | ... | @@ -10170,6 +10225,7 @@ static void ir_finish_bb(IrAnalyze *ira) { |
| 10170 | 10225 | ira->instruction_index += 1; |
| 10171 | 10226 | } |
| 10172 | 10227 | |
| 10228 | size_t my_old_bb_index = ira->old_bb_index; | |
| 10173 | 10229 | ira->old_bb_index += 1; |
| 10174 | 10230 | |
| 10175 | 10231 | bool need_repeat = true; |
| ... | ... | @@ -10180,7 +10236,7 @@ static void ir_finish_bb(IrAnalyze *ira) { |
| 10180 | 10236 | ira->old_bb_index += 1; |
| 10181 | 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 | 10240 | ira->old_bb_index += 1; |
| 10185 | 10241 | continue; |
| 10186 | 10242 | } |
| ... | ... | @@ -10205,16 +10261,18 @@ static IrInstruction *ir_unreach_error(IrAnalyze *ira) { |
| 10205 | 10261 | |
| 10206 | 10262 | static bool ir_emit_backward_branch(IrAnalyze *ira, IrInstruction *source_instruction) { |
| 10207 | 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; | |
| 10209 | 10265 | |
| 10210 | 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 | 10269 | return false; |
| 10213 | 10270 | } |
| 10214 | 10271 | |
| 10215 | 10272 | *bbc += 1; |
| 10216 | if (*bbc > quota) { | |
| 10217 | ir_add_error(ira, source_instruction, buf_sprintf("evaluation exceeded %" ZIG_PRI_usize " backwards branches", quota)); | |
| 10273 | if (*bbc > *quota) { | |
| 10274 | ir_add_error(ira, source_instruction, | |
| 10275 | buf_sprintf("evaluation exceeded %" ZIG_PRI_usize " backwards branches", *quota)); | |
| 10218 | 10276 | return false; |
| 10219 | 10277 | } |
| 10220 | 10278 | return true; |
| ... | ... | @@ -10249,6 +10307,12 @@ static IrInstruction *ir_const_bool(IrAnalyze *ira, IrInstruction *source_instru |
| 10249 | 10307 | return result; |
| 10250 | 10308 | } |
| 10251 | 10309 | |
| 10310 | static 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 | ||
| 10252 | 10316 | static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) { |
| 10253 | 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 | 10359 | } |
| 10296 | 10360 | |
| 10297 | 10361 | ConstExprValue *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 | 10363 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, |
| 10300 | 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 | 10381 | |
| 10318 | 10382 | if (codegen->verbose_ir) { |
| 10319 | 10383 | fprintf(stderr, "\nSource: "); |
| 10320 | ast_render(codegen, stderr, node, 4); | |
| 10384 | ast_render(stderr, node, 4); | |
| 10321 | 10385 | fprintf(stderr, "\n{ // (IR)\n"); |
| 10322 | 10386 | ir_print(codegen, stderr, ir_executable, 2); |
| 10323 | 10387 | fprintf(stderr, "}\n"); |
| ... | ... | @@ -10562,19 +10626,34 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so |
| 10562 | 10626 | assert(instr_is_comptime(value)); |
| 10563 | 10627 | |
| 10564 | 10628 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| 10565 | assert(val); | |
| 10629 | assert(val != nullptr); | |
| 10566 | 10630 | |
| 10567 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node); | |
| 10568 | const_instruction->base.value.special = ConstValSpecialStatic; | |
| 10631 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10632 | result->value.special = ConstValSpecialStatic; | |
| 10569 | 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 | 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 | 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; | |
| 10577 | return &const_instruction->base; | |
| 10640 | return result; | |
| 10641 | } | |
| 10642 | ||
| 10643 | static 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 | } |
| 10579 | 10658 | |
| 10580 | 10659 | static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value, |
| ... | ... | @@ -11576,6 +11655,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 11576 | 11655 | return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type); |
| 11577 | 11656 | } |
| 11578 | 11657 | |
| 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 | 11665 | // cast from [N]T to E![]const T |
| 11580 | 11666 | if (wanted_type->id == ZigTypeIdErrorUnion && |
| 11581 | 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 | 12279 | |
| 12194 | 12280 | IrBinOp op_id = bin_op_instruction->op_id; |
| 12195 | 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 | 12285 | ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdOptional) || |
| 12198 | (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdOptional) || | |
| 12199 | (op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull))) | |
| 12286 | (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdOptional))) | |
| 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 | 12288 | IrInstruction *maybe_op; |
| 12205 | 12289 | if (op1->value.type->id == ZigTypeIdNull) { |
| 12206 | 12290 | maybe_op = op2; |
| ... | ... | @@ -12222,6 +12306,44 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 12222 | 12306 | source_node, maybe_op); |
| 12223 | 12307 | is_non_null->value.type = ira->codegen->builtin_types.entry_bool; |
| 12224 | 12308 | |
| 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 | 12347 | if (op_id == IrBinOpCmpEq) { |
| 12226 | 12348 | IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope, |
| 12227 | 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 | 12353 | return is_non_null; |
| 12232 | 12354 | } |
| 12233 | 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", | |
| 12235 | buf_ptr(&(op1->value.type->id == ZigTypeIdNull ? op2->value.type->name : op1->value.type->name)))); | |
| 12356 | ZigType *non_null_type = (op1->value.type->id == ZigTypeIdNull) ? op2->value.type : op1->value.type; | |
| 12357 | ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null", | |
| 12358 | buf_ptr(&non_null_type->name))); | |
| 12236 | 12359 | return ira->codegen->invalid_instruction; |
| 12237 | 12360 | } |
| 12238 | 12361 | |
| ... | ... | @@ -13828,11 +13951,12 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i |
| 13828 | 13951 | zig_unreachable(); |
| 13829 | 13952 | } |
| 13830 | 13953 | |
| 13831 | static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry, ZigType *fn_type, | |
| 13832 | IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst) | |
| 13954 | static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry, | |
| 13955 | ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, | |
| 13956 | IrInstruction *async_allocator_inst) | |
| 13833 | 13957 | { |
| 13834 | 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 | 13960 | ZigType *container_type = async_allocator_inst->value.type->data.pointer.child_type; |
| 13837 | 13961 | IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, realloc_field_name, &call_instruction->base, |
| 13838 | 13962 | async_allocator_inst, container_type); |
| ... | ... | @@ -13840,7 +13964,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c |
| 13840 | 13964 | return ira->codegen->invalid_instruction; |
| 13841 | 13965 | } |
| 13842 | 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); | |
| 13844 | 13968 | |
| 13845 | 13969 | ZigType *realloc_fn_type = ptr_to_realloc_fn_type->data.pointer.child_type; |
| 13846 | 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 | 13999 | IrInstruction *casted_arg; |
| 13876 | 14000 | if (param_decl_node->data.param_decl.var_token == nullptr) { |
| 13877 | 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 | 14003 | if (type_is_invalid(param_type)) |
| 13880 | 14004 | return false; |
| 13881 | 14005 | |
| ... | ... | @@ -13915,7 +14039,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 13915 | 14039 | } else { |
| 13916 | 14040 | if (param_decl_node->data.param_decl.var_token == nullptr) { |
| 13917 | 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 | 14043 | if (type_is_invalid(param_type)) |
| 13920 | 14044 | return false; |
| 13921 | 14045 | |
| ... | ... | @@ -14296,7 +14420,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 14296 | 14420 | } |
| 14297 | 14421 | |
| 14298 | 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 | 14424 | if (type_is_invalid(specified_return_type)) |
| 14301 | 14425 | return ira->codegen->invalid_instruction; |
| 14302 | 14426 | ZigType *return_type; |
| ... | ... | @@ -14532,7 +14656,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 14532 | 14656 | |
| 14533 | 14657 | if (fn_proto_node->data.fn_proto.return_var_token == nullptr) { |
| 14534 | 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 | 14660 | if (type_is_invalid(specified_return_type)) |
| 14537 | 14661 | return ira->codegen->invalid_instruction; |
| 14538 | 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 | 14683 | if (call_instruction->is_async) { |
| 14560 | 14684 | AstNode *async_allocator_type_node = fn_proto_node->data.fn_proto.async_allocator_type; |
| 14561 | 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 | 14687 | if (type_is_invalid(async_allocator_type)) |
| 14564 | 14688 | return ira->codegen->invalid_instruction; |
| 14565 | 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 | 15946 | } |
| 15823 | 15947 | } |
| 15824 | 15948 | |
| 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 | 15950 | ErrorMsg *msg = ir_add_error_node(ira, source_node, |
| 15827 | 15951 | buf_sprintf("dependency on dynamic library '%s' requires enabling Position Independent Code", |
| 15828 | 15952 | buf_ptr(lib_name))); |
| ... | ... | @@ -16696,16 +16820,16 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 16696 | 16820 | case ZigTypeIdUnreachable: |
| 16697 | 16821 | case ZigTypeIdUndefined: |
| 16698 | 16822 | case ZigTypeIdNull: |
| 16699 | case ZigTypeIdComptimeFloat: | |
| 16700 | case ZigTypeIdComptimeInt: | |
| 16701 | case ZigTypeIdEnumLiteral: | |
| 16702 | 16823 | case ZigTypeIdBoundFn: |
| 16703 | case ZigTypeIdMetaType: | |
| 16704 | 16824 | case ZigTypeIdArgTuple: |
| 16705 | 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 | 16827 | buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name))); |
| 16708 | 16828 | return ira->codegen->invalid_instruction; |
| 16829 | case ZigTypeIdMetaType: | |
| 16830 | case ZigTypeIdEnumLiteral: | |
| 16831 | case ZigTypeIdComptimeFloat: | |
| 16832 | case ZigTypeIdComptimeInt: | |
| 16709 | 16833 | case ZigTypeIdVoid: |
| 16710 | 16834 | case ZigTypeIdBool: |
| 16711 | 16835 | case ZigTypeIdInt: |
| ... | ... | @@ -16732,11 +16856,30 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 16732 | 16856 | static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) { |
| 16733 | 16857 | ZigType *type_entry = value->value.type; |
| 16734 | 16858 | |
| 16735 | if (type_entry->id == ZigTypeIdOptional) { | |
| 16859 | if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.allow_zero) { | |
| 16736 | 16860 | if (instr_is_comptime(value)) { |
| 16737 | ConstExprValue *maybe_val = ir_resolve_const(ira, value, UndefBad); | |
| 16738 | if (!maybe_val) | |
| 16861 | ConstExprValue *c_ptr_val = ir_resolve_const(ira, value, UndefOk); | |
| 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 | 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); | |
| 16740 | 16883 | |
| 16741 | 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 | 16913 | if (type_is_invalid(type_entry)) |
| 16771 | 16914 | return ira->codegen->invalid_instruction; |
| 16772 | 16915 | |
| 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 | 16942 | if (type_entry->id != ZigTypeIdOptional) { |
| 16774 | 16943 | ir_add_error_node(ira, base_ptr->source_node, |
| 16775 | 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 | 16953 | ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad); |
| 16785 | 16954 | if (!val) |
| 16786 | 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 | 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 | 16961 | if (optional_value_is_null(maybe_val)) { |
| 16793 | 16962 | ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null")); |
| 16794 | 16963 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -17435,6 +17604,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 17435 | 17604 | ConstExprValue const_val = {}; |
| 17436 | 17605 | const_val.special = ConstValSpecialStatic; |
| 17437 | 17606 | const_val.type = container_type; |
| 17607 | // const_val.global_refs = allocate<ConstGlobalRefs>(1); | |
| 17438 | 17608 | const_val.data.x_struct.fields = create_const_vals(actual_field_count); |
| 17439 | 17609 | for (size_t i = 0; i < instr_field_count; i += 1) { |
| 17440 | 17610 | IrInstructionContainerInitFieldsField *field = &fields[i]; |
| ... | ... | @@ -17498,7 +17668,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 17498 | 17668 | if (const_val.special == ConstValSpecialStatic) { |
| 17499 | 17669 | IrInstruction *result = ir_const(ira, instruction, nullptr); |
| 17500 | 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 | 17672 | out_val->type = container_type; |
| 17503 | 17673 | |
| 17504 | 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 | 17740 | ConstExprValue const_val = {}; |
| 17571 | 17741 | const_val.special = ConstValSpecialStatic; |
| 17572 | 17742 | const_val.type = fixed_size_array_type; |
| 17743 | // const_val.global_refs = allocate<ConstGlobalRefs>(1); | |
| 17573 | 17744 | const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count); |
| 17574 | 17745 | |
| 17575 | 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 | 17777 | if (const_val.special == ConstValSpecialStatic) { |
| 17607 | 17778 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); |
| 17608 | 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 | 17780 | copy_const_val(out_val, &const_val, false); |
| 17612 | 17781 | result->value.type = fixed_size_array_type; |
| 17613 | 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 | 19130 | if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota)) |
| 18962 | 19131 | return ira->codegen->invalid_instruction; |
| 18963 | 19132 | |
| 18964 | if (new_quota > ira->new_irb.exec->backward_branch_quota) { | |
| 18965 | ira->new_irb.exec->backward_branch_quota = new_quota; | |
| 19133 | if (new_quota > *ira->new_irb.exec->backward_branch_quota) { | |
| 19134 | *ira->new_irb.exec->backward_branch_quota = new_quota; | |
| 18966 | 19135 | } |
| 18967 | 19136 | |
| 18968 | 19137 | return ir_const_void(ira, &instruction->base); |
| ... | ... | @@ -19059,24 +19228,50 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct |
| 19059 | 19228 | fprintf(stderr, "@cImport source: %s\n", buf_ptr(&tmp_c_file_path)); |
| 19060 | 19229 | } |
| 19061 | 19230 | |
| 19062 | ZigList<ErrorMsg *> errors = {0}; | |
| 19063 | ||
| 19064 | 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 | 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 | 19258 | if (err != ErrorCCompileErrors) { |
| 19068 | 19259 | ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); |
| 19069 | 19260 | return ira->codegen->invalid_instruction; |
| 19070 | 19261 | } |
| 19071 | assert(errors.length > 0); | |
| 19072 | 19262 | |
| 19073 | 19263 | ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed")); |
| 19074 | 19264 | if (ira->codegen->libc_link_lib == nullptr) { |
| 19075 | 19265 | add_error_note(ira->codegen, parent_err_msg, node, |
| 19076 | 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) { | |
| 19079 | ErrorMsg *err_msg = errors.at(i); | |
| 19268 | for (size_t i = 0; i < errors_len; i += 1) { | |
| 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 | 19275 | err_msg_add_note(parent_err_msg, err_msg); |
| 19081 | 19276 | } |
| 19082 | 19277 | |
| ... | ... | @@ -19106,7 +19301,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct |
| 19106 | 19301 | buf_sprintf("C import failed: unable to open output file: %s", strerror(errno))); |
| 19107 | 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 | 19305 | if (fclose(out_file) != 0) { |
| 19111 | 19306 | ir_add_error_node(ira, node, |
| 19112 | 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 | 21221 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { |
| 21027 | 21222 | IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; |
| 21028 | 21223 | |
| 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 | 21228 | if (type_is_invalid(start_value->value.type)) |
| 21031 | 21229 | return ira->codegen->invalid_instruction; |
| 21032 | 21230 | |
| 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 | 21235 | if (type_is_invalid(end_value->value.type)) |
| 21035 | 21236 | return ira->codegen->invalid_instruction; |
| 21036 | 21237 | |
| 21037 | assert(start_value->value.type->id == ZigTypeIdErrorSet); | |
| 21238 | ir_assert(start_value->value.type->id == ZigTypeIdErrorSet, &instruction->base); | |
| 21038 | 21239 | uint32_t start_index = start_value->value.data.x_err_set->value; |
| 21039 | 21240 | |
| 21040 | assert(end_value->value.type->id == ZigTypeIdErrorSet); | |
| 21241 | ir_assert(end_value->value.type->id == ZigTypeIdErrorSet, &instruction->base); | |
| 21041 | 21242 | uint32_t end_index = end_value->value.data.x_err_set->value; |
| 21042 | 21243 | |
| 21043 | 21244 | if (start_index != end_index) { |
| ... | ... | @@ -21260,7 +21461,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 21260 | 21461 | } |
| 21261 | 21462 | |
| 21262 | 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 | 21465 | result->value.type = result_type; |
| 21265 | 21466 | return result; |
| 21266 | 21467 | } |
| ... | ... | @@ -21330,7 +21531,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 21330 | 21531 | } |
| 21331 | 21532 | |
| 21332 | 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 | 21535 | result->value.type = dest_type; |
| 21335 | 21536 | |
| 21336 | 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 | 21763 | |
| 21563 | 21764 | static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) { |
| 21564 | 21765 | Error err; |
| 21565 | assert(val->special == ConstValSpecialStatic); | |
| 21766 | src_assert(val->special == ConstValSpecialStatic, source_node); | |
| 21566 | 21767 | switch (val->type->id) { |
| 21567 | 21768 | case ZigTypeIdInvalid: |
| 21568 | 21769 | case ZigTypeIdMetaType: |
| ... | ... | @@ -21612,7 +21813,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 21612 | 21813 | zig_panic("TODO buf_read_value_bytes enum packed"); |
| 21613 | 21814 | case ContainerLayoutExtern: { |
| 21614 | 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 | 21817 | bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count, |
| 21617 | 21818 | codegen->is_big_endian, tag_int_type->data.integral.is_signed); |
| 21618 | 21819 | return ErrorNone; |
| ... | ... | @@ -21667,7 +21868,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 21667 | 21868 | bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false); |
| 21668 | 21869 | while (src_i < src_field_count) { |
| 21669 | 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 | 21872 | if (field->gen_index != gen_i) |
| 21672 | 21873 | break; |
| 21673 | 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 | 21944 | Error err; |
| 21744 | 21945 | |
| 21745 | 21946 | ZigType *src_type = value->value.type; |
| 21746 | assert(get_codegen_ptr_type(src_type) == nullptr); | |
| 21747 | assert(type_can_bit_cast(src_type)); | |
| 21748 | assert(get_codegen_ptr_type(dest_type) == nullptr); | |
| 21749 | assert(type_can_bit_cast(dest_type)); | |
| 21947 | ir_assert(get_codegen_ptr_type(src_type) == nullptr, source_instr); | |
| 21948 | ir_assert(type_can_bit_cast(src_type), source_instr); | |
| 21949 | ir_assert(get_codegen_ptr_type(dest_type) == nullptr, source_instr); | |
| 21950 | ir_assert(type_can_bit_cast(dest_type), source_instr); | |
| 21750 | 21951 | |
| 21751 | 21952 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown))) |
| 21752 | 21953 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -21836,8 +22037,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct |
| 21836 | 22037 | static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, |
| 21837 | 22038 | ZigType *ptr_type) |
| 21838 | 22039 | { |
| 21839 | assert(get_src_ptr_type(ptr_type) != nullptr); | |
| 21840 | assert(type_has_bits(ptr_type)); | |
| 22040 | ir_assert(get_src_ptr_type(ptr_type) != nullptr, source_instr); | |
| 22041 | ir_assert(type_has_bits(ptr_type), source_instr); | |
| 21841 | 22042 | |
| 21842 | 22043 | IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize); |
| 21843 | 22044 | if (type_is_invalid(casted_int->value.type)) |
| ... | ... | @@ -21936,7 +22137,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 21936 | 22137 | case TldIdFn: { |
| 21937 | 22138 | TldFn *tld_fn = (TldFn *)tld; |
| 21938 | 22139 | ZigFn *fn_entry = tld_fn->fn_entry; |
| 21939 | assert(fn_entry->type_entry); | |
| 22140 | ir_assert(fn_entry->type_entry, &instruction->base); | |
| 21940 | 22141 | |
| 21941 | 22142 | if (tld_fn->extern_lib_name != nullptr) { |
| 21942 | 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 | 22335 | ZigType *result_type = fn_type_id->param_info[arg_index].type; |
| 22135 | 22336 | if (result_type == nullptr) { |
| 22136 | 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); | |
| 22138 | 22339 | |
| 22139 | 22340 | ir_add_error(ira, arg_index_inst, |
| 22140 | 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 | 22421 | return ira->codegen->invalid_instruction; |
| 22221 | 22422 | |
| 22222 | 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 | 22425 | IrInstruction *result = ir_build_coro_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node, |
| 22225 | 22426 | coro_id, coro_mem_ptr); |
| 22226 | 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 | 22659 | } |
| 22459 | 22660 | |
| 22460 | 22661 | if (ordering == AtomicOrderRelease || ordering == AtomicOrderAcqRel) { |
| 22461 | assert(instruction->ordering != nullptr); | |
| 22662 | ir_assert(instruction->ordering != nullptr, &instruction->base); | |
| 22462 | 22663 | ir_add_error(ira, instruction->ordering, |
| 22463 | 22664 | buf_sprintf("@atomicLoad atomic ordering must not be Release or AcqRel")); |
| 22464 | 22665 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -22466,7 +22667,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr |
| 22466 | 22667 | |
| 22467 | 22668 | if (instr_is_comptime(casted_ptr)) { |
| 22468 | 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 | 22671 | return result; |
| 22471 | 22672 | } |
| 22472 | 22673 | |
| ... | ... | @@ -22496,7 +22697,7 @@ static IrInstruction *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, I |
| 22496 | 22697 | return ira->codegen->invalid_instruction; |
| 22497 | 22698 | |
| 22498 | 22699 | ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 22499 | assert(fn_entry != nullptr); | |
| 22700 | ir_assert(fn_entry != nullptr, &instruction->base); | |
| 22500 | 22701 | |
| 22501 | 22702 | if (type_can_fail(promise_result_type)) { |
| 22502 | 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 | 22713 | if (type_is_invalid(coro_promise_ptr->value.type)) |
| 22513 | 22714 | return ira->codegen->invalid_instruction; |
| 22514 | 22715 | |
| 22515 | assert(coro_promise_ptr->value.type->id == ZigTypeIdPointer); | |
| 22716 | ir_assert(coro_promise_ptr->value.type->id == ZigTypeIdPointer, &instruction->base); | |
| 22516 | 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 | 22719 | ZigType *promise_result_type = promise_frame_type->data.structure.fields[1].type_entry; |
| 22519 | 22720 | |
| 22520 | 22721 | if (!type_can_fail(promise_result_type)) { |
| ... | ... | @@ -22606,7 +22807,7 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS |
| 22606 | 22807 | return result; |
| 22607 | 22808 | } |
| 22608 | 22809 | |
| 22609 | assert(float_type->id == ZigTypeIdFloat); | |
| 22810 | ir_assert(float_type->id == ZigTypeIdFloat, &instruction->base); | |
| 22610 | 22811 | if (float_type->data.floating.bit_count != 16 && |
| 22611 | 22812 | float_type->data.floating.bit_count != 32 && |
| 22612 | 22813 | float_type->data.floating.bit_count != 64) { |
| ... | ... | @@ -22817,6 +23018,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 22817 | 23018 | case IrInstructionIdArrayToVector: |
| 22818 | 23019 | case IrInstructionIdVectorToArray: |
| 22819 | 23020 | case IrInstructionIdAssertZero: |
| 23021 | case IrInstructionIdAssertNonNull: | |
| 22820 | 23022 | case IrInstructionIdResizeSlice: |
| 22821 | 23023 | case IrInstructionIdLoadPtrGen: |
| 22822 | 23024 | case IrInstructionIdBitCastGen: |
| ... | ... | @@ -23096,7 +23298,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 23096 | 23298 | |
| 23097 | 23299 | static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *old_instruction) { |
| 23098 | 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 | 23302 | old_instruction->child = new_instruction; |
| 23101 | 23303 | return new_instruction; |
| 23102 | 23304 | } |
| ... | ... | @@ -23221,6 +23423,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 23221 | 23423 | case IrInstructionIdCmpxchgGen: |
| 23222 | 23424 | case IrInstructionIdCmpxchgSrc: |
| 23223 | 23425 | case IrInstructionIdAssertZero: |
| 23426 | case IrInstructionIdAssertNonNull: | |
| 23224 | 23427 | case IrInstructionIdResizeSlice: |
| 23225 | 23428 | case IrInstructionIdGlobalAsm: |
| 23226 | 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 | 14 | bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); |
| 15 | 15 | |
| 16 | 16 | ConstExprValue *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 | 18 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, |
| 19 | 19 | IrExecutable *parent_exec, AstNode *expected_type_source_node); |
| 20 | 20 |
src/ir_print.cpp+9| ... | ... | @@ -1003,6 +1003,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct |
| 1003 | 1003 | fprintf(irp->f, ")"); |
| 1004 | 1004 | } |
| 1005 | 1005 | |
| 1006 | static 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 | ||
| 1006 | 1012 | static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) { |
| 1007 | 1013 | fprintf(irp->f, "@resizeSlice("); |
| 1008 | 1014 | ir_print_other_instruction(irp, instruction->operand); |
| ... | ... | @@ -1880,6 +1886,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1880 | 1886 | case IrInstructionIdAssertZero: |
| 1881 | 1887 | ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction); |
| 1882 | 1888 | break; |
| 1889 | case IrInstructionIdAssertNonNull: | |
| 1890 | ir_print_assert_non_null(irp, (IrInstructionAssertNonNull *)instruction); | |
| 1891 | break; | |
| 1883 | 1892 | case IrInstructionIdResizeSlice: |
| 1884 | 1893 | ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction); |
| 1885 | 1894 | break; |
src/libc_installation.cpp+30-6| ... | ... | @@ -14,6 +14,7 @@ static const char *zig_libc_keys[] = { |
| 14 | 14 | "include_dir", |
| 15 | 15 | "sys_include_dir", |
| 16 | 16 | "crt_dir", |
| 17 | "static_crt_dir", | |
| 17 | 18 | "msvc_lib_dir", |
| 18 | 19 | "kernel32_lib_dir", |
| 19 | 20 | }; |
| ... | ... | @@ -34,6 +35,7 @@ static void zig_libc_init_empty(ZigLibCInstallation *libc) { |
| 34 | 35 | buf_init_from_str(&libc->include_dir, ""); |
| 35 | 36 | buf_init_from_str(&libc->sys_include_dir, ""); |
| 36 | 37 | buf_init_from_str(&libc->crt_dir, ""); |
| 38 | buf_init_from_str(&libc->static_crt_dir, ""); | |
| 37 | 39 | buf_init_from_str(&libc->msvc_lib_dir, ""); |
| 38 | 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 | 47 | bool found_keys[array_length(zig_libc_keys)] = {}; |
| 46 | 48 | |
| 47 | 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 | 51 | if (err != ErrorFileNotFound && verbose) { |
| 50 | 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 | 76 | match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir); |
| 75 | 77 | match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->sys_include_dir); |
| 76 | 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); | |
| 78 | match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->kernel32_lib_dir); | |
| 79 | match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->static_crt_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 | } |
| 80 | 83 | |
| 81 | 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 | 113 | } |
| 111 | 114 | } |
| 112 | 115 | |
| 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 | 125 | if (buf_len(&libc->msvc_lib_dir) == 0) { |
| 114 | 126 | if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) { |
| 115 | 127 | if (verbose) { |
| ... | ... | @@ -311,6 +323,10 @@ static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool |
| 311 | 323 | #endif |
| 312 | 324 | |
| 313 | 325 | #if defined(ZIG_OS_WINDOWS) |
| 326 | static 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 | ||
| 314 | 330 | static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) { |
| 315 | 331 | Error err; |
| 316 | 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 | 338 | return ErrorNone; |
| 323 | 339 | } |
| 324 | 340 | |
| 325 | static Error zig_libc_find_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target, | |
| 341 | static Error zig_libc_find_native_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target, | |
| 326 | 342 | bool verbose) |
| 327 | 343 | { |
| 328 | 344 | Error err; |
| ... | ... | @@ -398,11 +414,16 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) { |
| 398 | 414 | "# On POSIX it's the directory that includes `sys/errno.h`.\n" |
| 399 | 415 | "sys_include_dir=%s\n" |
| 400 | 416 | "\n" |
| 401 | "# The directory that contains `crt1.o`.\n" | |
| 417 | "# The directory that contains `crt1.o` or `crt2.o`.\n" | |
| 402 | 418 | "# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n" |
| 403 | 419 | "# Not needed when targeting MacOS.\n" |
| 404 | 420 | "crt_dir=%s\n" |
| 405 | 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 | 427 | "# The directory that contains `vcruntime.lib`.\n" |
| 407 | 428 | "# Only needed when targeting MSVC on Windows.\n" |
| 408 | 429 | "msvc_lib_dir=%s\n" |
| ... | ... | @@ -415,6 +436,7 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) { |
| 415 | 436 | buf_ptr(&self->include_dir), |
| 416 | 437 | buf_ptr(&self->sys_include_dir), |
| 417 | 438 | buf_ptr(&self->crt_dir), |
| 439 | buf_ptr(&self->static_crt_dir), | |
| 418 | 440 | buf_ptr(&self->msvc_lib_dir), |
| 419 | 441 | buf_ptr(&self->kernel32_lib_dir) |
| 420 | 442 | ); |
| ... | ... | @@ -431,6 +453,8 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) { |
| 431 | 453 | return err; |
| 432 | 454 | if ((err = zig_libc_find_native_crt_dir_posix(self, verbose))) |
| 433 | 455 | return err; |
| 456 | if ((err = zig_libc_find_native_static_crt_dir_posix(self, verbose))) | |
| 457 | return err; | |
| 434 | 458 | return ErrorNone; |
| 435 | 459 | } else { |
| 436 | 460 | ZigWindowsSDK *sdk; |
| ... | ... | @@ -444,7 +468,7 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) { |
| 444 | 468 | return err; |
| 445 | 469 | if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose))) |
| 446 | 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 | 472 | return err; |
| 449 | 473 | return ErrorNone; |
| 450 | 474 | case ZigFindWindowsSdkErrorOutOfMemory: |
src/libc_installation.hpp+1-2| ... | ... | @@ -19,6 +19,7 @@ struct ZigLibCInstallation { |
| 19 | 19 | Buf include_dir; |
| 20 | 20 | Buf sys_include_dir; |
| 21 | 21 | Buf crt_dir; |
| 22 | Buf static_crt_dir; | |
| 22 | 23 | Buf msvc_lib_dir; |
| 23 | 24 | Buf kernel32_lib_dir; |
| 24 | 25 | }; |
| ... | ... | @@ -29,8 +30,6 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file); |
| 29 | 30 | |
| 30 | 31 | Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose); |
| 31 | 32 | |
| 32 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_WINDOWS) | |
| 33 | 33 | Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose); |
| 34 | #endif | |
| 35 | 34 | |
| 36 | 35 | #endif |
src/link.cpp+191-117| ... | ... | @@ -25,6 +25,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou |
| 25 | 25 | CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type, |
| 26 | 26 | parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path()); |
| 27 | 27 | child_gen->disable_gen_h = true; |
| 28 | child_gen->disable_stack_probing = true; | |
| 28 | 29 | child_gen->verbose_tokenize = parent_gen->verbose_tokenize; |
| 29 | 30 | child_gen->verbose_ast = parent_gen->verbose_ast; |
| 30 | 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 | 773 | } |
| 773 | 774 | } |
| 774 | 775 | |
| 775 | static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) { | |
| 776 | static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, OutType child_out_type) { | |
| 776 | 777 | // The Mach-O LLD code is not well maintained, and trips an assertion |
| 777 | 778 | // when we link compiler_rt and builtin as libraries rather than objects. |
| 778 | 779 | // Here we workaround this by having compiler_rt and builtin be objects. |
| 779 | 780 | // TODO write our own linker. https://github.com/ziglang/zig/issues/1535 |
| 780 | OutType child_out_type = OutTypeLib; | |
| 781 | 781 | if (parent_gen->zig_target->os == OsMacOSX) { |
| 782 | 782 | child_out_type = OutTypeObj; |
| 783 | 783 | } |
| 784 | 784 | |
| 785 | ||
| 786 | 785 | CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type, |
| 787 | 786 | parent_gen->libc); |
| 788 | 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 | 803 | Buf *full_path = buf_alloc(); |
| 805 | 804 | os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path); |
| 806 | 805 | |
| 807 | return build_a_raw(parent_gen, aname, full_path); | |
| 806 | return build_a_raw(parent_gen, aname, full_path, OutTypeLib); | |
| 808 | 807 | } |
| 809 | 808 | |
| 810 | static Buf *build_compiler_rt(CodeGen *parent_gen) { | |
| 809 | static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type) { | |
| 811 | 810 | Buf *full_path = buf_alloc(); |
| 812 | 811 | os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("compiler_rt.zig"), full_path); |
| 813 | 812 | |
| 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 | } |
| 816 | 815 | |
| 817 | 816 | static const char *get_darwin_arch_string(const ZigTarget *t) { |
| ... | ... | @@ -1006,7 +1005,7 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 1006 | 1005 | lj->args.append(buf_ptr(builtin_a_path)); |
| 1007 | 1006 | } |
| 1008 | 1007 | |
| 1009 | Buf *compiler_rt_o_path = build_compiler_rt(g); | |
| 1008 | Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib); | |
| 1010 | 1009 | lj->args.append(buf_ptr(compiler_rt_o_path)); |
| 1011 | 1010 | } |
| 1012 | 1011 | |
| ... | ... | @@ -1091,16 +1090,35 @@ static void construct_linker_job_wasm(LinkJob *lj) { |
| 1091 | 1090 | CodeGen *g = lj->codegen; |
| 1092 | 1091 | |
| 1093 | 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 | 1097 | lj->args.append("--allow-undefined"); |
| 1096 | lj->args.append("--export-all"); | |
| 1097 | 1098 | lj->args.append("-o"); |
| 1098 | 1099 | lj->args.append(buf_ptr(&g->output_file_path)); |
| 1099 | 1100 | |
| 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 | 1108 | // .o files |
| 1101 | 1109 | for (size_t i = 0; i < g->link_objects.length; i += 1) { |
| 1102 | 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 | } |
| 1105 | 1123 | |
| 1106 | 1124 | static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) { |
| ... | ... | @@ -1124,53 +1142,121 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si |
| 1124 | 1142 | } |
| 1125 | 1143 | |
| 1126 | 1144 | static void add_uefi_link_args(LinkJob *lj) { |
| 1127 | lj->args.append("/BASE:0"); | |
| 1128 | lj->args.append("/ENTRY:EfiMain"); | |
| 1129 | lj->args.append("/OPT:REF"); | |
| 1130 | lj->args.append("/SAFESEH:NO"); | |
| 1131 | lj->args.append("/MERGE:.rdata=.data"); | |
| 1132 | lj->args.append("/ALIGN:32"); | |
| 1133 | lj->args.append("/NODEFAULTLIB"); | |
| 1134 | lj->args.append("/SECTION:.xdata,D"); | |
| 1145 | lj->args.append("-BASE:0"); | |
| 1146 | lj->args.append("-ENTRY:EfiMain"); | |
| 1147 | lj->args.append("-OPT:REF"); | |
| 1148 | lj->args.append("-SAFESEH:NO"); | |
| 1149 | lj->args.append("-MERGE:.rdata=.data"); | |
| 1150 | lj->args.append("-ALIGN:32"); | |
| 1151 | lj->args.append("-NODEFAULTLIB"); | |
| 1152 | lj->args.append("-SECTION:.xdata,D"); | |
| 1135 | 1153 | } |
| 1136 | 1154 | |
| 1137 | static void add_nt_link_args(LinkJob *lj, bool is_library) { | |
| 1155 | static void add_msvc_link_args(LinkJob *lj, bool is_library) { | |
| 1138 | 1156 | CodeGen *g = lj->codegen; |
| 1139 | 1157 | |
| 1140 | if (lj->link_in_crt) { | |
| 1141 | // TODO: https://github.com/ziglang/zig/issues/2064 | |
| 1142 | bool is_dynamic = true; // g->is_dynamic; | |
| 1143 | const char *lib_str = is_dynamic ? "" : "lib"; | |
| 1144 | const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : ""; | |
| 1145 | ||
| 1146 | if (!is_dynamic) { | |
| 1147 | Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str); | |
| 1148 | lj->args.append(buf_ptr(cmt_lib_name)); | |
| 1149 | } else { | |
| 1150 | Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str); | |
| 1151 | lj->args.append(buf_ptr(msvcrt_lib_name)); | |
| 1152 | } | |
| 1158 | // TODO: https://github.com/ziglang/zig/issues/2064 | |
| 1159 | bool is_dynamic = true; // g->is_dynamic; | |
| 1160 | const char *lib_str = is_dynamic ? "" : "lib"; | |
| 1161 | const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : ""; | |
| 1162 | ||
| 1163 | if (!is_dynamic) { | |
| 1164 | Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str); | |
| 1165 | lj->args.append(buf_ptr(cmt_lib_name)); | |
| 1166 | } else { | |
| 1167 | Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str); | |
| 1168 | lj->args.append(buf_ptr(msvcrt_lib_name)); | |
| 1169 | } | |
| 1170 | ||
| 1171 | Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str); | |
| 1172 | lj->args.append(buf_ptr(vcruntime_lib_name)); | |
| 1153 | 1173 | |
| 1154 | Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str); | |
| 1155 | lj->args.append(buf_ptr(vcruntime_lib_name)); | |
| 1174 | Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str); | |
| 1175 | lj->args.append(buf_ptr(crt_lib_name)); | |
| 1156 | 1176 | |
| 1157 | Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str); | |
| 1158 | lj->args.append(buf_ptr(crt_lib_name)); | |
| 1177 | //Visual C++ 2015 Conformance Changes | |
| 1178 | //https://msdn.microsoft.com/en-us/library/bb531344.aspx | |
| 1179 | lj->args.append("legacy_stdio_definitions.lib"); | |
| 1159 | 1180 | |
| 1160 | //Visual C++ 2015 Conformance Changes | |
| 1161 | //https://msdn.microsoft.com/en-us/library/bb531344.aspx | |
| 1162 | lj->args.append("legacy_stdio_definitions.lib"); | |
| 1181 | // msvcrt depends on kernel32 and ntdll | |
| 1182 | lj->args.append("kernel32.lib"); | |
| 1183 | lj->args.append("ntdll.lib"); | |
| 1184 | } | |
| 1185 | ||
| 1186 | static 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 | ||
| 1192 | static 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 | ||
| 1198 | static void add_mingw_link_args(LinkJob *lj, bool is_library) { | |
| 1199 | CodeGen *g = lj->codegen; | |
| 1163 | 1200 | |
| 1164 | // msvcrt depends on kernel32 and ntdll | |
| 1165 | lj->args.append("kernel32.lib"); | |
| 1166 | lj->args.append("ntdll.lib"); | |
| 1201 | bool is_dll = g->out_type == OutTypeLib && g->is_dynamic; | |
| 1202 | ||
| 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 | ||
| 1246 | static 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 | 1253 | } else { |
| 1168 | lj->args.append("/NODEFAULTLIB"); | |
| 1254 | lj->args.append("-NODEFAULTLIB"); | |
| 1169 | 1255 | if (!is_library) { |
| 1170 | if (g->have_winmain) { | |
| 1171 | lj->args.append("/ENTRY:WinMain"); | |
| 1256 | if (lj->codegen->have_winmain) { | |
| 1257 | lj->args.append("-ENTRY:WinMain"); | |
| 1172 | 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 | 1266 | Error err; |
| 1181 | 1267 | CodeGen *g = lj->codegen; |
| 1182 | 1268 | |
| 1183 | lj->args.append("/ERRORLIMIT:0"); | |
| 1269 | lj->args.append("-ERRORLIMIT:0"); | |
| 1184 | 1270 | |
| 1185 | lj->args.append("/NOLOGO"); | |
| 1271 | lj->args.append("-NOLOGO"); | |
| 1186 | 1272 | |
| 1187 | 1273 | if (!g->strip_debug_symbols) { |
| 1188 | lj->args.append("/DEBUG"); | |
| 1274 | lj->args.append("-DEBUG"); | |
| 1189 | 1275 | } |
| 1190 | 1276 | |
| 1191 | 1277 | if (g->out_type == OutTypeExe) { |
| 1192 | 1278 | // TODO compile time stack upper bound detection |
| 1193 | lj->args.append("/STACK:16777216"); | |
| 1279 | lj->args.append("-STACK:16777216"); | |
| 1194 | 1280 | } |
| 1195 | 1281 | |
| 1196 | 1282 | coff_append_machine_arg(g, &lj->args); |
| 1197 | 1283 | |
| 1198 | 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 | 1314 | switch (g->subsystem) { |
| 1200 | 1315 | case TargetSubsystemAuto: |
| 1201 | 1316 | if (g->zig_target->os == OsUefi) { |
| 1202 | 1317 | add_uefi_link_args(lj); |
| 1203 | 1318 | } else { |
| 1204 | add_nt_link_args(lj, is_library); | |
| 1319 | add_win_link_args(lj, is_library); | |
| 1205 | 1320 | } |
| 1206 | 1321 | break; |
| 1207 | 1322 | case TargetSubsystemConsole: |
| 1208 | lj->args.append("/SUBSYSTEM:console"); | |
| 1209 | add_nt_link_args(lj, is_library); | |
| 1323 | lj->args.append("-SUBSYSTEM:console"); | |
| 1324 | add_win_link_args(lj, is_library); | |
| 1210 | 1325 | break; |
| 1211 | 1326 | case TargetSubsystemEfiApplication: |
| 1212 | lj->args.append("/SUBSYSTEM:efi_application"); | |
| 1327 | lj->args.append("-SUBSYSTEM:efi_application"); | |
| 1213 | 1328 | add_uefi_link_args(lj); |
| 1214 | 1329 | break; |
| 1215 | 1330 | case TargetSubsystemEfiBootServiceDriver: |
| 1216 | lj->args.append("/SUBSYSTEM:efi_boot_service_driver"); | |
| 1331 | lj->args.append("-SUBSYSTEM:efi_boot_service_driver"); | |
| 1217 | 1332 | add_uefi_link_args(lj); |
| 1218 | 1333 | break; |
| 1219 | 1334 | case TargetSubsystemEfiRom: |
| 1220 | lj->args.append("/SUBSYSTEM:efi_rom"); | |
| 1335 | lj->args.append("-SUBSYSTEM:efi_rom"); | |
| 1221 | 1336 | add_uefi_link_args(lj); |
| 1222 | 1337 | break; |
| 1223 | 1338 | case TargetSubsystemEfiRuntimeDriver: |
| 1224 | lj->args.append("/SUBSYSTEM:efi_runtime_driver"); | |
| 1339 | lj->args.append("-SUBSYSTEM:efi_runtime_driver"); | |
| 1225 | 1340 | add_uefi_link_args(lj); |
| 1226 | 1341 | break; |
| 1227 | 1342 | case TargetSubsystemNative: |
| 1228 | lj->args.append("/SUBSYSTEM:native"); | |
| 1229 | add_nt_link_args(lj, is_library); | |
| 1343 | lj->args.append("-SUBSYSTEM:native"); | |
| 1344 | add_win_link_args(lj, is_library); | |
| 1230 | 1345 | break; |
| 1231 | 1346 | case TargetSubsystemPosix: |
| 1232 | lj->args.append("/SUBSYSTEM:posix"); | |
| 1233 | add_nt_link_args(lj, is_library); | |
| 1347 | lj->args.append("-SUBSYSTEM:posix"); | |
| 1348 | add_win_link_args(lj, is_library); | |
| 1234 | 1349 | break; |
| 1235 | 1350 | case TargetSubsystemWindows: |
| 1236 | lj->args.append("/SUBSYSTEM:windows"); | |
| 1237 | add_nt_link_args(lj, is_library); | |
| 1351 | lj->args.append("-SUBSYSTEM:windows"); | |
| 1352 | add_win_link_args(lj, is_library); | |
| 1238 | 1353 | break; |
| 1239 | 1354 | } |
| 1240 | 1355 | |
| 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 | 1356 | if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) { |
| 1265 | 1357 | if (g->libc_link_lib == nullptr && !g->is_dummy_so) { |
| 1266 | 1358 | Buf *builtin_a_path = build_a(g, "builtin"); |
| ... | ... | @@ -1268,7 +1360,7 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 1268 | 1360 | } |
| 1269 | 1361 | |
| 1270 | 1362 | // 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 | 1364 | lj->args.append(buf_ptr(compiler_rt_o_path)); |
| 1273 | 1365 | } |
| 1274 | 1366 | |
| ... | ... | @@ -1280,11 +1372,10 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 1280 | 1372 | continue; |
| 1281 | 1373 | } |
| 1282 | 1374 | if (link_lib->provided_explicitly) { |
| 1283 | if (lj->codegen->zig_target->abi == ZigLLVM_GNU) { | |
| 1284 | Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name)); | |
| 1285 | lj->args.append(buf_ptr(arg)); | |
| 1286 | } | |
| 1287 | else { | |
| 1375 | if (target_abi_is_gnu(lj->codegen->zig_target->abi)) { | |
| 1376 | Buf *lib_name = buf_sprintf("lib%s.a", buf_ptr(link_lib->name)); | |
| 1377 | lj->args.append(buf_ptr(lib_name)); | |
| 1378 | } else { | |
| 1288 | 1379 | lj->args.append(buf_ptr(link_lib->name)); |
| 1289 | 1380 | } |
| 1290 | 1381 | } else { |
| ... | ... | @@ -1416,18 +1507,6 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) { |
| 1416 | 1507 | } |
| 1417 | 1508 | } |
| 1418 | 1509 | |
| 1419 | static 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 | ||
| 1431 | 1510 | static void construct_linker_job_macho(LinkJob *lj) { |
| 1432 | 1511 | CodeGen *g = lj->codegen; |
| 1433 | 1512 | |
| ... | ... | @@ -1524,7 +1603,7 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 1524 | 1603 | |
| 1525 | 1604 | // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce |
| 1526 | 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 | 1607 | lj->args.append(buf_ptr(compiler_rt_o_path)); |
| 1529 | 1608 | } |
| 1530 | 1609 | |
| ... | ... | @@ -1552,16 +1631,6 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 1552 | 1631 | lj->args.append("dynamic_lookup"); |
| 1553 | 1632 | } |
| 1554 | 1633 | |
| 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 | 1634 | for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) { |
| 1566 | 1635 | lj->args.append("-framework"); |
| 1567 | 1636 | lj->args.append(buf_ptr(g->darwin_frameworks.at(i))); |
| ... | ... | @@ -1585,6 +1654,11 @@ static void construct_linker_job(LinkJob *lj) { |
| 1585 | 1654 | } |
| 1586 | 1655 | } |
| 1587 | 1656 | |
| 1657 | void 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 | ||
| 1588 | 1662 | void codegen_link(CodeGen *g) { |
| 1589 | 1663 | codegen_add_time_event(g, "Build Dependencies"); |
| 1590 | 1664 | |
| ... | ... | @@ -1611,14 +1685,14 @@ void codegen_link(CodeGen *g) { |
| 1611 | 1685 | if (g->out_type == OutTypeLib && !g->is_dynamic) { |
| 1612 | 1686 | ZigList<const char *> file_names = {}; |
| 1613 | 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 | 1690 | ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os); |
| 1617 | 1691 | codegen_add_time_event(g, "LLVM Link"); |
| 1618 | 1692 | if (g->verbose_link) { |
| 1619 | 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) { | |
| 1621 | fprintf(stderr, " %s", (const char *)buf_ptr(g->link_objects.at(i))); | |
| 1694 | for (size_t i = 0; i < file_names.length; i += 1) { | |
| 1695 | fprintf(stderr, " %s", file_names.at(i)); | |
| 1622 | 1696 | } |
| 1623 | 1697 | fprintf(stderr, "\n"); |
| 1624 | 1698 | } |
src/list.hpp-2| ... | ... | @@ -10,8 +10,6 @@ |
| 10 | 10 | |
| 11 | 11 | #include "util.hpp" |
| 12 | 12 | |
| 13 | #include <assert.h> | |
| 14 | ||
| 15 | 13 | template<typename T> |
| 16 | 14 | struct ZigList { |
| 17 | 15 | void deinit() { |
src/main.cpp+87-82| ... | ... | @@ -14,6 +14,7 @@ |
| 14 | 14 | #include "os.hpp" |
| 15 | 15 | #include "target.hpp" |
| 16 | 16 | #include "libc_installation.hpp" |
| 17 | #include "userland.h" | |
| 17 | 18 | |
| 18 | 19 | #include <stdio.h> |
| 19 | 20 | |
| ... | ... | @@ -40,6 +41,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 40 | 41 | " libc [paths_file] Display native libc paths file or validate one\n" |
| 41 | 42 | " run [source] [-- [args]] create executable and run immediately\n" |
| 42 | 43 | " translate-c [source] convert c code to zig code\n" |
| 44 | " translate-c-2 [source] experimental self-hosted translate-c\n" | |
| 43 | 45 | " targets list available compilation targets\n" |
| 44 | 46 | " test [source] create and run a test build\n" |
| 45 | 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 | 54 | " --cache [auto|off|on] build in cache, print output path to stdout\n" |
| 53 | 55 | " --color [auto|off|on] enable or disable colored error messages\n" |
| 54 | 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 | 57 | " --disable-valgrind omit valgrind client requests in debug builds\n" |
| 58 | 58 | " --enable-valgrind include valgrind client requests release builds\n" |
| 59 | " --disable-stack-probing workaround for macosx\n" | |
| 59 | 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 | 63 | " -ftime-report print timing diagnostics\n" |
| 61 | 64 | " --libc [file] Provide a file which specifies libc paths\n" |
| 62 | 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 | 87 | " --override-std-dir [arg] use an alternate Zig standard library\n" |
| 85 | 88 | "\n" |
| 86 | 89 | "Link Options:\n" |
| 90 | " --bundle-compiler-rt [path] for static libraries, include compiler-rt symbols\n" | |
| 87 | 91 | " --dynamic-linker [path] set the path to ld.so\n" |
| 88 | 92 | " --each-lib-rpath add rpath for each used dynamic library\n" |
| 89 | 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 | 135 | return return_code; |
| 132 | 136 | } |
| 133 | 137 | |
| 134 | static 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 | ||
| 147 | 138 | static bool arch_available_in_llvm(ZigLLVM_ArchType arch) { |
| 148 | 139 | LLVMTargetRef target_ref; |
| 149 | 140 | char *err_msg = nullptr; |
| ... | ... | @@ -211,6 +202,7 @@ enum Cmd { |
| 211 | 202 | CmdTargets, |
| 212 | 203 | CmdTest, |
| 213 | 204 | CmdTranslateC, |
| 205 | CmdTranslateCUserland, | |
| 214 | 206 | CmdVersion, |
| 215 | 207 | CmdZen, |
| 216 | 208 | CmdLibC, |
| ... | ... | @@ -324,7 +316,7 @@ int main(int argc, char **argv) { |
| 324 | 316 | return print_error_usage(arg0); |
| 325 | 317 | } |
| 326 | 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 | 320 | Buf *build_zig_path = buf_alloc(); |
| 329 | 321 | os_path_join(cmd_template_path, buf_create_from_str("build.zig"), build_zig_path); |
| 330 | 322 | Buf *src_dir_path = buf_alloc(); |
| ... | ... | @@ -341,7 +333,7 @@ int main(int argc, char **argv) { |
| 341 | 333 | os_path_split(cwd, nullptr, cwd_basename); |
| 342 | 334 | |
| 343 | 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 | 337 | fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(build_zig_path), err_str(err)); |
| 346 | 338 | return EXIT_FAILURE; |
| 347 | 339 | } |
| ... | ... | @@ -356,7 +348,7 @@ int main(int argc, char **argv) { |
| 356 | 348 | } |
| 357 | 349 | |
| 358 | 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 | 352 | fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(main_zig_path), err_str(err)); |
| 361 | 353 | return EXIT_FAILURE; |
| 362 | 354 | } |
| ... | ... | @@ -450,9 +442,12 @@ int main(int argc, char **argv) { |
| 450 | 442 | int runtime_args_start = -1; |
| 451 | 443 | bool system_linker_hack = false; |
| 452 | 444 | TargetSubsystem subsystem = TargetSubsystemAuto; |
| 453 | bool is_single_threaded = false; | |
| 445 | bool want_single_threaded = false; | |
| 454 | 446 | bool disable_gen_h = false; |
| 447 | bool bundle_compiler_rt = false; | |
| 448 | bool disable_stack_probing = false; | |
| 455 | 449 | Buf *override_std_dir = nullptr; |
| 450 | Buf *override_lib_dir = nullptr; | |
| 456 | 451 | Buf *main_pkg_path = nullptr; |
| 457 | 452 | ValgrindSupport valgrind_support = ValgrindSupportAuto; |
| 458 | 453 | WantPIC want_pic = WantPICAuto; |
| ... | ... | @@ -486,13 +481,27 @@ int main(int argc, char **argv) { |
| 486 | 481 | } else if (i + 1 < argc && strcmp(argv[i], "--cache-dir") == 0) { |
| 487 | 482 | cache_dir = argv[i + 1]; |
| 488 | 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 | 496 | } else { |
| 490 | 497 | args.append(argv[i]); |
| 491 | 498 | } |
| 492 | 499 | } |
| 493 | 500 | |
| 501 | Buf *zig_lib_dir = (override_lib_dir == nullptr) ? get_zig_lib_dir() : override_lib_dir; | |
| 502 | ||
| 494 | 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); | |
| 496 | 505 | |
| 497 | 506 | ZigTarget target; |
| 498 | 507 | get_native_target(&target); |
| ... | ... | @@ -512,7 +521,7 @@ int main(int argc, char **argv) { |
| 512 | 521 | } |
| 513 | 522 | |
| 514 | 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 | 525 | g->valgrind_support = valgrind_support; |
| 517 | 526 | g->enable_time_report = timing_info; |
| 518 | 527 | codegen_set_out_name(g, buf_create_from_str("build")); |
| ... | ... | @@ -532,23 +541,25 @@ int main(int argc, char **argv) { |
| 532 | 541 | "Usage: %s build [options]\n" |
| 533 | 542 | "\n" |
| 534 | 543 | "General Options:\n" |
| 535 | " --help Print this help and exit\n" | |
| 536 | " --verbose Print commands before executing them\n" | |
| 537 | " --prefix [path] Override default install prefix\n" | |
| 538 | " --search-prefix [path] Add a path to look for binaries, libraries, headers\n" | |
| 544 | " --help Print this help and exit\n" | |
| 545 | " --verbose Print commands before executing them\n" | |
| 546 | " --prefix [path] Override default install prefix\n" | |
| 547 | " --search-prefix [path] Add a path to look for binaries, libraries, headers\n" | |
| 539 | 548 | "\n" |
| 540 | 549 | "Project-specific options become available when the build file is found.\n" |
| 541 | 550 | "\n" |
| 542 | 551 | "Advanced Options:\n" |
| 543 | " --build-file [file] Override path to build.zig\n" | |
| 544 | " --cache-dir [path] Override path to cache directory\n" | |
| 545 | " --verbose-tokenize Enable compiler debug output for tokenization\n" | |
| 546 | " --verbose-ast Enable compiler debug output for parsing into an AST\n" | |
| 547 | " --verbose-link Enable compiler debug output for linking\n" | |
| 548 | " --verbose-ir Enable compiler debug output for Zig IR\n" | |
| 549 | " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n" | |
| 550 | " --verbose-cimport Enable compiler debug output for C imports\n" | |
| 551 | " --verbose-cc Enable compiler debug output for C compilation\n" | |
| 552 | " --build-file [file] Override path to build.zig\n" | |
| 553 | " --cache-dir [path] Override path to cache directory\n" | |
| 554 | " --override-std-dir [arg] Override path to Zig standard library\n" | |
| 555 | " --override-lib-dir [arg] Override path to Zig lib library\n" | |
| 556 | " --verbose-tokenize Enable compiler debug output for tokenization\n" | |
| 557 | " --verbose-ast Enable compiler debug output for parsing into an AST\n" | |
| 558 | " --verbose-link Enable compiler debug output for linking\n" | |
| 559 | " --verbose-ir Enable compiler debug output for Zig IR\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 | 563 | "\n" |
| 553 | 564 | , zig_exe_path); |
| 554 | 565 | return EXIT_SUCCESS; |
| ... | ... | @@ -581,36 +592,7 @@ int main(int argc, char **argv) { |
| 581 | 592 | } |
| 582 | 593 | return (term.how == TerminationIdClean) ? term.code : -1; |
| 583 | 594 | } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) { |
| 584 | init_all_targets(); | |
| 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; | |
| 595 | return stage2_fmt(argc, argv); | |
| 614 | 596 | } |
| 615 | 597 | |
| 616 | 598 | for (int i = 1; i < argc; i += 1) { |
| ... | ... | @@ -664,16 +646,20 @@ int main(int argc, char **argv) { |
| 664 | 646 | valgrind_support = ValgrindSupportEnabled; |
| 665 | 647 | } else if (strcmp(arg, "--disable-valgrind") == 0) { |
| 666 | 648 | valgrind_support = ValgrindSupportDisabled; |
| 667 | } else if (strcmp(arg, "--enable-pic") == 0) { | |
| 649 | } else if (strcmp(arg, "-fPIC") == 0) { | |
| 668 | 650 | want_pic = WantPICEnabled; |
| 669 | } else if (strcmp(arg, "--disable-pic") == 0) { | |
| 651 | } else if (strcmp(arg, "-fno-PIC") == 0) { | |
| 670 | 652 | want_pic = WantPICDisabled; |
| 671 | 653 | } else if (strcmp(arg, "--system-linker-hack") == 0) { |
| 672 | 654 | system_linker_hack = true; |
| 673 | 655 | } else if (strcmp(arg, "--single-threaded") == 0) { |
| 674 | is_single_threaded = true; | |
| 656 | want_single_threaded = true; | |
| 675 | 657 | } else if (strcmp(arg, "--disable-gen-h") == 0) { |
| 676 | 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 | 663 | } else if (strcmp(arg, "--test-cmd-bin") == 0) { |
| 678 | 664 | test_exec_args.append(nullptr); |
| 679 | 665 | } else if (arg[1] == 'L' && arg[2] != 0) { |
| ... | ... | @@ -757,6 +743,8 @@ int main(int argc, char **argv) { |
| 757 | 743 | llvm_argv.append(argv[i]); |
| 758 | 744 | } else if (strcmp(arg, "--override-std-dir") == 0) { |
| 759 | 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 | 748 | } else if (strcmp(arg, "--main-pkg-path") == 0) { |
| 761 | 749 | main_pkg_path = buf_create_from_str(argv[i]); |
| 762 | 750 | } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) { |
| ... | ... | @@ -775,7 +763,11 @@ int main(int argc, char **argv) { |
| 775 | 763 | if (argv[i][0] == '-') { |
| 776 | 764 | c_file->args.append(argv[i]); |
| 777 | 765 | i += 1; |
| 778 | continue; | |
| 766 | if (i < argc) { | |
| 767 | continue; | |
| 768 | } | |
| 769 | ||
| 770 | break; | |
| 779 | 771 | } else { |
| 780 | 772 | c_file->source_path = argv[i]; |
| 781 | 773 | c_source_files.append(c_file); |
| ... | ... | @@ -867,6 +859,8 @@ int main(int argc, char **argv) { |
| 867 | 859 | cmd = CmdLibC; |
| 868 | 860 | } else if (strcmp(arg, "translate-c") == 0) { |
| 869 | 861 | cmd = CmdTranslateC; |
| 862 | } else if (strcmp(arg, "translate-c-2") == 0) { | |
| 863 | cmd = CmdTranslateCUserland; | |
| 870 | 864 | } else if (strcmp(arg, "test") == 0) { |
| 871 | 865 | cmd = CmdTest; |
| 872 | 866 | out_type = OutTypeExe; |
| ... | ... | @@ -883,6 +877,7 @@ int main(int argc, char **argv) { |
| 883 | 877 | case CmdBuild: |
| 884 | 878 | case CmdRun: |
| 885 | 879 | case CmdTranslateC: |
| 880 | case CmdTranslateCUserland: | |
| 886 | 881 | case CmdTest: |
| 887 | 882 | case CmdLibC: |
| 888 | 883 | if (!in_file) { |
| ... | ... | @@ -959,10 +954,10 @@ int main(int argc, char **argv) { |
| 959 | 954 | } |
| 960 | 955 | case CmdBuiltin: { |
| 961 | 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 | 958 | g->valgrind_support = valgrind_support; |
| 964 | 959 | g->want_pic = want_pic; |
| 965 | g->is_single_threaded = is_single_threaded; | |
| 960 | g->want_single_threaded = want_single_threaded; | |
| 966 | 961 | Buf *builtin_source = codegen_generate_builtin_source(g); |
| 967 | 962 | if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) { |
| 968 | 963 | fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout))); |
| ... | ... | @@ -973,6 +968,7 @@ int main(int argc, char **argv) { |
| 973 | 968 | case CmdRun: |
| 974 | 969 | case CmdBuild: |
| 975 | 970 | case CmdTranslateC: |
| 971 | case CmdTranslateCUserland: | |
| 976 | 972 | case CmdTest: |
| 977 | 973 | { |
| 978 | 974 | if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0 && |
| ... | ... | @@ -985,14 +981,16 @@ int main(int argc, char **argv) { |
| 985 | 981 | " * --assembly argument\n" |
| 986 | 982 | " * --c-source argument\n"); |
| 987 | 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 | 987 | fprintf(stderr, "Expected source file argument.\n"); |
| 990 | 988 | return print_error_usage(arg0); |
| 991 | 989 | } |
| 992 | 990 | |
| 993 | 991 | assert(cmd != CmdBuild || out_type != OutTypeUnknown); |
| 994 | 992 | |
| 995 | bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC); | |
| 993 | bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC || cmd == CmdTranslateCUserland); | |
| 996 | 994 | |
| 997 | 995 | if (cmd == CmdRun) { |
| 998 | 996 | out_name = "run"; |
| ... | ... | @@ -1026,7 +1024,8 @@ int main(int argc, char **argv) { |
| 1026 | 1024 | return print_error_usage(arg0); |
| 1027 | 1025 | } |
| 1028 | 1026 | |
| 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; | |
| 1030 | 1029 | |
| 1031 | 1030 | if (cmd == CmdRun && buf_out_name == nullptr) { |
| 1032 | 1031 | buf_out_name = buf_create_from_str("run"); |
| ... | ... | @@ -1050,7 +1049,7 @@ int main(int argc, char **argv) { |
| 1050 | 1049 | cache_dir_buf = buf_create_from_str(cache_dir); |
| 1051 | 1050 | } |
| 1052 | 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 | 1053 | if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); |
| 1055 | 1054 | g->valgrind_support = valgrind_support; |
| 1056 | 1055 | g->want_pic = want_pic; |
| ... | ... | @@ -1060,7 +1059,7 @@ int main(int argc, char **argv) { |
| 1060 | 1059 | codegen_set_out_name(g, buf_out_name); |
| 1061 | 1060 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); |
| 1062 | 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 | 1063 | codegen_set_linker_script(g, linker_script); |
| 1065 | 1064 | if (each_lib_rpath) |
| 1066 | 1065 | codegen_set_each_lib_rpath(g, each_lib_rpath); |
| ... | ... | @@ -1079,6 +1078,8 @@ int main(int argc, char **argv) { |
| 1079 | 1078 | g->verbose_cc = verbose_cc; |
| 1080 | 1079 | g->output_dir = output_dir; |
| 1081 | 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 | 1083 | codegen_set_errmsg_color(g, color); |
| 1083 | 1084 | g->system_linker_hack = system_linker_hack; |
| 1084 | 1085 | |
| ... | ... | @@ -1144,14 +1145,15 @@ int main(int argc, char **argv) { |
| 1144 | 1145 | codegen_print_timing_report(g, stdout); |
| 1145 | 1146 | |
| 1146 | 1147 | if (cmd == CmdRun) { |
| 1148 | const char *exec_path = buf_ptr(&g->output_file_path); | |
| 1147 | 1149 | ZigList<const char*> args = {0}; |
| 1150 | ||
| 1151 | args.append(exec_path); | |
| 1148 | 1152 | if (runtime_args_start != -1) { |
| 1149 | 1153 | for (int i = runtime_args_start; i < argc; ++i) { |
| 1150 | 1154 | args.append(argv[i]); |
| 1151 | 1155 | } |
| 1152 | 1156 | } |
| 1153 | ||
| 1154 | const char *exec_path = buf_ptr(&g->output_file_path); | |
| 1155 | 1157 | args.append(nullptr); |
| 1156 | 1158 | |
| 1157 | 1159 | os_execv(exec_path, args.items); |
| ... | ... | @@ -1169,9 +1171,8 @@ int main(int argc, char **argv) { |
| 1169 | 1171 | } else { |
| 1170 | 1172 | zig_unreachable(); |
| 1171 | 1173 | } |
| 1172 | } else if (cmd == CmdTranslateC) { | |
| 1173 | AstNode *root_node = codegen_translate_c(g, in_file_buf); | |
| 1174 | ast_render(g, stdout, root_node, 4); | |
| 1174 | } else if (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) { | |
| 1175 | codegen_translate_c(g, in_file_buf, stdout, cmd == CmdTranslateCUserland); | |
| 1175 | 1176 | if (timing_info) |
| 1176 | 1177 | codegen_print_timing_report(g, stderr); |
| 1177 | 1178 | return EXIT_SUCCESS; |
| ... | ... | @@ -1228,9 +1229,13 @@ int main(int argc, char **argv) { |
| 1228 | 1229 | case CmdVersion: |
| 1229 | 1230 | printf("%s\n", ZIG_VERSION_STRING); |
| 1230 | 1231 | return EXIT_SUCCESS; |
| 1231 | case CmdZen: | |
| 1232 | printf("%s\n", ZIG_ZEN); | |
| 1232 | case CmdZen: { | |
| 1233 | const char *ptr; | |
| 1234 | size_t len; | |
| 1235 | stage2_zen(&ptr, &len); | |
| 1236 | fwrite(ptr, len, 1, stdout); | |
| 1233 | 1237 | return EXIT_SUCCESS; |
| 1238 | } | |
| 1234 | 1239 | case CmdTargets: |
| 1235 | 1240 | return print_target_list(stdout); |
| 1236 | 1241 | case CmdNone: |
src/os.cpp+18-35| ... | ... | @@ -751,39 +751,15 @@ Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) { |
| 751 | 751 | #endif |
| 752 | 752 | } |
| 753 | 753 | |
| 754 | Error os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) { | |
| 754 | Error os_fetch_file(FILE *f, Buf *out_buf) { | |
| 755 | 755 | static const ssize_t buf_size = 0x2000; |
| 756 | 756 | buf_resize(out_buf, buf_size); |
| 757 | 757 | ssize_t actual_buf_len = 0; |
| 758 | 758 | |
| 759 | bool first_read = true; | |
| 760 | ||
| 761 | 759 | for (;;) { |
| 762 | 760 | size_t amt_read = fread(buf_ptr(out_buf) + actual_buf_len, 1, buf_size, f); |
| 763 | 761 | actual_buf_len += amt_read; |
| 764 | 762 | |
| 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 | 763 | if (amt_read != buf_size) { |
| 788 | 764 | if (feof(f)) { |
| 789 | 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 | 770 | } |
| 795 | 771 | |
| 796 | 772 | buf_resize(out_buf, actual_buf_len + buf_size); |
| 797 | first_read = false; | |
| 798 | 773 | } |
| 799 | 774 | zig_unreachable(); |
| 800 | 775 | } |
| ... | ... | @@ -864,8 +839,8 @@ static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args, |
| 864 | 839 | |
| 865 | 840 | FILE *stdout_f = fdopen(stdout_pipe[0], "rb"); |
| 866 | 841 | FILE *stderr_f = fdopen(stderr_pipe[0], "rb"); |
| 867 | Error err1 = os_fetch_file(stdout_f, out_stdout, false); | |
| 868 | Error err2 = os_fetch_file(stderr_f, out_stderr, false); | |
| 842 | Error err1 = os_fetch_file(stdout_f, out_stdout); | |
| 843 | Error err2 = os_fetch_file(stderr_f, out_stderr); | |
| 869 | 844 | |
| 870 | 845 | fclose(stdout_f); |
| 871 | 846 | fclose(stderr_f); |
| ... | ... | @@ -1097,7 +1072,7 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) { |
| 1097 | 1072 | } |
| 1098 | 1073 | } |
| 1099 | 1074 | |
| 1100 | Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { | |
| 1075 | Error os_fetch_file_path(Buf *full_path, Buf *out_contents) { | |
| 1101 | 1076 | FILE *f = fopen(buf_ptr(full_path), "rb"); |
| 1102 | 1077 | if (!f) { |
| 1103 | 1078 | switch (errno) { |
| ... | ... | @@ -1116,7 +1091,7 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { |
| 1116 | 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 | 1095 | fclose(f); |
| 1121 | 1096 | return result; |
| 1122 | 1097 | } |
| ... | ... | @@ -1772,8 +1747,14 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) { |
| 1772 | 1747 | // TODO use /etc/passwd |
| 1773 | 1748 | return ErrorFileNotFound; |
| 1774 | 1749 | } |
| 1775 | buf_resize(out_path, 0); | |
| 1776 | buf_appendf(out_path, "%s/.local/share/%s", home_dir, appname); | |
| 1750 | if (home_dir[0] == 0) { | |
| 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 | 1758 | return ErrorNone; |
| 1778 | 1759 | #endif |
| 1779 | 1760 | } |
| ... | ... | @@ -2081,11 +2062,13 @@ Error os_file_overwrite(OsFile file, Buf *contents) { |
| 2081 | 2062 | #endif |
| 2082 | 2063 | } |
| 2083 | 2064 | |
| 2084 | void os_file_close(OsFile file) { | |
| 2065 | void os_file_close(OsFile *file) { | |
| 2085 | 2066 | #if defined(ZIG_OS_WINDOWS) |
| 2086 | CloseHandle(file); | |
| 2067 | CloseHandle(*file); | |
| 2068 | *file = NULL; | |
| 2087 | 2069 | #else |
| 2088 | close(file); | |
| 2070 | close(*file); | |
| 2071 | *file = -1; | |
| 2089 | 2072 | #endif |
| 2090 | 2073 | } |
| 2091 | 2074 |
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 | 121 | Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len); |
| 122 | 122 | Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents); |
| 123 | 123 | Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents); |
| 124 | void os_file_close(OsFile file); | |
| 124 | void os_file_close(OsFile *file); | |
| 125 | 125 | |
| 126 | 126 | Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents); |
| 127 | 127 | Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path); |
| 128 | 128 | |
| 129 | Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang); | |
| 130 | Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang); | |
| 129 | Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents); | |
| 130 | Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents); | |
| 131 | 131 | |
| 132 | 132 | Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd); |
| 133 | 133 |
src/parser.cpp+57-57| ... | ... | @@ -577,7 +577,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { |
| 577 | 577 | |
| 578 | 578 | // TopLevelDecl |
| 579 | 579 | // <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) |
| 580 | // / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl | |
| 580 | // / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl | |
| 581 | 581 | // / KEYWORD_use Expr SEMICOLON |
| 582 | 582 | static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { |
| 583 | 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 | 591 | lib_name = eat_token_if(pc, TokenIdStringLiteral); |
| 592 | 592 | |
| 593 | 593 | if (first->id != TokenIdKeywordInline) { |
| 594 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); | |
| 594 | 595 | AstNode *var_decl = ast_parse_var_decl(pc); |
| 595 | 596 | if (var_decl != nullptr) { |
| 596 | 597 | assert(var_decl->type == NodeTypeVariableDeclaration); |
| 597 | 598 | var_decl->line = first->start_line; |
| 598 | 599 | var_decl->column = first->start_column; |
| 600 | var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; | |
| 599 | 601 | var_decl->data.variable_declaration.visib_mod = visib_mod; |
| 600 | 602 | var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern; |
| 601 | 603 | var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport; |
| 602 | 604 | var_decl->data.variable_declaration.lib_name = token_buf(lib_name); |
| 603 | 605 | return var_decl; |
| 604 | 606 | } |
| 607 | ||
| 608 | if (thread_local_kw != nullptr) | |
| 609 | put_back_token(pc); | |
| 605 | 610 | } |
| 606 | 611 | |
| 607 | 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 | 637 | ast_invalid_token_error(pc, peek_token(pc)); |
| 633 | 638 | } |
| 634 | 639 | |
| 640 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); | |
| 635 | 641 | AstNode *var_decl = ast_parse_var_decl(pc); |
| 636 | 642 | if (var_decl != nullptr) { |
| 637 | 643 | assert(var_decl->type == NodeTypeVariableDeclaration); |
| 638 | 644 | var_decl->data.variable_declaration.visib_mod = visib_mod; |
| 645 | var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; | |
| 639 | 646 | return var_decl; |
| 640 | 647 | } |
| 641 | 648 | |
| 649 | if (thread_local_kw != nullptr) | |
| 650 | put_back_token(pc); | |
| 651 | ||
| 642 | 652 | AstNode *fn_proto = ast_parse_fn_proto(pc); |
| 643 | 653 | if (fn_proto != nullptr) { |
| 644 | 654 | AstNode *body = ast_parse_block(pc); |
| ... | ... | @@ -741,17 +751,12 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 741 | 751 | |
| 742 | 752 | // VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON |
| 743 | 753 | static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 744 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); | |
| 745 | 754 | Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst); |
| 746 | 755 | if (mut_kw == nullptr) |
| 747 | 756 | mut_kw = eat_token_if(pc, TokenIdKeywordVar); |
| 748 | if (mut_kw == nullptr) { | |
| 749 | if (thread_local_kw == nullptr) { | |
| 750 | return nullptr; | |
| 751 | } else { | |
| 752 | ast_invalid_token_error(pc, peek_token(pc)); | |
| 753 | } | |
| 754 | } | |
| 757 | if (mut_kw == nullptr) | |
| 758 | return nullptr; | |
| 759 | ||
| 755 | 760 | Token *identifier = expect_token(pc, TokenIdSymbol); |
| 756 | 761 | AstNode *type_expr = nullptr; |
| 757 | 762 | if (eat_token_if(pc, TokenIdColon) != nullptr) |
| ... | ... | @@ -766,7 +771,6 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 766 | 771 | expect_token(pc, TokenIdSemicolon); |
| 767 | 772 | |
| 768 | 773 | AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw); |
| 769 | res->data.variable_declaration.threadlocal_tok = thread_local_kw; | |
| 770 | 774 | res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst; |
| 771 | 775 | res->data.variable_declaration.symbol = token_buf(identifier); |
| 772 | 776 | res->data.variable_declaration.type = type_expr; |
| ... | ... | @@ -952,17 +956,10 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) { |
| 952 | 956 | |
| 953 | 957 | // LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) |
| 954 | 958 | static AstNode *ast_parse_loop_statement(ParseContext *pc) { |
| 955 | Token *label = ast_parse_block_label(pc); | |
| 956 | Token *first = label; | |
| 957 | ||
| 958 | 959 | Token *inline_token = eat_token_if(pc, TokenIdKeywordInline); |
| 959 | if (first == nullptr) | |
| 960 | first = inline_token; | |
| 961 | ||
| 962 | 960 | AstNode *for_statement = ast_parse_for_statement(pc); |
| 963 | 961 | if (for_statement != nullptr) { |
| 964 | 962 | assert(for_statement->type == NodeTypeForExpr); |
| 965 | for_statement->data.for_expr.name = token_buf(label); | |
| 966 | 963 | for_statement->data.for_expr.is_inline = inline_token != nullptr; |
| 967 | 964 | return for_statement; |
| 968 | 965 | } |
| ... | ... | @@ -970,12 +967,11 @@ static AstNode *ast_parse_loop_statement(ParseContext *pc) { |
| 970 | 967 | AstNode *while_statement = ast_parse_while_statement(pc); |
| 971 | 968 | if (while_statement != nullptr) { |
| 972 | 969 | assert(while_statement->type == NodeTypeWhileExpr); |
| 973 | while_statement->data.while_expr.name = token_buf(label); | |
| 974 | 970 | while_statement->data.while_expr.is_inline = inline_token != nullptr; |
| 975 | 971 | return while_statement; |
| 976 | 972 | } |
| 977 | 973 | |
| 978 | if (first != nullptr) | |
| 974 | if (inline_token != nullptr) | |
| 979 | 975 | ast_invalid_token_error(pc, peek_token(pc)); |
| 980 | 976 | return nullptr; |
| 981 | 977 | } |
| ... | ... | @@ -1117,7 +1113,7 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc) { |
| 1117 | 1113 | |
| 1118 | 1114 | // CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? |
| 1119 | 1115 | static 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 | } |
| 1122 | 1118 | |
| 1123 | 1119 | // BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* |
| ... | ... | @@ -1162,10 +1158,6 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) { |
| 1162 | 1158 | // / Block |
| 1163 | 1159 | // / CurlySuffixExpr |
| 1164 | 1160 | static 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 | 1161 | AstNode *asm_expr = ast_parse_asm_expr(pc); |
| 1170 | 1162 | if (asm_expr != nullptr) |
| 1171 | 1163 | return asm_expr; |
| ... | ... | @@ -1246,11 +1238,8 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) { |
| 1246 | 1238 | } |
| 1247 | 1239 | |
| 1248 | 1240 | AstNode *block = ast_parse_block(pc); |
| 1249 | if (block != nullptr) { | |
| 1250 | assert(block->type == NodeTypeBlock); | |
| 1251 | block->data.block.name = token_buf(label); | |
| 1241 | if (block != nullptr) | |
| 1252 | 1242 | return block; |
| 1253 | } | |
| 1254 | 1243 | |
| 1255 | 1244 | AstNode *curly_suffix = ast_parse_curly_suffix_expr(pc); |
| 1256 | 1245 | if (curly_suffix != nullptr) |
| ... | ... | @@ -1503,6 +1492,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { |
| 1503 | 1492 | // <- BUILTINIDENTIFIER FnCallArguments |
| 1504 | 1493 | // / CHAR_LITERAL |
| 1505 | 1494 | // / ContainerDecl |
| 1495 | // / DOT IDENTIFIER | |
| 1506 | 1496 | // / ErrorSetDecl |
| 1507 | 1497 | // / FLOAT |
| 1508 | 1498 | // / FnProto |
| ... | ... | @@ -1563,6 +1553,10 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { |
| 1563 | 1553 | if (container_decl != nullptr) |
| 1564 | 1554 | return container_decl; |
| 1565 | 1555 | |
| 1556 | AstNode *enum_lit = ast_parse_enum_lit(pc); | |
| 1557 | if (enum_lit != nullptr) | |
| 1558 | return enum_lit; | |
| 1559 | ||
| 1566 | 1560 | AstNode *error_set_decl = ast_parse_error_set_decl(pc); |
| 1567 | 1561 | if (error_set_decl != nullptr) |
| 1568 | 1562 | return error_set_decl; |
| ... | ... | @@ -1672,32 +1666,26 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { |
| 1672 | 1666 | |
| 1673 | 1667 | // ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto |
| 1674 | 1668 | static AstNode *ast_parse_container_decl(ParseContext *pc) { |
| 1675 | Token *extern_token = eat_token_if(pc, TokenIdKeywordExtern); | |
| 1676 | if (extern_token != nullptr) { | |
| 1677 | AstNode *res = ast_parse_container_decl_auto(pc); | |
| 1678 | if (res == nullptr) { | |
| 1679 | put_back_token(pc); | |
| 1680 | return nullptr; | |
| 1681 | } | |
| 1669 | Token *layout_token = eat_token_if(pc, TokenIdKeywordExtern); | |
| 1670 | if (layout_token == nullptr) | |
| 1671 | layout_token = eat_token_if(pc, TokenIdKeywordPacked); | |
| 1682 | 1672 | |
| 1683 | assert(res->type == NodeTypeContainerDecl); | |
| 1684 | res->line = extern_token->start_line; | |
| 1685 | res->column = extern_token->start_column; | |
| 1686 | res->data.container_decl.layout = ContainerLayoutExtern; | |
| 1687 | return res; | |
| 1673 | AstNode *res = ast_parse_container_decl_auto(pc); | |
| 1674 | if (res == nullptr) { | |
| 1675 | if (layout_token != nullptr) | |
| 1676 | put_back_token(pc); | |
| 1677 | return nullptr; | |
| 1688 | 1678 | } |
| 1689 | 1679 | |
| 1690 | Token *packed_token = eat_token_if(pc, TokenIdKeywordPacked); | |
| 1691 | if (packed_token != nullptr) { | |
| 1692 | AstNode *res = ast_expect(pc, ast_parse_container_decl_auto); | |
| 1693 | assert(res->type == NodeTypeContainerDecl); | |
| 1694 | res->line = packed_token->start_line; | |
| 1695 | res->column = packed_token->start_column; | |
| 1696 | res->data.container_decl.layout = ContainerLayoutPacked; | |
| 1697 | return res; | |
| 1680 | assert(res->type == NodeTypeContainerDecl); | |
| 1681 | if (layout_token != nullptr) { | |
| 1682 | res->line = layout_token->start_line; | |
| 1683 | res->column = layout_token->start_column; | |
| 1684 | res->data.container_decl.layout = layout_token->id == TokenIdKeywordExtern | |
| 1685 | ? ContainerLayoutExtern | |
| 1686 | : ContainerLayoutPacked; | |
| 1698 | 1687 | } |
| 1699 | ||
| 1700 | return ast_parse_container_decl_auto(pc); | |
| 1688 | return res; | |
| 1701 | 1689 | } |
| 1702 | 1690 | |
| 1703 | 1691 | // ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE |
| ... | ... | @@ -1971,7 +1959,14 @@ static AstNode *ast_parse_field_init(ParseContext *pc) { |
| 1971 | 1959 | return nullptr; |
| 1972 | 1960 | |
| 1973 | 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 | 1970 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| 1976 | 1971 | |
| 1977 | 1972 | AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first); |
| ... | ... | @@ -2750,12 +2745,19 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { |
| 2750 | 2745 | } |
| 2751 | 2746 | |
| 2752 | 2747 | // ContainerDeclType |
| 2753 | // <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)? | |
| 2748 | // <- KEYWORD_struct | |
| 2749 | // / KEYWORD_enum (LPAREN Expr RPAREN)? | |
| 2754 | 2750 | // / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? |
| 2755 | 2751 | static AstNode *ast_parse_container_decl_type(ParseContext *pc) { |
| 2756 | 2752 | Token *first = eat_token_if(pc, TokenIdKeywordStruct); |
| 2757 | if (first == nullptr) | |
| 2758 | first = eat_token_if(pc, TokenIdKeywordEnum); | |
| 2753 | if (first != nullptr) { | |
| 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 | 2761 | if (first != nullptr) { |
| 2760 | 2762 | AstNode *init_arg_expr = nullptr; |
| 2761 | 2763 | if (eat_token_if(pc, TokenIdLParen) != nullptr) { |
| ... | ... | @@ -2764,9 +2766,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { |
| 2764 | 2766 | } |
| 2765 | 2767 | AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); |
| 2766 | 2768 | res->data.container_decl.init_arg_expr = init_arg_expr; |
| 2767 | res->data.container_decl.kind = first->id == TokenIdKeywordStruct | |
| 2768 | ? ContainerKindStruct | |
| 2769 | : ContainerKindEnum; | |
| 2769 | res->data.container_decl.kind = ContainerKindEnum; | |
| 2770 | 2770 | return res; |
| 2771 | 2771 | } |
| 2772 | 2772 |
src/target.cpp+26-1| ... | ... | @@ -894,10 +894,25 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 894 | 894 | case CIntTypeCount: |
| 895 | 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 | 913 | case OsAnanas: |
| 898 | 914 | case OsCloudABI: |
| 899 | 915 | case OsDragonFly: |
| 900 | case OsIOS: | |
| 901 | 916 | case OsKFreeBSD: |
| 902 | 917 | case OsLv2: |
| 903 | 918 | case OsSolaris: |
| ... | ... | @@ -950,6 +965,8 @@ const char *target_exe_file_ext(const ZigTarget *target) { |
| 950 | 965 | return ".exe"; |
| 951 | 966 | } else if (target->os == OsUefi) { |
| 952 | 967 | return ".efi"; |
| 968 | } else if (target_is_wasm(target)) { | |
| 969 | return ".wasm"; | |
| 953 | 970 | } else { |
| 954 | 971 | return ""; |
| 955 | 972 | } |
| ... | ... | @@ -1350,6 +1367,14 @@ bool target_is_musl(const ZigTarget *target) { |
| 1350 | 1367 | return target->os == OsLinux && target_abi_is_musl(target->abi); |
| 1351 | 1368 | } |
| 1352 | 1369 | |
| 1370 | bool target_is_wasm(const ZigTarget *target) { | |
| 1371 | return target->arch == ZigLLVM_wasm32 || target->arch == ZigLLVM_wasm64; | |
| 1372 | } | |
| 1373 | ||
| 1374 | bool target_is_single_threaded(const ZigTarget *target) { | |
| 1375 | return target_is_wasm(target); | |
| 1376 | } | |
| 1377 | ||
| 1353 | 1378 | ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { |
| 1354 | 1379 | switch (os) { |
| 1355 | 1380 | case OsFreestanding: |
src/target.hpp+2| ... | ... | @@ -170,6 +170,8 @@ bool target_abi_is_gnu(ZigLLVM_EnvironmentType abi); |
| 170 | 170 | bool target_abi_is_musl(ZigLLVM_EnvironmentType abi); |
| 171 | 171 | bool target_is_glibc(const ZigTarget *target); |
| 172 | 172 | bool target_is_musl(const ZigTarget *target); |
| 173 | bool target_is_wasm(const ZigTarget *target); | |
| 174 | bool target_is_single_threaded(const ZigTarget *target); | |
| 173 | 175 | |
| 174 | 176 | uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch); |
| 175 | 177 |
src/translate_c.cpp+1628-1591| ... | ... | @@ -76,10 +76,9 @@ struct TransScopeWhile { |
| 76 | 76 | }; |
| 77 | 77 | |
| 78 | 78 | struct Context { |
| 79 | ZigList<ErrorMsg *> *errors; | |
| 79 | AstNode *root; | |
| 80 | 80 | VisibMod visib_mod; |
| 81 | 81 | bool want_export; |
| 82 | AstNode *root; | |
| 83 | 82 | HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table; |
| 84 | 83 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; |
| 85 | 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 | 111 | |
| 113 | 112 | static TransScopeBlock *trans_scope_block_find(TransScope *scope); |
| 114 | 113 | |
| 115 | static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl); | |
| 116 | static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl); | |
| 117 | static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl); | |
| 114 | static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl); | |
| 115 | static AstNode *resolve_enum_decl(Context *c, const ZigClangEnumDecl *enum_decl); | |
| 116 | static AstNode *resolve_typedef_decl(Context *c, const ZigClangTypedefNameDecl *typedef_decl); | |
| 118 | 117 | |
| 119 | static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt, | |
| 118 | static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *stmt, | |
| 120 | 119 | ResultUsed result_used, TransLRValue lrval, |
| 121 | 120 | AstNode **out_node, TransScope **out_child_scope, |
| 122 | 121 | TransScope **out_node_scope); |
| 123 | static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node); | |
| 124 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval); | |
| 125 | static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc); | |
| 126 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval); | |
| 127 | static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc); | |
| 122 | static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt *stmt, AstNode **out_node); | |
| 123 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr, TransLRValue lrval); | |
| 124 | static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc); | |
| 125 | static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceLocation source_loc); | |
| 126 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, | |
| 127 | const ZigClangExpr *expr, TransLRValue lrval); | |
| 128 | static AstNode *trans_ap_value(Context *c, const ZigClangAPValue *ap_value, ZigClangQualType qt, | |
| 129 | ZigClangSourceLocation source_loc); | |
| 130 | static bool c_is_unsigned_integer(Context *c, ZigClangQualType qt); | |
| 131 | ||
| 132 | static const ZigClangAPSInt *bitcast(const llvm::APSInt *src) { | |
| 133 | return reinterpret_cast<const ZigClangAPSInt *>(src); | |
| 134 | } | |
| 135 | ||
| 136 | static const ZigClangAPValue *bitcast(const clang::APValue *src) { | |
| 137 | return reinterpret_cast<const ZigClangAPValue *>(src); | |
| 138 | } | |
| 139 | ||
| 140 | static const ZigClangStmt *bitcast(const clang::Stmt *src) { | |
| 141 | return reinterpret_cast<const ZigClangStmt *>(src); | |
| 142 | } | |
| 143 | ||
| 144 | static const ZigClangExpr *bitcast(const clang::Expr *src) { | |
| 145 | return reinterpret_cast<const ZigClangExpr *>(src); | |
| 146 | } | |
| 128 | 147 | |
| 129 | 148 | static ZigClangSourceLocation bitcast(clang::SourceLocation src) { |
| 130 | 149 | ZigClangSourceLocation dest; |
| ... | ... | @@ -136,14 +155,14 @@ static ZigClangQualType bitcast(clang::QualType src) { |
| 136 | 155 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType)); |
| 137 | 156 | return dest; |
| 138 | 157 | } |
| 139 | static clang::QualType bitcast(ZigClangQualType src) { | |
| 140 | clang::QualType dest; | |
| 141 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType)); | |
| 142 | return dest; | |
| 143 | } | |
| 158 | //static clang::QualType bitcast(ZigClangQualType src) { | |
| 159 | // clang::QualType dest; | |
| 160 | // memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType)); | |
| 161 | // return dest; | |
| 162 | //} | |
| 144 | 163 | |
| 145 | 164 | ATTRIBUTE_PRINTF(3, 4) |
| 146 | static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) { | |
| 165 | static void emit_warning(Context *c, ZigClangSourceLocation sl, const char *format, ...) { | |
| 147 | 166 | if (!c->warnings_on) { |
| 148 | 167 | return; |
| 149 | 168 | } |
| ... | ... | @@ -153,7 +172,6 @@ static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, cons |
| 153 | 172 | Buf *msg = buf_vprintf(format, ap); |
| 154 | 173 | va_end(ap); |
| 155 | 174 | |
| 156 | ZigClangSourceLocation sl = bitcast(clang_sl); | |
| 157 | 175 | const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager, |
| 158 | 176 | ZigClangSourceManager_getSpellingLoc(c->source_manager, sl)); |
| 159 | 177 | Buf *path; |
| ... | ... | @@ -489,107 +507,99 @@ static Buf *string_ref_to_buf(llvm::StringRef string_ref) { |
| 489 | 507 | return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size()); |
| 490 | 508 | } |
| 491 | 509 | |
| 492 | static const char *decl_name(const clang::Decl *decl) { | |
| 493 | const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl); | |
| 494 | return (const char *)named_decl->getName().bytes_begin(); | |
| 495 | } | |
| 496 | ||
| 497 | static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) { | |
| 510 | static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_int) { | |
| 498 | 511 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); |
| 499 | 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 | 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 | 519 | return node; |
| 504 | 520 | } |
| 505 | llvm::APSInt negated = -aps_int; | |
| 506 | bigint_init_data(node->data.int_literal.bigint, negated.getRawData(), negated.getNumWords(), true); | |
| 521 | const ZigClangAPSInt *negated = ZigClangAPSInt_negate(aps_int); | |
| 522 | bigint_init_data(node->data.int_literal.bigint, ZigClangAPSInt_getRawData(negated), | |
| 523 | ZigClangAPSInt_getNumWords(negated), true); | |
| 524 | ZigClangAPSInt_free(negated); | |
| 507 | 525 | return node; |
| 526 | } | |
| 508 | 527 | |
| 528 | static 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 | } |
| 510 | 539 | |
| 511 | static const clang::Type *qual_type_canon(clang::QualType qt) { | |
| 512 | return qt.getCanonicalType().getTypePtr(); | |
| 540 | static const ZigClangType *qual_type_canon(ZigClangQualType qt) { | |
| 541 | ZigClangQualType canon = ZigClangQualType_getCanonicalType(qt); | |
| 542 | return ZigClangQualType_getTypePtr(canon); | |
| 513 | 543 | } |
| 514 | 544 | |
| 515 | static clang::QualType get_expr_qual_type(Context *c, const clang::Expr *expr) { | |
| 545 | static ZigClangQualType get_expr_qual_type(Context *c, const ZigClangExpr *expr) { | |
| 516 | 546 | // String literals in C are `char *` but they should really be `const char *`. |
| 517 | if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) { | |
| 518 | const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr); | |
| 519 | if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) { | |
| 520 | const clang::Expr *sub_expr = cast_expr->getSubExpr(); | |
| 521 | if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) { | |
| 522 | clang::QualType array_qt = sub_expr->getType(); | |
| 523 | const clang::ArrayType *array_type = static_cast<const clang::ArrayType *>(array_qt.getTypePtr()); | |
| 524 | clang::QualType pointee_qt = array_type->getElementType(); | |
| 525 | pointee_qt.addConst(); | |
| 526 | return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt))); | |
| 547 | if (ZigClangExpr_getStmtClass(expr) == ZigClangStmt_ImplicitCastExprClass) { | |
| 548 | const clang::ImplicitCastExpr *cast_expr = reinterpret_cast<const clang::ImplicitCastExpr *>(expr); | |
| 549 | if ((ZigClangCK)cast_expr->getCastKind() == ZigClangCK_ArrayToPointerDecay) { | |
| 550 | const ZigClangExpr *sub_expr = bitcast(cast_expr->getSubExpr()); | |
| 551 | if (ZigClangExpr_getStmtClass(sub_expr) == ZigClangStmt_StringLiteralClass) { | |
| 552 | ZigClangQualType array_qt = ZigClangExpr_getType(sub_expr); | |
| 553 | const clang::ArrayType *array_type = reinterpret_cast<const clang::ArrayType *>( | |
| 554 | ZigClangQualType_getTypePtr(array_qt)); | |
| 555 | ZigClangQualType pointee_qt = bitcast(array_type->getElementType()); | |
| 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 | } |
| 532 | 563 | |
| 533 | static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) { | |
| 534 | if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) { | |
| 535 | const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr); | |
| 536 | return get_expr_qual_type(c, cast_expr->getSubExpr()); | |
| 564 | static ZigClangQualType get_expr_qual_type_before_implicit_cast(Context *c, const ZigClangExpr *expr) { | |
| 565 | if (ZigClangExpr_getStmtClass(expr) == ZigClangStmt_ImplicitCastExprClass) { | |
| 566 | const clang::ImplicitCastExpr *cast_expr = reinterpret_cast<const clang::ImplicitCastExpr *>(expr); | |
| 567 | return get_expr_qual_type(c, bitcast(cast_expr->getSubExpr())); | |
| 537 | 568 | } |
| 538 | return expr->getType(); | |
| 569 | return ZigClangExpr_getType(expr); | |
| 539 | 570 | } |
| 540 | 571 | |
| 541 | static AstNode *get_expr_type(Context *c, const clang::Expr *expr) { | |
| 542 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getBeginLoc()); | |
| 543 | } | |
| 544 | ||
| 545 | static 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(); | |
| 572 | static AstNode *get_expr_type(Context *c, const ZigClangExpr *expr) { | |
| 573 | return trans_qual_type(c, get_expr_qual_type(c, expr), ZigClangExpr_getBeginLoc(expr)); | |
| 556 | 574 | } |
| 557 | 575 | |
| 558 | 576 | static bool is_c_void_type(AstNode *node) { |
| 559 | 577 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); |
| 560 | 578 | } |
| 561 | 579 | |
| 562 | static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) { | |
| 563 | clang::QualType t1 = get_expr_qual_type(c, expr1); | |
| 564 | clang::QualType t2 = get_expr_qual_type(c, expr2); | |
| 565 | ||
| 566 | return qual_types_equal(t1, t2); | |
| 580 | static bool qual_type_is_ptr(ZigClangQualType qt) { | |
| 581 | const ZigClangType *ty = qual_type_canon(qt); | |
| 582 | return ZigClangType_getTypeClass(ty) == ZigClangType_Pointer; | |
| 567 | 583 | } |
| 568 | 584 | |
| 569 | static bool qual_type_is_ptr(clang::QualType qt) { | |
| 570 | const clang::Type *ty = qual_type_canon(qt); | |
| 571 | return ty->getTypeClass() == clang::Type::Pointer; | |
| 572 | } | |
| 573 | ||
| 574 | static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) { | |
| 575 | const clang::Type *ty = qual_type_canon(qt); | |
| 585 | static const clang::FunctionProtoType *qual_type_get_fn_proto(ZigClangQualType qt, bool *is_ptr) { | |
| 586 | const ZigClangType *ty = qual_type_canon(qt); | |
| 576 | 587 | *is_ptr = false; |
| 577 | 588 | |
| 578 | if (ty->getTypeClass() == clang::Type::Pointer) { | |
| 589 | if (ZigClangType_getTypeClass(ty) == ZigClangType_Pointer) { | |
| 579 | 590 | *is_ptr = true; |
| 580 | const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty); | |
| 581 | clang::QualType child_qt = pointer_ty->getPointeeType(); | |
| 582 | ty = child_qt.getTypePtr(); | |
| 591 | ZigClangQualType child_qt = ZigClangType_getPointeeType(ty); | |
| 592 | ty = ZigClangQualType_getTypePtr(child_qt); | |
| 583 | 593 | } |
| 584 | 594 | |
| 585 | if (ty->getTypeClass() == clang::Type::FunctionProto) { | |
| 586 | return static_cast<const clang::FunctionProtoType*>(ty); | |
| 595 | if (ZigClangType_getTypeClass(ty) == ZigClangType_FunctionProto) { | |
| 596 | return reinterpret_cast<const clang::FunctionProtoType*>(ty); | |
| 587 | 597 | } |
| 588 | 598 | |
| 589 | 599 | return nullptr; |
| 590 | 600 | } |
| 591 | 601 | |
| 592 | static bool qual_type_is_fn_ptr(clang::QualType qt) { | |
| 602 | static bool qual_type_is_fn_ptr(ZigClangQualType qt) { | |
| 593 | 603 | bool is_ptr; |
| 594 | 604 | if (qual_type_get_fn_proto(qt, &is_ptr)) { |
| 595 | 605 | return is_ptr; |
| ... | ... | @@ -598,31 +608,31 @@ static bool qual_type_is_fn_ptr(clang::QualType qt) { |
| 598 | 608 | return false; |
| 599 | 609 | } |
| 600 | 610 | |
| 601 | static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) { | |
| 602 | const clang::Type *ty = qt.getTypePtr(); | |
| 603 | switch (ty->getTypeClass()) { | |
| 604 | case clang::Type::Builtin: | |
| 611 | static uint32_t qual_type_int_bit_width(Context *c, const ZigClangQualType qt, ZigClangSourceLocation source_loc) { | |
| 612 | const ZigClangType *ty = ZigClangQualType_getTypePtr(qt); | |
| 613 | switch (ZigClangType_getTypeClass(ty)) { | |
| 614 | case ZigClangType_Builtin: | |
| 605 | 615 | { |
| 606 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); | |
| 607 | switch (builtin_ty->getKind()) { | |
| 608 | case clang::BuiltinType::Char_U: | |
| 609 | case clang::BuiltinType::UChar: | |
| 610 | case clang::BuiltinType::Char_S: | |
| 611 | case clang::BuiltinType::SChar: | |
| 616 | const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty); | |
| 617 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { | |
| 618 | case ZigClangBuiltinTypeChar_U: | |
| 619 | case ZigClangBuiltinTypeUChar: | |
| 620 | case ZigClangBuiltinTypeChar_S: | |
| 621 | case ZigClangBuiltinTypeSChar: | |
| 612 | 622 | return 8; |
| 613 | case clang::BuiltinType::UInt128: | |
| 614 | case clang::BuiltinType::Int128: | |
| 623 | case ZigClangBuiltinTypeUInt128: | |
| 624 | case ZigClangBuiltinTypeInt128: | |
| 615 | 625 | return 128; |
| 616 | 626 | default: |
| 617 | 627 | return 0; |
| 618 | 628 | } |
| 619 | 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); | |
| 624 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 625 | const char *type_name = decl_name(typedef_decl); | |
| 633 | const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty); | |
| 634 | const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); | |
| 635 | const char *type_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl); | |
| 626 | 636 | if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) { |
| 627 | 637 | return 8; |
| 628 | 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 | 652 | } |
| 643 | 653 | |
| 644 | 654 | |
| 645 | static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt, | |
| 646 | const clang::SourceLocation &source_loc) | |
| 655 | static AstNode *qual_type_to_log2_int_ref(Context *c, const ZigClangQualType qt, | |
| 656 | ZigClangSourceLocation source_loc) | |
| 647 | 657 | { |
| 648 | 658 | uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc); |
| 649 | 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 | 685 | return log2int_fn_call; |
| 676 | 686 | } |
| 677 | 687 | |
| 678 | static bool qual_type_child_is_fn_proto(const clang::QualType &qt) { | |
| 679 | if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) { | |
| 680 | const clang::ParenType *paren_type = static_cast<const clang::ParenType *>(qt.getTypePtr()); | |
| 688 | static bool qual_type_child_is_fn_proto(ZigClangQualType qt) { | |
| 689 | const ZigClangType *ty = ZigClangQualType_getTypePtr(qt); | |
| 690 | if (ZigClangType_getTypeClass(ty) == ZigClangType_Paren) { | |
| 691 | const clang::ParenType *paren_type = reinterpret_cast<const clang::ParenType *>(ty); | |
| 681 | 692 | if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) { |
| 682 | 693 | return true; |
| 683 | 694 | } |
| 684 | } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) { | |
| 685 | const clang::AttributedType *attr_type = static_cast<const clang::AttributedType *>(qt.getTypePtr()); | |
| 686 | return qual_type_child_is_fn_proto(attr_type->getEquivalentType()); | |
| 695 | } else if (ZigClangType_getTypeClass(ty) == ZigClangType_Attributed) { | |
| 696 | const clang::AttributedType *attr_type = reinterpret_cast<const clang::AttributedType *>(ty); | |
| 697 | return qual_type_child_is_fn_proto(bitcast(attr_type->getEquivalentType())); | |
| 687 | 698 | } |
| 688 | 699 | return false; |
| 689 | 700 | } |
| 690 | 701 | |
| 691 | static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type, | |
| 692 | clang::QualType src_type, AstNode *expr) | |
| 702 | static AstNode* trans_c_ptr_cast(Context *c, ZigClangSourceLocation source_location, ZigClangQualType dest_type, | |
| 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 | ||
| 732 | static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location, ZigClangQualType dest_type, | |
| 733 | ZigClangQualType src_type, AstNode *expr) | |
| 693 | 734 | { |
| 694 | 735 | // The only way void pointer casts are valid C code, is if |
| 695 | 736 | // the value of the expression is ignored. We therefore just |
| 696 | 737 | // return the expr, and let the system that ignores values |
| 697 | 738 | // translate this correctly. |
| 698 | if (qual_type_canon(dest_type)->isVoidType()) { | |
| 739 | if (ZigClangType_isVoidType(qual_type_canon(dest_type))) { | |
| 699 | 740 | return expr; |
| 700 | 741 | } |
| 701 | if (qual_types_equal(dest_type, src_type)) { | |
| 742 | if (ZigClangQualType_eq(dest_type, src_type)) { | |
| 702 | 743 | return expr; |
| 703 | 744 | } |
| 704 | 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"); | |
| 706 | ptr_cast_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location)); | |
| 707 | ptr_cast_node->data.fn_call_expr.params.append(expr); | |
| 708 | return ptr_cast_node; | |
| 746 | return trans_c_ptr_cast(c, source_location, dest_type, src_type, expr); | |
| 747 | } | |
| 748 | if (c_is_unsigned_integer(c, dest_type) && qual_type_is_ptr(src_type)) { | |
| 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 | 759 | // TODO: maybe widen to increase size |
| 711 | 760 | // TODO: maybe bitcast to change sign |
| ... | ... | @@ -713,72 +762,72 @@ static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_loc |
| 713 | 762 | return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr); |
| 714 | 763 | } |
| 715 | 764 | |
| 716 | static bool c_is_signed_integer(Context *c, clang::QualType qt) { | |
| 717 | const clang::Type *c_type = qual_type_canon(qt); | |
| 718 | if (c_type->getTypeClass() != clang::Type::Builtin) | |
| 765 | static bool c_is_signed_integer(Context *c, ZigClangQualType qt) { | |
| 766 | const ZigClangType *c_type = qual_type_canon(qt); | |
| 767 | if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin) | |
| 719 | 768 | return false; |
| 720 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); | |
| 721 | switch (builtin_ty->getKind()) { | |
| 722 | case clang::BuiltinType::SChar: | |
| 723 | case clang::BuiltinType::Short: | |
| 724 | case clang::BuiltinType::Int: | |
| 725 | case clang::BuiltinType::Long: | |
| 726 | case clang::BuiltinType::LongLong: | |
| 727 | case clang::BuiltinType::Int128: | |
| 728 | case clang::BuiltinType::WChar_S: | |
| 769 | const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type); | |
| 770 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { | |
| 771 | case ZigClangBuiltinTypeSChar: | |
| 772 | case ZigClangBuiltinTypeShort: | |
| 773 | case ZigClangBuiltinTypeInt: | |
| 774 | case ZigClangBuiltinTypeLong: | |
| 775 | case ZigClangBuiltinTypeLongLong: | |
| 776 | case ZigClangBuiltinTypeInt128: | |
| 777 | case ZigClangBuiltinTypeWChar_S: | |
| 729 | 778 | return true; |
| 730 | 779 | default: |
| 731 | 780 | return false; |
| 732 | 781 | } |
| 733 | 782 | } |
| 734 | 783 | |
| 735 | static bool c_is_unsigned_integer(Context *c, clang::QualType qt) { | |
| 736 | const clang::Type *c_type = qual_type_canon(qt); | |
| 737 | if (c_type->getTypeClass() != clang::Type::Builtin) | |
| 784 | static bool c_is_unsigned_integer(Context *c, ZigClangQualType qt) { | |
| 785 | const ZigClangType *c_type = qual_type_canon(qt); | |
| 786 | if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin) | |
| 738 | 787 | return false; |
| 739 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); | |
| 740 | switch (builtin_ty->getKind()) { | |
| 741 | case clang::BuiltinType::Char_U: | |
| 742 | case clang::BuiltinType::UChar: | |
| 743 | case clang::BuiltinType::Char_S: | |
| 744 | case clang::BuiltinType::UShort: | |
| 745 | case clang::BuiltinType::UInt: | |
| 746 | case clang::BuiltinType::ULong: | |
| 747 | case clang::BuiltinType::ULongLong: | |
| 748 | case clang::BuiltinType::UInt128: | |
| 749 | case clang::BuiltinType::WChar_U: | |
| 788 | const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type); | |
| 789 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { | |
| 790 | case ZigClangBuiltinTypeChar_U: | |
| 791 | case ZigClangBuiltinTypeUChar: | |
| 792 | case ZigClangBuiltinTypeChar_S: | |
| 793 | case ZigClangBuiltinTypeUShort: | |
| 794 | case ZigClangBuiltinTypeUInt: | |
| 795 | case ZigClangBuiltinTypeULong: | |
| 796 | case ZigClangBuiltinTypeULongLong: | |
| 797 | case ZigClangBuiltinTypeUInt128: | |
| 798 | case ZigClangBuiltinTypeWChar_U: | |
| 750 | 799 | return true; |
| 751 | 800 | default: |
| 752 | 801 | return false; |
| 753 | 802 | } |
| 754 | 803 | } |
| 755 | 804 | |
| 756 | static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) { | |
| 757 | const clang::Type *c_type = qual_type_canon(qt); | |
| 758 | if (c_type->getTypeClass() != clang::Type::Builtin) | |
| 805 | static bool c_is_builtin_type(Context *c, ZigClangQualType qt, ZigClangBuiltinTypeKind kind) { | |
| 806 | const ZigClangType *c_type = qual_type_canon(qt); | |
| 807 | if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin) | |
| 759 | 808 | return false; |
| 760 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); | |
| 761 | return builtin_ty->getKind() == kind; | |
| 809 | const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type); | |
| 810 | return ZigClangBuiltinType_getKind(builtin_ty) == kind; | |
| 762 | 811 | } |
| 763 | 812 | |
| 764 | static bool c_is_float(Context *c, clang::QualType qt) { | |
| 765 | const clang::Type *c_type = qt.getTypePtr(); | |
| 766 | if (c_type->getTypeClass() != clang::Type::Builtin) | |
| 813 | static bool c_is_float(Context *c, ZigClangQualType qt) { | |
| 814 | const ZigClangType *c_type = ZigClangQualType_getTypePtr(qt); | |
| 815 | if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin) | |
| 767 | 816 | return false; |
| 768 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); | |
| 769 | switch (builtin_ty->getKind()) { | |
| 770 | case clang::BuiltinType::Half: | |
| 771 | case clang::BuiltinType::Float: | |
| 772 | case clang::BuiltinType::Double: | |
| 773 | case clang::BuiltinType::Float128: | |
| 774 | case clang::BuiltinType::LongDouble: | |
| 817 | const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type); | |
| 818 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { | |
| 819 | case ZigClangBuiltinTypeHalf: | |
| 820 | case ZigClangBuiltinTypeFloat: | |
| 821 | case ZigClangBuiltinTypeDouble: | |
| 822 | case ZigClangBuiltinTypeFloat128: | |
| 823 | case ZigClangBuiltinTypeLongDouble: | |
| 775 | 824 | return true; |
| 776 | 825 | default: |
| 777 | 826 | return false; |
| 778 | 827 | } |
| 779 | 828 | } |
| 780 | 829 | |
| 781 | static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) { | |
| 830 | static bool qual_type_has_wrapping_overflow(Context *c, ZigClangQualType qt) { | |
| 782 | 831 | if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) { |
| 783 | 832 | // float and signed integer overflow is undefined behavior. |
| 784 | 833 | return false; |
| ... | ... | @@ -788,181 +837,182 @@ static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) { |
| 788 | 837 | } |
| 789 | 838 | } |
| 790 | 839 | |
| 791 | static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) { | |
| 792 | switch (ty->getTypeClass()) { | |
| 793 | case clang::Type::Builtin: { | |
| 794 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); | |
| 795 | return builtin_ty->getKind() == clang::BuiltinType::Void; | |
| 840 | static bool type_is_opaque(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) { | |
| 841 | switch (ZigClangType_getTypeClass(ty)) { | |
| 842 | case ZigClangType_Builtin: { | |
| 843 | const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty); | |
| 844 | return ZigClangBuiltinType_getKind(builtin_ty) == ZigClangBuiltinTypeVoid; | |
| 796 | 845 | } |
| 797 | case clang::Type::Record: { | |
| 798 | const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty); | |
| 846 | case ZigClangType_Record: { | |
| 847 | const clang::RecordType *record_ty = reinterpret_cast<const clang::RecordType*>(ty); | |
| 799 | 848 | return record_ty->getDecl()->getDefinition() == nullptr; |
| 800 | 849 | } |
| 801 | case clang::Type::Elaborated: { | |
| 802 | const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty); | |
| 803 | return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc); | |
| 850 | case ZigClangType_Elaborated: { | |
| 851 | const clang::ElaboratedType *elaborated_ty = reinterpret_cast<const clang::ElaboratedType*>(ty); | |
| 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: { | |
| 806 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); | |
| 807 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 808 | return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc); | |
| 855 | case ZigClangType_Typedef: { | |
| 856 | const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty); | |
| 857 | const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); | |
| 858 | ZigClangQualType underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl); | |
| 859 | return type_is_opaque(c, ZigClangQualType_getTypePtr(underlying_type), source_loc); | |
| 809 | 860 | } |
| 810 | 861 | default: |
| 811 | 862 | return false; |
| 812 | 863 | } |
| 813 | 864 | } |
| 814 | 865 | |
| 815 | static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) { | |
| 816 | switch (ty->getTypeClass()) { | |
| 817 | case clang::Type::Builtin: | |
| 866 | static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) { | |
| 867 | switch (ZigClangType_getTypeClass(ty)) { | |
| 868 | case ZigClangType_Builtin: | |
| 818 | 869 | { |
| 819 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); | |
| 820 | switch (builtin_ty->getKind()) { | |
| 821 | case clang::BuiltinType::Void: | |
| 870 | const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType *>(ty); | |
| 871 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { | |
| 872 | case ZigClangBuiltinTypeVoid: | |
| 822 | 873 | return trans_create_node_symbol_str(c, "c_void"); |
| 823 | case clang::BuiltinType::Bool: | |
| 874 | case ZigClangBuiltinTypeBool: | |
| 824 | 875 | return trans_create_node_symbol_str(c, "bool"); |
| 825 | case clang::BuiltinType::Char_U: | |
| 826 | case clang::BuiltinType::UChar: | |
| 827 | case clang::BuiltinType::Char_S: | |
| 828 | case clang::BuiltinType::Char8: | |
| 876 | case ZigClangBuiltinTypeChar_U: | |
| 877 | case ZigClangBuiltinTypeUChar: | |
| 878 | case ZigClangBuiltinTypeChar_S: | |
| 879 | case ZigClangBuiltinTypeChar8: | |
| 829 | 880 | return trans_create_node_symbol_str(c, "u8"); |
| 830 | case clang::BuiltinType::SChar: | |
| 881 | case ZigClangBuiltinTypeSChar: | |
| 831 | 882 | return trans_create_node_symbol_str(c, "i8"); |
| 832 | case clang::BuiltinType::UShort: | |
| 883 | case ZigClangBuiltinTypeUShort: | |
| 833 | 884 | return trans_create_node_symbol_str(c, "c_ushort"); |
| 834 | case clang::BuiltinType::UInt: | |
| 885 | case ZigClangBuiltinTypeUInt: | |
| 835 | 886 | return trans_create_node_symbol_str(c, "c_uint"); |
| 836 | case clang::BuiltinType::ULong: | |
| 887 | case ZigClangBuiltinTypeULong: | |
| 837 | 888 | return trans_create_node_symbol_str(c, "c_ulong"); |
| 838 | case clang::BuiltinType::ULongLong: | |
| 889 | case ZigClangBuiltinTypeULongLong: | |
| 839 | 890 | return trans_create_node_symbol_str(c, "c_ulonglong"); |
| 840 | case clang::BuiltinType::Short: | |
| 891 | case ZigClangBuiltinTypeShort: | |
| 841 | 892 | return trans_create_node_symbol_str(c, "c_short"); |
| 842 | case clang::BuiltinType::Int: | |
| 893 | case ZigClangBuiltinTypeInt: | |
| 843 | 894 | return trans_create_node_symbol_str(c, "c_int"); |
| 844 | case clang::BuiltinType::Long: | |
| 895 | case ZigClangBuiltinTypeLong: | |
| 845 | 896 | return trans_create_node_symbol_str(c, "c_long"); |
| 846 | case clang::BuiltinType::LongLong: | |
| 897 | case ZigClangBuiltinTypeLongLong: | |
| 847 | 898 | return trans_create_node_symbol_str(c, "c_longlong"); |
| 848 | case clang::BuiltinType::UInt128: | |
| 899 | case ZigClangBuiltinTypeUInt128: | |
| 849 | 900 | return trans_create_node_symbol_str(c, "u128"); |
| 850 | case clang::BuiltinType::Int128: | |
| 901 | case ZigClangBuiltinTypeInt128: | |
| 851 | 902 | return trans_create_node_symbol_str(c, "i128"); |
| 852 | case clang::BuiltinType::Float: | |
| 903 | case ZigClangBuiltinTypeFloat: | |
| 853 | 904 | return trans_create_node_symbol_str(c, "f32"); |
| 854 | case clang::BuiltinType::Double: | |
| 905 | case ZigClangBuiltinTypeDouble: | |
| 855 | 906 | return trans_create_node_symbol_str(c, "f64"); |
| 856 | case clang::BuiltinType::Float128: | |
| 907 | case ZigClangBuiltinTypeFloat128: | |
| 857 | 908 | return trans_create_node_symbol_str(c, "f128"); |
| 858 | case clang::BuiltinType::Float16: | |
| 909 | case ZigClangBuiltinTypeFloat16: | |
| 859 | 910 | return trans_create_node_symbol_str(c, "f16"); |
| 860 | case clang::BuiltinType::LongDouble: | |
| 911 | case ZigClangBuiltinTypeLongDouble: | |
| 861 | 912 | return trans_create_node_symbol_str(c, "c_longdouble"); |
| 862 | case clang::BuiltinType::WChar_U: | |
| 863 | case clang::BuiltinType::Char16: | |
| 864 | case clang::BuiltinType::Char32: | |
| 865 | case clang::BuiltinType::WChar_S: | |
| 866 | case clang::BuiltinType::Half: | |
| 867 | case clang::BuiltinType::NullPtr: | |
| 868 | case clang::BuiltinType::ObjCId: | |
| 869 | case clang::BuiltinType::ObjCClass: | |
| 870 | case clang::BuiltinType::ObjCSel: | |
| 871 | case clang::BuiltinType::OMPArraySection: | |
| 872 | case clang::BuiltinType::Dependent: | |
| 873 | case clang::BuiltinType::Overload: | |
| 874 | case clang::BuiltinType::BoundMember: | |
| 875 | case clang::BuiltinType::PseudoObject: | |
| 876 | case clang::BuiltinType::UnknownAny: | |
| 877 | case clang::BuiltinType::BuiltinFn: | |
| 878 | case clang::BuiltinType::ARCUnbridgedCast: | |
| 879 | case clang::BuiltinType::ShortAccum: | |
| 880 | case clang::BuiltinType::Accum: | |
| 881 | case clang::BuiltinType::LongAccum: | |
| 882 | case clang::BuiltinType::UShortAccum: | |
| 883 | case clang::BuiltinType::UAccum: | |
| 884 | case clang::BuiltinType::ULongAccum: | |
| 885 | ||
| 886 | case clang::BuiltinType::OCLImage1dRO: | |
| 887 | case clang::BuiltinType::OCLImage1dArrayRO: | |
| 888 | case clang::BuiltinType::OCLImage1dBufferRO: | |
| 889 | case clang::BuiltinType::OCLImage2dRO: | |
| 890 | case clang::BuiltinType::OCLImage2dArrayRO: | |
| 891 | case clang::BuiltinType::OCLImage2dDepthRO: | |
| 892 | case clang::BuiltinType::OCLImage2dArrayDepthRO: | |
| 893 | case clang::BuiltinType::OCLImage2dMSAARO: | |
| 894 | case clang::BuiltinType::OCLImage2dArrayMSAARO: | |
| 895 | case clang::BuiltinType::OCLImage2dMSAADepthRO: | |
| 896 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRO: | |
| 897 | case clang::BuiltinType::OCLImage3dRO: | |
| 898 | case clang::BuiltinType::OCLImage1dWO: | |
| 899 | case clang::BuiltinType::OCLImage1dArrayWO: | |
| 900 | case clang::BuiltinType::OCLImage1dBufferWO: | |
| 901 | case clang::BuiltinType::OCLImage2dWO: | |
| 902 | case clang::BuiltinType::OCLImage2dArrayWO: | |
| 903 | case clang::BuiltinType::OCLImage2dDepthWO: | |
| 904 | case clang::BuiltinType::OCLImage2dArrayDepthWO: | |
| 905 | case clang::BuiltinType::OCLImage2dMSAAWO: | |
| 906 | case clang::BuiltinType::OCLImage2dArrayMSAAWO: | |
| 907 | case clang::BuiltinType::OCLImage2dMSAADepthWO: | |
| 908 | case clang::BuiltinType::OCLImage2dArrayMSAADepthWO: | |
| 909 | case clang::BuiltinType::OCLImage3dWO: | |
| 910 | case clang::BuiltinType::OCLImage1dRW: | |
| 911 | case clang::BuiltinType::OCLImage1dArrayRW: | |
| 912 | case clang::BuiltinType::OCLImage1dBufferRW: | |
| 913 | case clang::BuiltinType::OCLImage2dRW: | |
| 914 | case clang::BuiltinType::OCLImage2dArrayRW: | |
| 915 | case clang::BuiltinType::OCLImage2dDepthRW: | |
| 916 | case clang::BuiltinType::OCLImage2dArrayDepthRW: | |
| 917 | case clang::BuiltinType::OCLImage2dMSAARW: | |
| 918 | case clang::BuiltinType::OCLImage2dArrayMSAARW: | |
| 919 | case clang::BuiltinType::OCLImage2dMSAADepthRW: | |
| 920 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRW: | |
| 921 | case clang::BuiltinType::OCLImage3dRW: | |
| 922 | case clang::BuiltinType::OCLSampler: | |
| 923 | case clang::BuiltinType::OCLEvent: | |
| 924 | case clang::BuiltinType::OCLClkEvent: | |
| 925 | case clang::BuiltinType::OCLQueue: | |
| 926 | case clang::BuiltinType::OCLReserveID: | |
| 927 | case clang::BuiltinType::ShortFract: | |
| 928 | case clang::BuiltinType::Fract: | |
| 929 | case clang::BuiltinType::LongFract: | |
| 930 | case clang::BuiltinType::UShortFract: | |
| 931 | case clang::BuiltinType::UFract: | |
| 932 | case clang::BuiltinType::ULongFract: | |
| 933 | case clang::BuiltinType::SatShortAccum: | |
| 934 | case clang::BuiltinType::SatAccum: | |
| 935 | case clang::BuiltinType::SatLongAccum: | |
| 936 | case clang::BuiltinType::SatUShortAccum: | |
| 937 | case clang::BuiltinType::SatUAccum: | |
| 938 | case clang::BuiltinType::SatULongAccum: | |
| 939 | case clang::BuiltinType::SatShortFract: | |
| 940 | case clang::BuiltinType::SatFract: | |
| 941 | case clang::BuiltinType::SatLongFract: | |
| 942 | case clang::BuiltinType::SatUShortFract: | |
| 943 | case clang::BuiltinType::SatUFract: | |
| 944 | case clang::BuiltinType::SatULongFract: | |
| 945 | case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload: | |
| 946 | case clang::BuiltinType::OCLIntelSubgroupAVCImePayload: | |
| 947 | case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload: | |
| 948 | case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload: | |
| 949 | case clang::BuiltinType::OCLIntelSubgroupAVCMceResult: | |
| 950 | case clang::BuiltinType::OCLIntelSubgroupAVCImeResult: | |
| 951 | case clang::BuiltinType::OCLIntelSubgroupAVCRefResult: | |
| 952 | case clang::BuiltinType::OCLIntelSubgroupAVCSicResult: | |
| 953 | case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout: | |
| 954 | case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout: | |
| 955 | case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin: | |
| 956 | case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin: | |
| 913 | case ZigClangBuiltinTypeWChar_U: | |
| 914 | case ZigClangBuiltinTypeChar16: | |
| 915 | case ZigClangBuiltinTypeChar32: | |
| 916 | case ZigClangBuiltinTypeWChar_S: | |
| 917 | case ZigClangBuiltinTypeHalf: | |
| 918 | case ZigClangBuiltinTypeNullPtr: | |
| 919 | case ZigClangBuiltinTypeObjCId: | |
| 920 | case ZigClangBuiltinTypeObjCClass: | |
| 921 | case ZigClangBuiltinTypeObjCSel: | |
| 922 | case ZigClangBuiltinTypeOMPArraySection: | |
| 923 | case ZigClangBuiltinTypeDependent: | |
| 924 | case ZigClangBuiltinTypeOverload: | |
| 925 | case ZigClangBuiltinTypeBoundMember: | |
| 926 | case ZigClangBuiltinTypePseudoObject: | |
| 927 | case ZigClangBuiltinTypeUnknownAny: | |
| 928 | case ZigClangBuiltinTypeBuiltinFn: | |
| 929 | case ZigClangBuiltinTypeARCUnbridgedCast: | |
| 930 | case ZigClangBuiltinTypeShortAccum: | |
| 931 | case ZigClangBuiltinTypeAccum: | |
| 932 | case ZigClangBuiltinTypeLongAccum: | |
| 933 | case ZigClangBuiltinTypeUShortAccum: | |
| 934 | case ZigClangBuiltinTypeUAccum: | |
| 935 | case ZigClangBuiltinTypeULongAccum: | |
| 936 | ||
| 937 | case ZigClangBuiltinTypeOCLImage1dRO: | |
| 938 | case ZigClangBuiltinTypeOCLImage1dArrayRO: | |
| 939 | case ZigClangBuiltinTypeOCLImage1dBufferRO: | |
| 940 | case ZigClangBuiltinTypeOCLImage2dRO: | |
| 941 | case ZigClangBuiltinTypeOCLImage2dArrayRO: | |
| 942 | case ZigClangBuiltinTypeOCLImage2dDepthRO: | |
| 943 | case ZigClangBuiltinTypeOCLImage2dArrayDepthRO: | |
| 944 | case ZigClangBuiltinTypeOCLImage2dMSAARO: | |
| 945 | case ZigClangBuiltinTypeOCLImage2dArrayMSAARO: | |
| 946 | case ZigClangBuiltinTypeOCLImage2dMSAADepthRO: | |
| 947 | case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO: | |
| 948 | case ZigClangBuiltinTypeOCLImage3dRO: | |
| 949 | case ZigClangBuiltinTypeOCLImage1dWO: | |
| 950 | case ZigClangBuiltinTypeOCLImage1dArrayWO: | |
| 951 | case ZigClangBuiltinTypeOCLImage1dBufferWO: | |
| 952 | case ZigClangBuiltinTypeOCLImage2dWO: | |
| 953 | case ZigClangBuiltinTypeOCLImage2dArrayWO: | |
| 954 | case ZigClangBuiltinTypeOCLImage2dDepthWO: | |
| 955 | case ZigClangBuiltinTypeOCLImage2dArrayDepthWO: | |
| 956 | case ZigClangBuiltinTypeOCLImage2dMSAAWO: | |
| 957 | case ZigClangBuiltinTypeOCLImage2dArrayMSAAWO: | |
| 958 | case ZigClangBuiltinTypeOCLImage2dMSAADepthWO: | |
| 959 | case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO: | |
| 960 | case ZigClangBuiltinTypeOCLImage3dWO: | |
| 961 | case ZigClangBuiltinTypeOCLImage1dRW: | |
| 962 | case ZigClangBuiltinTypeOCLImage1dArrayRW: | |
| 963 | case ZigClangBuiltinTypeOCLImage1dBufferRW: | |
| 964 | case ZigClangBuiltinTypeOCLImage2dRW: | |
| 965 | case ZigClangBuiltinTypeOCLImage2dArrayRW: | |
| 966 | case ZigClangBuiltinTypeOCLImage2dDepthRW: | |
| 967 | case ZigClangBuiltinTypeOCLImage2dArrayDepthRW: | |
| 968 | case ZigClangBuiltinTypeOCLImage2dMSAARW: | |
| 969 | case ZigClangBuiltinTypeOCLImage2dArrayMSAARW: | |
| 970 | case ZigClangBuiltinTypeOCLImage2dMSAADepthRW: | |
| 971 | case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW: | |
| 972 | case ZigClangBuiltinTypeOCLImage3dRW: | |
| 973 | case ZigClangBuiltinTypeOCLSampler: | |
| 974 | case ZigClangBuiltinTypeOCLEvent: | |
| 975 | case ZigClangBuiltinTypeOCLClkEvent: | |
| 976 | case ZigClangBuiltinTypeOCLQueue: | |
| 977 | case ZigClangBuiltinTypeOCLReserveID: | |
| 978 | case ZigClangBuiltinTypeShortFract: | |
| 979 | case ZigClangBuiltinTypeFract: | |
| 980 | case ZigClangBuiltinTypeLongFract: | |
| 981 | case ZigClangBuiltinTypeUShortFract: | |
| 982 | case ZigClangBuiltinTypeUFract: | |
| 983 | case ZigClangBuiltinTypeULongFract: | |
| 984 | case ZigClangBuiltinTypeSatShortAccum: | |
| 985 | case ZigClangBuiltinTypeSatAccum: | |
| 986 | case ZigClangBuiltinTypeSatLongAccum: | |
| 987 | case ZigClangBuiltinTypeSatUShortAccum: | |
| 988 | case ZigClangBuiltinTypeSatUAccum: | |
| 989 | case ZigClangBuiltinTypeSatULongAccum: | |
| 990 | case ZigClangBuiltinTypeSatShortFract: | |
| 991 | case ZigClangBuiltinTypeSatFract: | |
| 992 | case ZigClangBuiltinTypeSatLongFract: | |
| 993 | case ZigClangBuiltinTypeSatUShortFract: | |
| 994 | case ZigClangBuiltinTypeSatUFract: | |
| 995 | case ZigClangBuiltinTypeSatULongFract: | |
| 996 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload: | |
| 997 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload: | |
| 998 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload: | |
| 999 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload: | |
| 1000 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult: | |
| 1001 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult: | |
| 1002 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult: | |
| 1003 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult: | |
| 1004 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout: | |
| 1005 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout: | |
| 1006 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin: | |
| 1007 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin: | |
| 957 | 1008 | emit_warning(c, source_loc, "unsupported builtin type"); |
| 958 | 1009 | return nullptr; |
| 959 | 1010 | } |
| 960 | 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); | |
| 965 | clang::QualType child_qt = pointer_ty->getPointeeType(); | |
| 1015 | ZigClangQualType child_qt = ZigClangType_getPointeeType(ty); | |
| 966 | 1016 | AstNode *child_node = trans_qual_type(c, child_qt, source_loc); |
| 967 | 1017 | if (child_node == nullptr) { |
| 968 | 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 | 1023 | return trans_create_node_prefix_op(c, PrefixOpOptional, child_node); |
| 974 | 1024 | } |
| 975 | 1025 | |
| 976 | if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) { | |
| 977 | AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(), | |
| 978 | child_qt.isVolatileQualified(), child_node, PtrLenSingle); | |
| 1026 | if (type_is_opaque(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) { | |
| 1027 | AstNode *pointer_node = trans_create_node_ptr_type(c, | |
| 1028 | ZigClangQualType_isConstQualified(child_qt), | |
| 1029 | ZigClangQualType_isVolatileQualified(child_qt), | |
| 1030 | child_node, PtrLenSingle); | |
| 979 | 1031 | return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node); |
| 980 | 1032 | } else { |
| 981 | return trans_create_node_ptr_type(c, child_qt.isConstQualified(), | |
| 982 | child_qt.isVolatileQualified(), child_node, PtrLenC); | |
| 1033 | return trans_create_node_ptr_type(c, | |
| 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); | |
| 988 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 1041 | const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty); | |
| 1042 | const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); | |
| 989 | 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 | 1048 | switch (elaborated_ty->getKeyword()) { |
| 995 | 1049 | case clang::ETK_Struct: |
| 996 | 1050 | case clang::ETK_Enum: |
| 997 | 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 | 1053 | case clang::ETK_Interface: |
| 1000 | 1054 | case clang::ETK_Class: |
| 1001 | 1055 | case clang::ETK_Typename: |
| ... | ... | @@ -1004,81 +1058,81 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc |
| 1004 | 1058 | return nullptr; |
| 1005 | 1059 | } |
| 1006 | 1060 | } |
| 1007 | case clang::Type::FunctionProto: | |
| 1008 | case clang::Type::FunctionNoProto: | |
| 1061 | case ZigClangType_FunctionProto: | |
| 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); | |
| 1011 | 1065 | |
| 1012 | 1066 | AstNode *proto_node = trans_create_node(c, NodeTypeFnProto); |
| 1013 | switch (fn_ty->getCallConv()) { | |
| 1014 | case clang::CC_C: // __attribute__((cdecl)) | |
| 1067 | switch (ZigClangFunctionType_getCallConv(fn_ty)) { | |
| 1068 | case ZigClangCallingConv_C: // __attribute__((cdecl)) | |
| 1015 | 1069 | proto_node->data.fn_proto.cc = CallingConventionC; |
| 1016 | 1070 | proto_node->data.fn_proto.is_extern = true; |
| 1017 | 1071 | break; |
| 1018 | case clang::CC_X86StdCall: // __attribute__((stdcall)) | |
| 1072 | case ZigClangCallingConv_X86StdCall: // __attribute__((stdcall)) | |
| 1019 | 1073 | proto_node->data.fn_proto.cc = CallingConventionStdcall; |
| 1020 | 1074 | break; |
| 1021 | case clang::CC_X86FastCall: // __attribute__((fastcall)) | |
| 1075 | case ZigClangCallingConv_X86FastCall: // __attribute__((fastcall)) | |
| 1022 | 1076 | emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall"); |
| 1023 | 1077 | return nullptr; |
| 1024 | case clang::CC_X86ThisCall: // __attribute__((thiscall)) | |
| 1078 | case ZigClangCallingConv_X86ThisCall: // __attribute__((thiscall)) | |
| 1025 | 1079 | emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall"); |
| 1026 | 1080 | return nullptr; |
| 1027 | case clang::CC_X86VectorCall: // __attribute__((vectorcall)) | |
| 1081 | case ZigClangCallingConv_X86VectorCall: // __attribute__((vectorcall)) | |
| 1028 | 1082 | emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall"); |
| 1029 | 1083 | return nullptr; |
| 1030 | case clang::CC_X86Pascal: // __attribute__((pascal)) | |
| 1084 | case ZigClangCallingConv_X86Pascal: // __attribute__((pascal)) | |
| 1031 | 1085 | emit_warning(c, source_loc, "unsupported calling convention: x86 pascal"); |
| 1032 | 1086 | return nullptr; |
| 1033 | case clang::CC_Win64: // __attribute__((ms_abi)) | |
| 1087 | case ZigClangCallingConv_Win64: // __attribute__((ms_abi)) | |
| 1034 | 1088 | emit_warning(c, source_loc, "unsupported calling convention: win64"); |
| 1035 | 1089 | return nullptr; |
| 1036 | case clang::CC_X86_64SysV: // __attribute__((sysv_abi)) | |
| 1090 | case ZigClangCallingConv_X86_64SysV: // __attribute__((sysv_abi)) | |
| 1037 | 1091 | emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv"); |
| 1038 | 1092 | return nullptr; |
| 1039 | case clang::CC_X86RegCall: | |
| 1093 | case ZigClangCallingConv_X86RegCall: | |
| 1040 | 1094 | emit_warning(c, source_loc, "unsupported calling convention: x86 reg"); |
| 1041 | 1095 | return nullptr; |
| 1042 | case clang::CC_AAPCS: // __attribute__((pcs("aapcs"))) | |
| 1096 | case ZigClangCallingConv_AAPCS: // __attribute__((pcs("aapcs"))) | |
| 1043 | 1097 | emit_warning(c, source_loc, "unsupported calling convention: aapcs"); |
| 1044 | 1098 | return nullptr; |
| 1045 | case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) | |
| 1099 | case ZigClangCallingConv_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) | |
| 1046 | 1100 | emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp"); |
| 1047 | 1101 | return nullptr; |
| 1048 | case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc)) | |
| 1102 | case ZigClangCallingConv_IntelOclBicc: // __attribute__((intel_ocl_bicc)) | |
| 1049 | 1103 | emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc"); |
| 1050 | 1104 | return nullptr; |
| 1051 | case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target | |
| 1105 | case ZigClangCallingConv_SpirFunction: // default for OpenCL functions on SPIR target | |
| 1052 | 1106 | emit_warning(c, source_loc, "unsupported calling convention: SPIR function"); |
| 1053 | 1107 | return nullptr; |
| 1054 | case clang::CC_OpenCLKernel: | |
| 1108 | case ZigClangCallingConv_OpenCLKernel: | |
| 1055 | 1109 | emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel"); |
| 1056 | 1110 | return nullptr; |
| 1057 | case clang::CC_Swift: | |
| 1111 | case ZigClangCallingConv_Swift: | |
| 1058 | 1112 | emit_warning(c, source_loc, "unsupported calling convention: Swift"); |
| 1059 | 1113 | return nullptr; |
| 1060 | case clang::CC_PreserveMost: | |
| 1114 | case ZigClangCallingConv_PreserveMost: | |
| 1061 | 1115 | emit_warning(c, source_loc, "unsupported calling convention: PreserveMost"); |
| 1062 | 1116 | return nullptr; |
| 1063 | case clang::CC_PreserveAll: | |
| 1117 | case ZigClangCallingConv_PreserveAll: | |
| 1064 | 1118 | emit_warning(c, source_loc, "unsupported calling convention: PreserveAll"); |
| 1065 | 1119 | return nullptr; |
| 1066 | case clang::CC_AArch64VectorCall: | |
| 1120 | case ZigClangCallingConv_AArch64VectorCall: | |
| 1067 | 1121 | emit_warning(c, source_loc, "unsupported calling convention: AArch64VectorCall"); |
| 1068 | 1122 | return nullptr; |
| 1069 | 1123 | } |
| 1070 | 1124 | |
| 1071 | if (fn_ty->getNoReturnAttr()) { | |
| 1125 | if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) { | |
| 1072 | 1126 | proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn"); |
| 1073 | 1127 | } else { |
| 1074 | proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_ty->getReturnType(), | |
| 1075 | source_loc); | |
| 1128 | proto_node->data.fn_proto.return_type = trans_qual_type(c, | |
| 1129 | ZigClangFunctionType_getReturnType(fn_ty), source_loc); | |
| 1076 | 1130 | if (proto_node->data.fn_proto.return_type == nullptr) { |
| 1077 | 1131 | emit_warning(c, source_loc, "unsupported function proto return type"); |
| 1078 | 1132 | return nullptr; |
| 1079 | 1133 | } |
| 1080 | 1134 | // convert c_void to actual void (only for return type) |
| 1081 | // we do want to look at the AstNode instead of clang::QualType, because | |
| 1135 | // we do want to look at the AstNode instead of ZigClangQualType, because | |
| 1082 | 1136 | // if they do something like: |
| 1083 | 1137 | // typedef Foo void; |
| 1084 | 1138 | // void foo(void) -> Foo; |
| ... | ... | @@ -1094,17 +1148,17 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc |
| 1094 | 1148 | proto_node->data.fn_proto.name = buf_create_from_str(fn_name); |
| 1095 | 1149 | } |
| 1096 | 1150 | |
| 1097 | if (ty->getTypeClass() == clang::Type::FunctionNoProto) { | |
| 1151 | if (ZigClangType_getTypeClass(ty) == ZigClangType_FunctionNoProto) { | |
| 1098 | 1152 | return proto_node; |
| 1099 | 1153 | } |
| 1100 | 1154 | |
| 1101 | const clang::FunctionProtoType *fn_proto_ty = static_cast<const clang::FunctionProtoType*>(ty); | |
| 1155 | const ZigClangFunctionProtoType *fn_proto_ty = reinterpret_cast<const ZigClangFunctionProtoType*>(ty); | |
| 1102 | 1156 | |
| 1103 | proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic(); | |
| 1104 | size_t param_count = fn_proto_ty->getNumParams(); | |
| 1157 | proto_node->data.fn_proto.is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty); | |
| 1158 | size_t param_count = ZigClangFunctionProtoType_getNumParams(fn_proto_ty); | |
| 1105 | 1159 | |
| 1106 | 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 | 1162 | AstNode *param_type_node = trans_qual_type(c, qt, source_loc); |
| 1109 | 1163 | |
| 1110 | 1164 | if (param_type_node == nullptr) { |
| ... | ... | @@ -1118,7 +1172,7 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc |
| 1118 | 1172 | if (param_name != nullptr) { |
| 1119 | 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 | 1176 | param_node->data.param_decl.type = param_type_node; |
| 1123 | 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 | 1181 | |
| 1128 | 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); | |
| 1133 | return resolve_record_decl(c, record_ty->getDecl()); | |
| 1186 | const ZigClangRecordType *record_ty = reinterpret_cast<const ZigClangRecordType*>(ty); | |
| 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); | |
| 1138 | return resolve_enum_decl(c, enum_ty->getDecl()); | |
| 1191 | const ZigClangEnumType *enum_ty = reinterpret_cast<const ZigClangEnumType*>(ty); | |
| 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); | |
| 1143 | AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc); | |
| 1196 | const clang::ConstantArrayType *const_arr_ty = reinterpret_cast<const clang::ConstantArrayType *>(ty); | |
| 1197 | AstNode *child_type_node = trans_qual_type(c, bitcast(const_arr_ty->getElementType()), source_loc); | |
| 1144 | 1198 | if (child_type_node == nullptr) { |
| 1145 | 1199 | emit_warning(c, source_loc, "unresolved array element type"); |
| 1146 | 1200 | return nullptr; |
| ... | ... | @@ -1149,83 +1203,87 @@ static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::Sourc |
| 1149 | 1203 | AstNode *size_node = trans_create_node_unsigned(c, size); |
| 1150 | 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); | |
| 1155 | return trans_qual_type(c, paren_ty->getInnerType(), source_loc); | |
| 1208 | const clang::ParenType *paren_ty = reinterpret_cast<const clang::ParenType *>(ty); | |
| 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); | |
| 1160 | return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc); | |
| 1213 | const clang::DecayedType *decayed_ty = reinterpret_cast<const clang::DecayedType *>(ty); | |
| 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); | |
| 1165 | return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc); | |
| 1218 | const clang::AttributedType *attributed_ty = reinterpret_cast<const clang::AttributedType *>(ty); | |
| 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); | |
| 1170 | clang::QualType child_qt = incomplete_array_ty->getElementType(); | |
| 1223 | const clang::IncompleteArrayType *incomplete_array_ty = reinterpret_cast<const clang::IncompleteArrayType *>(ty); | |
| 1224 | ZigClangQualType child_qt = bitcast(incomplete_array_ty->getElementType()); | |
| 1171 | 1225 | AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc); |
| 1172 | 1226 | if (child_type_node == nullptr) { |
| 1173 | 1227 | emit_warning(c, source_loc, "unresolved array element type"); |
| 1174 | 1228 | return nullptr; |
| 1175 | 1229 | } |
| 1176 | AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(), | |
| 1177 | child_qt.isVolatileQualified(), child_type_node, PtrLenC); | |
| 1230 | AstNode *pointer_node = trans_create_node_ptr_type(c, | |
| 1231 | ZigClangQualType_isConstQualified(child_qt), | |
| 1232 | ZigClangQualType_isVolatileQualified(child_qt), | |
| 1233 | child_type_node, PtrLenC); | |
| 1178 | 1234 | return pointer_node; |
| 1179 | 1235 | } |
| 1180 | case clang::Type::BlockPointer: | |
| 1181 | case clang::Type::LValueReference: | |
| 1182 | case clang::Type::RValueReference: | |
| 1183 | case clang::Type::MemberPointer: | |
| 1184 | case clang::Type::VariableArray: | |
| 1185 | case clang::Type::DependentSizedArray: | |
| 1186 | case clang::Type::DependentSizedExtVector: | |
| 1187 | case clang::Type::Vector: | |
| 1188 | case clang::Type::ExtVector: | |
| 1189 | case clang::Type::UnresolvedUsing: | |
| 1190 | case clang::Type::Adjusted: | |
| 1191 | case clang::Type::TypeOfExpr: | |
| 1192 | case clang::Type::TypeOf: | |
| 1193 | case clang::Type::Decltype: | |
| 1194 | case clang::Type::UnaryTransform: | |
| 1195 | case clang::Type::TemplateTypeParm: | |
| 1196 | case clang::Type::SubstTemplateTypeParm: | |
| 1197 | case clang::Type::SubstTemplateTypeParmPack: | |
| 1198 | case clang::Type::TemplateSpecialization: | |
| 1199 | case clang::Type::Auto: | |
| 1200 | case clang::Type::InjectedClassName: | |
| 1201 | case clang::Type::DependentName: | |
| 1202 | case clang::Type::DependentTemplateSpecialization: | |
| 1203 | case clang::Type::PackExpansion: | |
| 1204 | case clang::Type::ObjCObject: | |
| 1205 | case clang::Type::ObjCInterface: | |
| 1206 | case clang::Type::Complex: | |
| 1207 | case clang::Type::ObjCObjectPointer: | |
| 1208 | case clang::Type::Atomic: | |
| 1209 | case clang::Type::Pipe: | |
| 1210 | case clang::Type::ObjCTypeParam: | |
| 1211 | case clang::Type::DeducedTemplateSpecialization: | |
| 1212 | case clang::Type::DependentAddressSpace: | |
| 1213 | case clang::Type::DependentVector: | |
| 1214 | emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName()); | |
| 1236 | case ZigClangType_BlockPointer: | |
| 1237 | case ZigClangType_LValueReference: | |
| 1238 | case ZigClangType_RValueReference: | |
| 1239 | case ZigClangType_MemberPointer: | |
| 1240 | case ZigClangType_VariableArray: | |
| 1241 | case ZigClangType_DependentSizedArray: | |
| 1242 | case ZigClangType_DependentSizedExtVector: | |
| 1243 | case ZigClangType_Vector: | |
| 1244 | case ZigClangType_ExtVector: | |
| 1245 | case ZigClangType_UnresolvedUsing: | |
| 1246 | case ZigClangType_Adjusted: | |
| 1247 | case ZigClangType_TypeOfExpr: | |
| 1248 | case ZigClangType_TypeOf: | |
| 1249 | case ZigClangType_Decltype: | |
| 1250 | case ZigClangType_UnaryTransform: | |
| 1251 | case ZigClangType_TemplateTypeParm: | |
| 1252 | case ZigClangType_SubstTemplateTypeParm: | |
| 1253 | case ZigClangType_SubstTemplateTypeParmPack: | |
| 1254 | case ZigClangType_TemplateSpecialization: | |
| 1255 | case ZigClangType_Auto: | |
| 1256 | case ZigClangType_InjectedClassName: | |
| 1257 | case ZigClangType_DependentName: | |
| 1258 | case ZigClangType_DependentTemplateSpecialization: | |
| 1259 | case ZigClangType_PackExpansion: | |
| 1260 | case ZigClangType_ObjCObject: | |
| 1261 | case ZigClangType_ObjCInterface: | |
| 1262 | case ZigClangType_Complex: | |
| 1263 | case ZigClangType_ObjCObjectPointer: | |
| 1264 | case ZigClangType_Atomic: | |
| 1265 | case ZigClangType_Pipe: | |
| 1266 | case ZigClangType_ObjCTypeParam: | |
| 1267 | case ZigClangType_DeducedTemplateSpecialization: | |
| 1268 | case ZigClangType_DependentAddressSpace: | |
| 1269 | case ZigClangType_DependentVector: | |
| 1270 | emit_warning(c, source_loc, "unsupported type: '%s'", ZigClangType_getTypeClassName(ty)); | |
| 1215 | 1271 | return nullptr; |
| 1216 | 1272 | } |
| 1217 | 1273 | zig_unreachable(); |
| 1218 | 1274 | } |
| 1219 | 1275 | |
| 1220 | static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) { | |
| 1221 | return trans_type(c, qt.getTypePtr(), source_loc); | |
| 1276 | static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceLocation source_loc) { | |
| 1277 | return trans_type(c, ZigClangQualType_getTypePtr(qt), source_loc); | |
| 1222 | 1278 | } |
| 1223 | 1279 | |
| 1224 | static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, | |
| 1280 | static int trans_compound_stmt_inline(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt, | |
| 1225 | 1281 | AstNode *block_node, TransScope **out_node_scope) |
| 1226 | 1282 | { |
| 1227 | 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 | 1287 | AstNode *child_node; |
| 1230 | 1288 | scope = trans_stmt(c, scope, *it, &child_node); |
| 1231 | 1289 | if (scope == nullptr) |
| ... | ... | @@ -1239,7 +1297,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang |
| 1239 | 1297 | return ErrorNone; |
| 1240 | 1298 | } |
| 1241 | 1299 | |
| 1242 | static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, | |
| 1300 | static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt, | |
| 1243 | 1301 | TransScope **out_node_scope) |
| 1244 | 1302 | { |
| 1245 | 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 | 1309 | static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope, |
| 1252 | 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 | 1313 | if (block == nullptr) |
| 1256 | 1314 | return block; |
| 1257 | 1315 | assert(block->type == NodeTypeBlock); |
| ... | ... | @@ -1274,7 +1332,7 @@ static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope * |
| 1274 | 1332 | } |
| 1275 | 1333 | |
| 1276 | 1334 | static 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 | 1336 | if (value_expr == nullptr) { |
| 1279 | 1337 | return trans_create_node(c, NodeTypeReturnExpr); |
| 1280 | 1338 | } else { |
| ... | ... | @@ -1289,22 +1347,62 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::Re |
| 1289 | 1347 | static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const clang::IntegerLiteral *stmt) { |
| 1290 | 1348 | clang::Expr::EvalResult result; |
| 1291 | 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 | ||
| 1357 | static 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 | 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 | 1364 | return maybe_suppress_result(c, result_used, node); |
| 1297 | 1365 | } |
| 1298 | 1366 | |
| 1367 | static 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 | ||
| 1299 | 1397 | static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) { |
| 1300 | 1398 | clang::Expr::EvalResult result; |
| 1301 | 1399 | if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen, |
| 1302 | 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 | 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 | 1406 | return maybe_suppress_result(c, result_used, node); |
| 1309 | 1407 | } |
| 1310 | 1408 | |
| ... | ... | @@ -1313,9 +1411,9 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T |
| 1313 | 1411 | { |
| 1314 | 1412 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 1315 | 1413 | |
| 1316 | clang::Expr *cond_expr = stmt->getCond(); | |
| 1317 | clang::Expr *true_expr = stmt->getTrueExpr(); | |
| 1318 | clang::Expr *false_expr = stmt->getFalseExpr(); | |
| 1414 | const ZigClangExpr *cond_expr = bitcast(stmt->getCond()); | |
| 1415 | const ZigClangExpr *true_expr = bitcast(stmt->getTrueExpr()); | |
| 1416 | const ZigClangExpr *false_expr = bitcast(stmt->getFalseExpr()); | |
| 1319 | 1417 | |
| 1320 | 1418 | node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue); |
| 1321 | 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 | 1430 | return maybe_suppress_result(c, result_used, node); |
| 1333 | 1431 | } |
| 1334 | 1432 | |
| 1335 | static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) { | |
| 1433 | static AstNode *trans_create_bin_op(Context *c, TransScope *scope, const ZigClangExpr *lhs, | |
| 1434 | BinOpType bin_op, const ZigClangExpr *rhs) | |
| 1435 | { | |
| 1336 | 1436 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1337 | 1437 | node->data.bin_op_expr.bin_op = bin_op; |
| 1338 | 1438 | |
| ... | ... | @@ -1347,7 +1447,9 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr * |
| 1347 | 1447 | return node; |
| 1348 | 1448 | } |
| 1349 | 1449 | |
| 1350 | static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) { | |
| 1450 | static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, const ZigClangExpr *lhs, | |
| 1451 | BinOpType bin_op, const ZigClangExpr *rhs) | |
| 1452 | { | |
| 1351 | 1453 | assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr); |
| 1352 | 1454 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1353 | 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 | 1465 | return node; |
| 1364 | 1466 | } |
| 1365 | 1467 | |
| 1366 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, clang::Expr *lhs, clang::Expr *rhs) { | |
| 1468 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, | |
| 1469 | const ZigClangExpr *lhs, const ZigClangExpr *rhs) | |
| 1470 | { | |
| 1367 | 1471 | if (result_used == ResultUsedNo) { |
| 1368 | 1472 | // common case |
| 1369 | 1473 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| ... | ... | @@ -1414,10 +1518,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco |
| 1414 | 1518 | } |
| 1415 | 1519 | } |
| 1416 | 1520 | |
| 1417 | static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type, | |
| 1418 | clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr) | |
| 1521 | static AstNode *trans_create_shift_op(Context *c, TransScope *scope, ZigClangQualType result_type, | |
| 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 | 1525 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location); |
| 1422 | 1526 | // lhs >> u5(rh) |
| 1423 | 1527 | |
| ... | ... | @@ -1434,130 +1538,130 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::Qual |
| 1434 | 1538 | static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) { |
| 1435 | 1539 | switch (stmt->getOpcode()) { |
| 1436 | 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 | 1542 | return nullptr; |
| 1439 | 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 | 1545 | return nullptr; |
| 1442 | 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 | 1548 | return nullptr; |
| 1445 | 1549 | case clang::BO_Mul: { |
| 1446 | AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), | |
| 1447 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, | |
| 1448 | stmt->getRHS()); | |
| 1550 | AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), | |
| 1551 | qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())) ? BinOpTypeMultWrap : BinOpTypeMult, | |
| 1552 | bitcast(stmt->getRHS())); | |
| 1449 | 1553 | return maybe_suppress_result(c, result_used, node); |
| 1450 | 1554 | } |
| 1451 | 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 | 1557 | // 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 | 1559 | return maybe_suppress_result(c, result_used, node); |
| 1456 | 1560 | } else { |
| 1457 | 1561 | // signed integer division uses @divTrunc |
| 1458 | 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 | 1564 | if (lhs == nullptr) return nullptr; |
| 1461 | 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 | 1567 | if (rhs == nullptr) return nullptr; |
| 1464 | 1568 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1465 | 1569 | return maybe_suppress_result(c, result_used, fn_call); |
| 1466 | 1570 | } |
| 1467 | 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 | 1573 | // 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 | 1575 | return maybe_suppress_result(c, result_used, node); |
| 1472 | 1576 | } else { |
| 1473 | 1577 | // signed integer division uses @rem |
| 1474 | 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 | 1580 | if (lhs == nullptr) return nullptr; |
| 1477 | 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 | 1583 | if (rhs == nullptr) return nullptr; |
| 1480 | 1584 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1481 | 1585 | return maybe_suppress_result(c, result_used, fn_call); |
| 1482 | 1586 | } |
| 1483 | 1587 | case clang::BO_Add: { |
| 1484 | AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), | |
| 1485 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, | |
| 1486 | stmt->getRHS()); | |
| 1588 | AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), | |
| 1589 | qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())) ? BinOpTypeAddWrap : BinOpTypeAdd, | |
| 1590 | bitcast(stmt->getRHS())); | |
| 1487 | 1591 | return maybe_suppress_result(c, result_used, node); |
| 1488 | 1592 | } |
| 1489 | 1593 | case clang::BO_Sub: { |
| 1490 | AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), | |
| 1491 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, | |
| 1492 | stmt->getRHS()); | |
| 1594 | AstNode *node = trans_create_bin_op(c, scope, bitcast(stmt->getLHS()), | |
| 1595 | qual_type_has_wrapping_overflow(c, bitcast(stmt->getType())) ? BinOpTypeSubWrap : BinOpTypeSub, | |
| 1596 | bitcast(stmt->getRHS())); | |
| 1493 | 1597 | return maybe_suppress_result(c, result_used, node); |
| 1494 | 1598 | } |
| 1495 | 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 | 1601 | return maybe_suppress_result(c, result_used, node); |
| 1498 | 1602 | } |
| 1499 | 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 | 1605 | return maybe_suppress_result(c, result_used, node); |
| 1502 | 1606 | } |
| 1503 | 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 | 1609 | return maybe_suppress_result(c, result_used, node); |
| 1506 | 1610 | } |
| 1507 | 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 | 1613 | return maybe_suppress_result(c, result_used, node); |
| 1510 | 1614 | } |
| 1511 | 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 | 1617 | return maybe_suppress_result(c, result_used, node); |
| 1514 | 1618 | } |
| 1515 | 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 | 1621 | return maybe_suppress_result(c, result_used, node); |
| 1518 | 1622 | } |
| 1519 | 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 | 1625 | return maybe_suppress_result(c, result_used, node); |
| 1522 | 1626 | } |
| 1523 | 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 | 1629 | return maybe_suppress_result(c, result_used, node); |
| 1526 | 1630 | } |
| 1527 | 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 | 1633 | return maybe_suppress_result(c, result_used, node); |
| 1530 | 1634 | } |
| 1531 | 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 | 1637 | return maybe_suppress_result(c, result_used, node); |
| 1534 | 1638 | } |
| 1535 | 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 | 1641 | return maybe_suppress_result(c, result_used, node); |
| 1538 | 1642 | } |
| 1539 | 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 | 1645 | return maybe_suppress_result(c, result_used, node); |
| 1542 | 1646 | } |
| 1543 | 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 | 1649 | return maybe_suppress_result(c, result_used, node); |
| 1546 | 1650 | } |
| 1547 | 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 | 1653 | case clang::BO_Comma: |
| 1550 | 1654 | { |
| 1551 | 1655 | TransScopeBlock *scope_block = trans_scope_block_create(c, scope); |
| 1552 | 1656 | Buf *label_name = buf_create_from_str("x"); |
| 1553 | 1657 | scope_block->node->data.block.name = label_name; |
| 1554 | 1658 | |
| 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 | 1660 | if (lhs == nullptr) |
| 1557 | 1661 | return nullptr; |
| 1558 | 1662 | scope_block->node->data.block.statements.append(lhs); |
| 1559 | 1663 | |
| 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 | 1665 | if (rhs == nullptr) |
| 1562 | 1666 | return nullptr; |
| 1563 | 1667 | |
| ... | ... | @@ -1584,17 +1688,17 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1584 | 1688 | static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope, |
| 1585 | 1689 | const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) |
| 1586 | 1690 | { |
| 1587 | const clang::SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc(); | |
| 1588 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); | |
| 1691 | ZigClangSourceLocation rhs_location = bitcast(stmt->getRHS()->getBeginLoc()); | |
| 1692 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, bitcast(stmt->getComputationLHSType()), rhs_location); | |
| 1589 | 1693 | |
| 1590 | 1694 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| 1591 | 1695 | if (!use_intermediate_casts && result_used == ResultUsedNo) { |
| 1592 | 1696 | // simple common case, where the C and Zig are identical: |
| 1593 | 1697 | // 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 | 1699 | if (lhs == nullptr) return nullptr; |
| 1596 | 1700 | |
| 1597 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransRValue); | |
| 1701 | AstNode *rhs = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getRHS()), TransRValue); | |
| 1598 | 1702 | if (rhs == nullptr) return nullptr; |
| 1599 | 1703 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1600 | 1704 | |
| ... | ... | @@ -1614,7 +1718,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1614 | 1718 | child_scope->node->data.block.name = label_name; |
| 1615 | 1719 | |
| 1616 | 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 | 1722 | if (lhs == nullptr) return nullptr; |
| 1619 | 1723 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs); |
| 1620 | 1724 | // TODO: avoid name collisions with generated variable names |
| ... | ... | @@ -1624,20 +1728,20 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1624 | 1728 | |
| 1625 | 1729 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1626 | 1730 | |
| 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 | 1732 | if (rhs == nullptr) return nullptr; |
| 1629 | 1733 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1630 | 1734 | |
| 1631 | 1735 | // operation_type(*_ref) |
| 1632 | 1736 | AstNode *operation_type_cast = trans_c_cast(c, rhs_location, |
| 1633 | stmt->getComputationLHSType(), | |
| 1634 | stmt->getLHS()->getType(), | |
| 1737 | bitcast(stmt->getComputationLHSType()), | |
| 1738 | bitcast(stmt->getLHS()->getType()), | |
| 1635 | 1739 | trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name))); |
| 1636 | 1740 | |
| 1637 | 1741 | // result_type(... >> u5(rhs)) |
| 1638 | 1742 | AstNode *result_type_cast = trans_c_cast(c, rhs_location, |
| 1639 | stmt->getComputationResultType(), | |
| 1640 | stmt->getComputationLHSType(), | |
| 1743 | bitcast(stmt->getComputationResultType()), | |
| 1744 | bitcast(stmt->getComputationLHSType()), | |
| 1641 | 1745 | trans_create_node_bin_op(c, |
| 1642 | 1746 | operation_type_cast, |
| 1643 | 1747 | bin_op, |
| ... | ... | @@ -1669,9 +1773,9 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, |
| 1669 | 1773 | if (result_used == ResultUsedNo) { |
| 1670 | 1774 | // simple common case, where the C and Zig are identical: |
| 1671 | 1775 | // 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 | 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 | 1779 | if (rhs == nullptr) return nullptr; |
| 1676 | 1780 | return trans_create_node_bin_op(c, lhs, assign_op, rhs); |
| 1677 | 1781 | } else { |
| ... | ... | @@ -1688,7 +1792,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, |
| 1688 | 1792 | child_scope->node->data.block.name = label_name; |
| 1689 | 1793 | |
| 1690 | 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 | 1796 | if (lhs == nullptr) return nullptr; |
| 1693 | 1797 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs); |
| 1694 | 1798 | // TODO: avoid name collisions with generated variable names |
| ... | ... | @@ -1698,7 +1802,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, |
| 1698 | 1802 | |
| 1699 | 1803 | // *_ref = *_ref + rhs; |
| 1700 | 1804 | |
| 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 | 1806 | if (rhs == nullptr) return nullptr; |
| 1703 | 1807 | |
| 1704 | 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 | 1832 | { |
| 1729 | 1833 | switch (stmt->getOpcode()) { |
| 1730 | 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 | 1836 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap); |
| 1733 | 1837 | else |
| 1734 | 1838 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult); |
| 1735 | 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 | 1841 | return nullptr; |
| 1738 | 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 | 1844 | return nullptr; |
| 1741 | 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 | 1847 | return nullptr; |
| 1744 | 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 | 1850 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap); |
| 1747 | 1851 | else |
| 1748 | 1852 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd); |
| 1749 | 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 | 1855 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap); |
| 1752 | 1856 | else |
| 1753 | 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 | 1894 | } |
| 1791 | 1895 | |
| 1792 | 1896 | static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ImplicitCastExpr *stmt) { |
| 1793 | switch (stmt->getCastKind()) { | |
| 1794 | case clang::CK_LValueToRValue: | |
| 1795 | return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | |
| 1796 | case clang::CK_IntegralCast: | |
| 1897 | switch ((ZigClangCK)stmt->getCastKind()) { | |
| 1898 | case ZigClangCK_LValueToRValue: | |
| 1899 | return trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue); | |
| 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 | 1903 | if (target_node == nullptr) |
| 1800 | 1904 | return nullptr; |
| 1801 | AstNode *node = trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), | |
| 1802 | stmt->getSubExpr()->getType(), target_node); | |
| 1905 | AstNode *node = trans_c_cast(c, bitcast(stmt->getExprLoc()), bitcast(stmt->getType()), | |
| 1906 | bitcast(stmt->getSubExpr()->getType()), target_node); | |
| 1803 | 1907 | return maybe_suppress_result(c, result_used, node); |
| 1804 | 1908 | } |
| 1805 | case clang::CK_FunctionToPointerDecay: | |
| 1806 | case clang::CK_ArrayToPointerDecay: | |
| 1909 | case ZigClangCK_FunctionToPointerDecay: | |
| 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 | 1913 | if (target_node == nullptr) |
| 1810 | 1914 | return nullptr; |
| 1811 | 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 | 1920 | if (target_node == nullptr) |
| 1817 | 1921 | return nullptr; |
| 1818 | 1922 | |
| 1819 | if (expr_types_equal(c, stmt, stmt->getSubExpr())) { | |
| 1820 | return target_node; | |
| 1821 | } | |
| 1923 | const ZigClangQualType dest_type = get_expr_qual_type(c, bitcast(stmt)); | |
| 1924 | const ZigClangQualType src_type = get_expr_qual_type(c, bitcast(stmt->getSubExpr())); | |
| 1822 | 1925 | |
| 1823 | AstNode *dest_type_node = get_expr_type(c, stmt); | |
| 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); | |
| 1926 | return trans_c_cast(c, bitcast(stmt->getBeginLoc()), dest_type, src_type, target_node); | |
| 1829 | 1927 | } |
| 1830 | case clang::CK_NullToPointer: | |
| 1831 | return trans_create_node_unsigned(c, 0); | |
| 1832 | case clang::CK_NoOp: | |
| 1833 | return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | |
| 1834 | case clang::CK_Dependent: | |
| 1835 | emit_warning(c, 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"); | |
| 1928 | case ZigClangCK_NullToPointer: | |
| 1929 | return trans_create_node(c, NodeTypeNullLiteral); | |
| 1930 | case ZigClangCK_NoOp: | |
| 1931 | return trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue); | |
| 1932 | case ZigClangCK_Dependent: | |
| 1933 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_Dependent"); | |
| 1848 | 1934 | return nullptr; |
| 1849 | case clang::CK_Dynamic: | |
| 1850 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dynamic"); | |
| 1935 | case ZigClangCK_LValueBitCast: | |
| 1936 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_LValueBitCast"); | |
| 1851 | 1937 | return nullptr; |
| 1852 | case clang::CK_ToUnion: | |
| 1853 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToUnion"); | |
| 1938 | case ZigClangCK_BaseToDerived: | |
| 1939 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_BaseToDerived"); | |
| 1854 | 1940 | return nullptr; |
| 1855 | case clang::CK_NullToMemberPointer: | |
| 1856 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NullToMemberPointer"); | |
| 1941 | case ZigClangCK_DerivedToBase: | |
| 1942 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_DerivedToBase"); | |
| 1857 | 1943 | return nullptr; |
| 1858 | case clang::CK_BaseToDerivedMemberPointer: | |
| 1859 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer"); | |
| 1944 | case ZigClangCK_UncheckedDerivedToBase: | |
| 1945 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_UncheckedDerivedToBase"); | |
| 1860 | 1946 | return nullptr; |
| 1861 | case clang::CK_DerivedToBaseMemberPointer: | |
| 1862 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer"); | |
| 1947 | case ZigClangCK_Dynamic: | |
| 1948 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_Dynamic"); | |
| 1863 | 1949 | return nullptr; |
| 1864 | case clang::CK_MemberPointerToBoolean: | |
| 1865 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_MemberPointerToBoolean"); | |
| 1950 | case ZigClangCK_ToUnion: | |
| 1951 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_ToUnion"); | |
| 1866 | 1952 | return nullptr; |
| 1867 | case clang::CK_ReinterpretMemberPointer: | |
| 1868 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ReinterpretMemberPointer"); | |
| 1953 | case ZigClangCK_NullToMemberPointer: | |
| 1954 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_NullToMemberPointer"); | |
| 1869 | 1955 | return nullptr; |
| 1870 | case clang::CK_UserDefinedConversion: | |
| 1871 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UserDefinedConversion"); | |
| 1956 | case ZigClangCK_BaseToDerivedMemberPointer: | |
| 1957 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_BaseToDerivedMemberPointer"); | |
| 1872 | 1958 | return nullptr; |
| 1873 | case clang::CK_ConstructorConversion: | |
| 1874 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ConstructorConversion"); | |
| 1959 | case ZigClangCK_DerivedToBaseMemberPointer: | |
| 1960 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_DerivedToBaseMemberPointer"); | |
| 1875 | 1961 | return nullptr; |
| 1876 | case clang::CK_IntegralToPointer: | |
| 1877 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToPointer"); | |
| 1962 | case ZigClangCK_MemberPointerToBoolean: | |
| 1963 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_MemberPointerToBoolean"); | |
| 1878 | 1964 | return nullptr; |
| 1879 | case clang::CK_PointerToIntegral: | |
| 1880 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_PointerToIntegral"); | |
| 1965 | case ZigClangCK_ReinterpretMemberPointer: | |
| 1966 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_ReinterpretMemberPointer"); | |
| 1881 | 1967 | return nullptr; |
| 1882 | case clang::CK_PointerToBoolean: | |
| 1883 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_PointerToBoolean"); | |
| 1968 | case ZigClangCK_UserDefinedConversion: | |
| 1969 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C translation cast CK_UserDefinedConversion"); | |
| 1884 | 1970 | return nullptr; |
| 1885 | case clang::CK_ToVoid: | |
| 1886 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ToVoid"); | |
| 1971 | case ZigClangCK_ConstructorConversion: | |
| 1972 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion"); | |
| 1887 | 1973 | return nullptr; |
| 1888 | case clang::CK_VectorSplat: | |
| 1889 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_VectorSplat"); | |
| 1890 | return nullptr; | |
| 1891 | case clang::CK_IntegralToBoolean: | |
| 1892 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToBoolean"); | |
| 1893 | return nullptr; | |
| 1894 | case clang::CK_IntegralToFloating: | |
| 1895 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralToFloating"); | |
| 1974 | case ZigClangCK_PointerToBoolean: | |
| 1975 | { | |
| 1976 | const clang::Expr *expr = stmt->getSubExpr(); | |
| 1977 | AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue); | |
| 1978 | if (val == nullptr) | |
| 1979 | return nullptr; | |
| 1980 | ||
| 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 | 1991 | return nullptr; |
| 1897 | case clang::CK_FixedPointCast: | |
| 1898 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FixedPointCast"); | |
| 1992 | case ZigClangCK_VectorSplat: | |
| 1993 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat"); | |
| 1899 | 1994 | return nullptr; |
| 1900 | case clang::CK_FixedPointToBoolean: | |
| 1901 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FixedPointToBoolean"); | |
| 1995 | case ZigClangCK_IntegralToBoolean: | |
| 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 | 2069 | return nullptr; |
| 1903 | case clang::CK_FloatingToIntegral: | |
| 1904 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingToIntegral"); | |
| 2070 | case ZigClangCK_FixedPointToBoolean: | |
| 2071 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean"); | |
| 1905 | 2072 | return nullptr; |
| 1906 | case clang::CK_FloatingToBoolean: | |
| 1907 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingToBoolean"); | |
| 2073 | case ZigClangCK_FloatingToBoolean: | |
| 2074 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean"); | |
| 1908 | 2075 | return nullptr; |
| 1909 | case clang::CK_BooleanToSignedIntegral: | |
| 1910 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BooleanToSignedIntegral"); | |
| 2076 | case ZigClangCK_BooleanToSignedIntegral: | |
| 2077 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BooleanToSignedIntegral"); | |
| 1911 | 2078 | return nullptr; |
| 1912 | case clang::CK_FloatingCast: | |
| 1913 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingCast"); | |
| 2079 | case ZigClangCK_FloatingCast: | |
| 2080 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingCast"); | |
| 1914 | 2081 | return nullptr; |
| 1915 | case clang::CK_CPointerToObjCPointerCast: | |
| 1916 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_CPointerToObjCPointerCast"); | |
| 2082 | case ZigClangCK_CPointerToObjCPointerCast: | |
| 2083 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_CPointerToObjCPointerCast"); | |
| 1917 | 2084 | return nullptr; |
| 1918 | case clang::CK_BlockPointerToObjCPointerCast: | |
| 1919 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BlockPointerToObjCPointerCast"); | |
| 2085 | case ZigClangCK_BlockPointerToObjCPointerCast: | |
| 2086 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BlockPointerToObjCPointerCast"); | |
| 1920 | 2087 | return nullptr; |
| 1921 | case clang::CK_AnyPointerToBlockPointerCast: | |
| 1922 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AnyPointerToBlockPointerCast"); | |
| 2088 | case ZigClangCK_AnyPointerToBlockPointerCast: | |
| 2089 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AnyPointerToBlockPointerCast"); | |
| 1923 | 2090 | return nullptr; |
| 1924 | case clang::CK_ObjCObjectLValueCast: | |
| 1925 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ObjCObjectLValueCast"); | |
| 2091 | case ZigClangCK_ObjCObjectLValueCast: | |
| 2092 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ObjCObjectLValueCast"); | |
| 1926 | 2093 | return nullptr; |
| 1927 | case clang::CK_FloatingRealToComplex: | |
| 1928 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingRealToComplex"); | |
| 2094 | case ZigClangCK_FloatingRealToComplex: | |
| 2095 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingRealToComplex"); | |
| 1929 | 2096 | return nullptr; |
| 1930 | case clang::CK_FloatingComplexToReal: | |
| 1931 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToReal"); | |
| 2097 | case ZigClangCK_FloatingComplexToReal: | |
| 2098 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToReal"); | |
| 1932 | 2099 | return nullptr; |
| 1933 | case clang::CK_FloatingComplexToBoolean: | |
| 1934 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToBoolean"); | |
| 2100 | case ZigClangCK_FloatingComplexToBoolean: | |
| 2101 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToBoolean"); | |
| 1935 | 2102 | return nullptr; |
| 1936 | case clang::CK_FloatingComplexCast: | |
| 1937 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexCast"); | |
| 2103 | case ZigClangCK_FloatingComplexCast: | |
| 2104 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexCast"); | |
| 1938 | 2105 | return nullptr; |
| 1939 | case clang::CK_FloatingComplexToIntegralComplex: | |
| 1940 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_FloatingComplexToIntegralComplex"); | |
| 2106 | case ZigClangCK_FloatingComplexToIntegralComplex: | |
| 2107 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingComplexToIntegralComplex"); | |
| 1941 | 2108 | return nullptr; |
| 1942 | case clang::CK_IntegralRealToComplex: | |
| 1943 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralRealToComplex"); | |
| 2109 | case ZigClangCK_IntegralRealToComplex: | |
| 2110 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralRealToComplex"); | |
| 1944 | 2111 | return nullptr; |
| 1945 | case clang::CK_IntegralComplexToReal: | |
| 1946 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToReal"); | |
| 2112 | case ZigClangCK_IntegralComplexToReal: | |
| 2113 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToReal"); | |
| 1947 | 2114 | return nullptr; |
| 1948 | case clang::CK_IntegralComplexToBoolean: | |
| 1949 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToBoolean"); | |
| 2115 | case ZigClangCK_IntegralComplexToBoolean: | |
| 2116 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToBoolean"); | |
| 1950 | 2117 | return nullptr; |
| 1951 | case clang::CK_IntegralComplexCast: | |
| 1952 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexCast"); | |
| 2118 | case ZigClangCK_IntegralComplexCast: | |
| 2119 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexCast"); | |
| 1953 | 2120 | return nullptr; |
| 1954 | case clang::CK_IntegralComplexToFloatingComplex: | |
| 1955 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntegralComplexToFloatingComplex"); | |
| 2121 | case ZigClangCK_IntegralComplexToFloatingComplex: | |
| 2122 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralComplexToFloatingComplex"); | |
| 1956 | 2123 | return nullptr; |
| 1957 | case clang::CK_ARCProduceObject: | |
| 1958 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCProduceObject"); | |
| 2124 | case ZigClangCK_ARCProduceObject: | |
| 2125 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCProduceObject"); | |
| 1959 | 2126 | return nullptr; |
| 1960 | case clang::CK_ARCConsumeObject: | |
| 1961 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCConsumeObject"); | |
| 2127 | case ZigClangCK_ARCConsumeObject: | |
| 2128 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCConsumeObject"); | |
| 1962 | 2129 | return nullptr; |
| 1963 | case clang::CK_ARCReclaimReturnedObject: | |
| 1964 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCReclaimReturnedObject"); | |
| 2130 | case ZigClangCK_ARCReclaimReturnedObject: | |
| 2131 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCReclaimReturnedObject"); | |
| 1965 | 2132 | return nullptr; |
| 1966 | case clang::CK_ARCExtendBlockObject: | |
| 1967 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ARCExtendBlockObject"); | |
| 2133 | case ZigClangCK_ARCExtendBlockObject: | |
| 2134 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ARCExtendBlockObject"); | |
| 1968 | 2135 | return nullptr; |
| 1969 | case clang::CK_AtomicToNonAtomic: | |
| 1970 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AtomicToNonAtomic"); | |
| 2136 | case ZigClangCK_AtomicToNonAtomic: | |
| 2137 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AtomicToNonAtomic"); | |
| 1971 | 2138 | return nullptr; |
| 1972 | case clang::CK_NonAtomicToAtomic: | |
| 1973 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_NonAtomicToAtomic"); | |
| 2139 | case ZigClangCK_NonAtomicToAtomic: | |
| 2140 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_NonAtomicToAtomic"); | |
| 1974 | 2141 | return nullptr; |
| 1975 | case clang::CK_CopyAndAutoreleaseBlockObject: | |
| 1976 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_CopyAndAutoreleaseBlockObject"); | |
| 2142 | case ZigClangCK_CopyAndAutoreleaseBlockObject: | |
| 2143 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_CopyAndAutoreleaseBlockObject"); | |
| 1977 | 2144 | return nullptr; |
| 1978 | case clang::CK_BuiltinFnToFnPtr: | |
| 1979 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_BuiltinFnToFnPtr"); | |
| 2145 | case ZigClangCK_BuiltinFnToFnPtr: | |
| 2146 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_BuiltinFnToFnPtr"); | |
| 1980 | 2147 | return nullptr; |
| 1981 | case clang::CK_ZeroToOCLOpaqueType: | |
| 1982 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_ZeroToOCLOpaqueType"); | |
| 2148 | case ZigClangCK_ZeroToOCLOpaqueType: | |
| 2149 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ZeroToOCLOpaqueType"); | |
| 1983 | 2150 | return nullptr; |
| 1984 | case clang::CK_AddressSpaceConversion: | |
| 1985 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_AddressSpaceConversion"); | |
| 2151 | case ZigClangCK_AddressSpaceConversion: | |
| 2152 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_AddressSpaceConversion"); | |
| 1986 | 2153 | return nullptr; |
| 1987 | case clang::CK_IntToOCLSampler: | |
| 1988 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CK_IntToOCLSampler"); | |
| 2154 | case ZigClangCK_IntToOCLSampler: | |
| 2155 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntToOCLSampler"); | |
| 1989 | 2156 | return nullptr; |
| 1990 | 2157 | } |
| 1991 | 2158 | zig_unreachable(); |
| ... | ... | @@ -1993,7 +2160,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra |
| 1993 | 2160 | |
| 1994 | 2161 | static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) { |
| 1995 | 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 | 2164 | Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name); |
| 1998 | 2165 | if (lrval == TransLValue) { |
| 1999 | 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 | 2171 | static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| 2005 | 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()); | |
| 2008 | 2175 | |
| 2009 | 2176 | if (result_used == ResultUsedNo) { |
| 2010 | 2177 | // common case |
| ... | ... | @@ -2060,7 +2227,7 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr |
| 2060 | 2227 | static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| 2061 | 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()); | |
| 2064 | 2231 | |
| 2065 | 2232 | if (result_used == ResultUsedNo) { |
| 2066 | 2233 | // common case |
| ... | ... | @@ -2110,50 +2277,50 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra |
| 2110 | 2277 | static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) { |
| 2111 | 2278 | switch (stmt->getOpcode()) { |
| 2112 | 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 | 2281 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 2115 | 2282 | else |
| 2116 | 2283 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 2117 | 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 | 2286 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 2120 | 2287 | else |
| 2121 | 2288 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 2122 | 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 | 2291 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 2125 | 2292 | else |
| 2126 | 2293 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 2127 | 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 | 2296 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 2130 | 2297 | else |
| 2131 | 2298 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 2132 | 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 | 2302 | if (value_node == nullptr) |
| 2136 | 2303 | return value_node; |
| 2137 | 2304 | return trans_create_node_addr_of(c, value_node); |
| 2138 | 2305 | } |
| 2139 | 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 | 2309 | if (value_node == nullptr) |
| 2143 | 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 | 2312 | if (is_fn_ptr) |
| 2146 | 2313 | return value_node; |
| 2147 | 2314 | AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node); |
| 2148 | 2315 | return trans_create_node_ptr_deref(c, unwrapped); |
| 2149 | 2316 | } |
| 2150 | 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 | 2319 | return nullptr; |
| 2153 | 2320 | case clang::UO_Minus: |
| 2154 | 2321 | { |
| 2155 | clang::Expr *op_expr = stmt->getSubExpr(); | |
| 2156 | if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) { | |
| 2322 | const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr()); | |
| 2323 | if (!qual_type_has_wrapping_overflow(c, ZigClangExpr_getType(op_expr))) { | |
| 2157 | 2324 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 2158 | 2325 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; |
| 2159 | 2326 | |
| ... | ... | @@ -2162,7 +2329,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 2162 | 2329 | return nullptr; |
| 2163 | 2330 | |
| 2164 | 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 | 2333 | // we gotta emit 0 -% x |
| 2167 | 2334 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 2168 | 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 | 2341 | node->data.bin_op_expr.bin_op = BinOpTypeSubWrap; |
| 2175 | 2342 | return node; |
| 2176 | 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 | 2345 | return nullptr; |
| 2179 | 2346 | } |
| 2180 | 2347 | } |
| 2181 | 2348 | case clang::UO_Not: |
| 2182 | 2349 | { |
| 2183 | clang::Expr *op_expr = stmt->getSubExpr(); | |
| 2350 | const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr()); | |
| 2184 | 2351 | AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 2185 | 2352 | if (sub_node == nullptr) |
| 2186 | 2353 | return nullptr; |
| ... | ... | @@ -2189,7 +2356,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 2189 | 2356 | } |
| 2190 | 2357 | case clang::UO_LNot: |
| 2191 | 2358 | { |
| 2192 | clang::Expr *op_expr = stmt->getSubExpr(); | |
| 2359 | const ZigClangExpr *op_expr = bitcast(stmt->getSubExpr()); | |
| 2193 | 2360 | AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 2194 | 2361 | if (sub_node == nullptr) |
| 2195 | 2362 | return nullptr; |
| ... | ... | @@ -2197,15 +2364,15 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 2197 | 2364 | return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node); |
| 2198 | 2365 | } |
| 2199 | 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 | 2368 | return nullptr; |
| 2202 | 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 | 2371 | return nullptr; |
| 2205 | 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 | 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 | 2376 | return nullptr; |
| 2210 | 2377 | } |
| 2211 | 2378 | zig_unreachable(); |
| ... | ... | @@ -2225,249 +2392,250 @@ static int trans_local_declaration(Context *c, TransScope *scope, const clang::D |
| 2225 | 2392 | switch (decl->getKind()) { |
| 2226 | 2393 | case clang::Decl::Var: { |
| 2227 | 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 | 2396 | AstNode *init_node = nullptr; |
| 2230 | 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 | 2399 | if (init_node == nullptr) |
| 2233 | 2400 | return ErrorUnexpected; |
| 2234 | 2401 | |
| 2235 | 2402 | } else { |
| 2236 | 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 | 2406 | if (type_node == nullptr) |
| 2240 | 2407 | return ErrorUnexpected; |
| 2241 | 2408 | |
| 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)); | |
| 2243 | 2410 | |
| 2244 | 2411 | TransScopeVar *var_scope = trans_scope_var_create(c, scope, c_symbol_name); |
| 2245 | 2412 | scope = &var_scope->base; |
| 2246 | 2413 | |
| 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 | 2416 | var_scope->zig_name, type_node, init_node); |
| 2249 | 2417 | |
| 2250 | 2418 | scope_block->node->data.block.statements.append(node); |
| 2251 | 2419 | continue; |
| 2252 | 2420 | } |
| 2253 | 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 | 2423 | return ErrorUnexpected; |
| 2256 | 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 | 2426 | return ErrorUnexpected; |
| 2259 | 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 | 2429 | return ErrorUnexpected; |
| 2262 | 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 | 2432 | return ErrorUnexpected; |
| 2265 | 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 | 2435 | return ErrorUnexpected; |
| 2268 | 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 | 2438 | return ErrorUnexpected; |
| 2271 | 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 | 2441 | return ErrorUnexpected; |
| 2274 | 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 | 2444 | return ErrorUnexpected; |
| 2277 | 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 | 2447 | return ErrorUnexpected; |
| 2280 | 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 | 2450 | return ErrorUnexpected; |
| 2283 | 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 | 2453 | return ErrorUnexpected; |
| 2286 | 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 | 2456 | return ErrorUnexpected; |
| 2289 | 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 | 2459 | return ErrorUnexpected; |
| 2292 | 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 | 2462 | return ErrorUnexpected; |
| 2295 | 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 | 2465 | return ErrorUnexpected; |
| 2298 | 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 | 2468 | return ErrorUnexpected; |
| 2301 | 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 | 2471 | return ErrorUnexpected; |
| 2304 | 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 | 2474 | return ErrorUnexpected; |
| 2307 | 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 | 2477 | return ErrorUnexpected; |
| 2310 | 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 | 2480 | return ErrorUnexpected; |
| 2313 | 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 | 2483 | return ErrorUnexpected; |
| 2316 | 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 | 2486 | return ErrorUnexpected; |
| 2319 | 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 | 2489 | return ErrorUnexpected; |
| 2322 | 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 | 2492 | return ErrorUnexpected; |
| 2325 | 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 | 2495 | return ErrorUnexpected; |
| 2328 | 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 | 2498 | return ErrorUnexpected; |
| 2331 | 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 | 2501 | return ErrorUnexpected; |
| 2334 | 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 | 2504 | return ErrorUnexpected; |
| 2337 | 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 | 2507 | return ErrorUnexpected; |
| 2340 | 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 | 2510 | return ErrorUnexpected; |
| 2343 | 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 | 2513 | return ErrorUnexpected; |
| 2346 | 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 | 2516 | return ErrorUnexpected; |
| 2349 | 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 | 2519 | return ErrorUnexpected; |
| 2352 | 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 | 2522 | return ErrorUnexpected; |
| 2355 | 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 | 2525 | return ErrorUnexpected; |
| 2358 | 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 | 2528 | return ErrorUnexpected; |
| 2361 | 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 | 2531 | return ErrorUnexpected; |
| 2364 | 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 | 2534 | return ErrorUnexpected; |
| 2367 | 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 | 2537 | return ErrorUnexpected; |
| 2370 | 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 | 2540 | return ErrorUnexpected; |
| 2373 | 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 | 2543 | return ErrorUnexpected; |
| 2376 | 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 | 2546 | return ErrorUnexpected; |
| 2379 | 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 | 2549 | return ErrorUnexpected; |
| 2382 | 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 | 2552 | return ErrorUnexpected; |
| 2385 | 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 | 2555 | return ErrorUnexpected; |
| 2388 | 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 | 2558 | return ErrorUnexpected; |
| 2391 | 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 | 2561 | return ErrorUnexpected; |
| 2394 | 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 | 2564 | return ErrorUnexpected; |
| 2397 | 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 | 2567 | return ErrorUnexpected; |
| 2400 | 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 | 2570 | return ErrorUnexpected; |
| 2403 | 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 | 2573 | return ErrorUnexpected; |
| 2406 | 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 | 2576 | return ErrorUnexpected; |
| 2409 | 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 | 2579 | return ErrorUnexpected; |
| 2412 | 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 | 2582 | return ErrorUnexpected; |
| 2415 | 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 | 2585 | return ErrorUnexpected; |
| 2418 | 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 | 2588 | return ErrorUnexpected; |
| 2421 | 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 | 2591 | return ErrorUnexpected; |
| 2424 | 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 | 2594 | return ErrorUnexpected; |
| 2427 | 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 | 2597 | return ErrorUnexpected; |
| 2430 | 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 | 2600 | return ErrorUnexpected; |
| 2433 | 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 | 2603 | return ErrorUnexpected; |
| 2436 | 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 | 2606 | return ErrorUnexpected; |
| 2439 | 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 | 2609 | return ErrorUnexpected; |
| 2442 | 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 | 2612 | return ErrorUnexpected; |
| 2445 | 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 | 2615 | return ErrorUnexpected; |
| 2448 | 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 | 2618 | return ErrorUnexpected; |
| 2451 | 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 | 2621 | return ErrorUnexpected; |
| 2454 | 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 | 2624 | return ErrorUnexpected; |
| 2457 | 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 | 2627 | return ErrorUnexpected; |
| 2460 | 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 | 2630 | return ErrorUnexpected; |
| 2463 | 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 | 2633 | return ErrorUnexpected; |
| 2466 | 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 | 2636 | return ErrorUnexpected; |
| 2469 | 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 | 2639 | return ErrorUnexpected; |
| 2472 | 2640 | } |
| 2473 | 2641 | zig_unreachable(); |
| ... | ... | @@ -2493,7 +2661,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) |
| 2493 | 2661 | return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast); |
| 2494 | 2662 | } |
| 2495 | 2663 | |
| 2496 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval) { | |
| 2664 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr, TransLRValue lrval) { | |
| 2497 | 2665 | AstNode *res = trans_expr(c, result_used, scope, expr, lrval); |
| 2498 | 2666 | if (res == nullptr) |
| 2499 | 2667 | return nullptr; |
| ... | ... | @@ -2530,146 +2698,145 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2530 | 2698 | } |
| 2531 | 2699 | |
| 2532 | 2700 | |
| 2533 | const clang::Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr(); | |
| 2534 | auto classs = ty->getTypeClass(); | |
| 2701 | const ZigClangType *ty = ZigClangQualType_getTypePtr(get_expr_qual_type_before_implicit_cast(c, expr)); | |
| 2702 | auto classs = ZigClangType_getTypeClass(ty); | |
| 2535 | 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); | |
| 2539 | switch (builtin_ty->getKind()) { | |
| 2540 | case clang::BuiltinType::Bool: | |
| 2541 | case clang::BuiltinType::Char_U: | |
| 2542 | case clang::BuiltinType::UChar: | |
| 2543 | case clang::BuiltinType::Char_S: | |
| 2544 | case clang::BuiltinType::SChar: | |
| 2545 | case clang::BuiltinType::UShort: | |
| 2546 | case clang::BuiltinType::UInt: | |
| 2547 | case clang::BuiltinType::ULong: | |
| 2548 | case clang::BuiltinType::ULongLong: | |
| 2549 | case clang::BuiltinType::Short: | |
| 2550 | case clang::BuiltinType::Int: | |
| 2551 | case clang::BuiltinType::Long: | |
| 2552 | case clang::BuiltinType::LongLong: | |
| 2553 | case clang::BuiltinType::UInt128: | |
| 2554 | case clang::BuiltinType::Int128: | |
| 2555 | case clang::BuiltinType::Float: | |
| 2556 | case clang::BuiltinType::Double: | |
| 2557 | case clang::BuiltinType::Float128: | |
| 2558 | case clang::BuiltinType::LongDouble: | |
| 2559 | case clang::BuiltinType::WChar_U: | |
| 2560 | case clang::BuiltinType::Char8: | |
| 2561 | case clang::BuiltinType::Char16: | |
| 2562 | case clang::BuiltinType::Char32: | |
| 2563 | case clang::BuiltinType::WChar_S: | |
| 2564 | case clang::BuiltinType::Float16: | |
| 2706 | const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty); | |
| 2707 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { | |
| 2708 | case ZigClangBuiltinTypeBool: | |
| 2709 | case ZigClangBuiltinTypeChar_U: | |
| 2710 | case ZigClangBuiltinTypeUChar: | |
| 2711 | case ZigClangBuiltinTypeChar_S: | |
| 2712 | case ZigClangBuiltinTypeSChar: | |
| 2713 | case ZigClangBuiltinTypeUShort: | |
| 2714 | case ZigClangBuiltinTypeUInt: | |
| 2715 | case ZigClangBuiltinTypeULong: | |
| 2716 | case ZigClangBuiltinTypeULongLong: | |
| 2717 | case ZigClangBuiltinTypeShort: | |
| 2718 | case ZigClangBuiltinTypeInt: | |
| 2719 | case ZigClangBuiltinTypeLong: | |
| 2720 | case ZigClangBuiltinTypeLongLong: | |
| 2721 | case ZigClangBuiltinTypeUInt128: | |
| 2722 | case ZigClangBuiltinTypeInt128: | |
| 2723 | case ZigClangBuiltinTypeFloat: | |
| 2724 | case ZigClangBuiltinTypeDouble: | |
| 2725 | case ZigClangBuiltinTypeFloat128: | |
| 2726 | case ZigClangBuiltinTypeLongDouble: | |
| 2727 | case ZigClangBuiltinTypeWChar_U: | |
| 2728 | case ZigClangBuiltinTypeChar8: | |
| 2729 | case ZigClangBuiltinTypeChar16: | |
| 2730 | case ZigClangBuiltinTypeChar32: | |
| 2731 | case ZigClangBuiltinTypeWChar_S: | |
| 2732 | case ZigClangBuiltinTypeFloat16: | |
| 2565 | 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 | 2735 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, |
| 2568 | trans_create_node_unsigned(c, 0)); | |
| 2569 | ||
| 2570 | case clang::BuiltinType::Void: | |
| 2571 | case clang::BuiltinType::Half: | |
| 2572 | case clang::BuiltinType::ObjCId: | |
| 2573 | case clang::BuiltinType::ObjCClass: | |
| 2574 | case clang::BuiltinType::ObjCSel: | |
| 2575 | case clang::BuiltinType::OMPArraySection: | |
| 2576 | case clang::BuiltinType::Dependent: | |
| 2577 | case clang::BuiltinType::Overload: | |
| 2578 | case clang::BuiltinType::BoundMember: | |
| 2579 | case clang::BuiltinType::PseudoObject: | |
| 2580 | case clang::BuiltinType::UnknownAny: | |
| 2581 | case clang::BuiltinType::BuiltinFn: | |
| 2582 | case clang::BuiltinType::ARCUnbridgedCast: | |
| 2583 | case clang::BuiltinType::OCLImage1dRO: | |
| 2584 | case clang::BuiltinType::OCLImage1dArrayRO: | |
| 2585 | case clang::BuiltinType::OCLImage1dBufferRO: | |
| 2586 | case clang::BuiltinType::OCLImage2dRO: | |
| 2587 | case clang::BuiltinType::OCLImage2dArrayRO: | |
| 2588 | case clang::BuiltinType::OCLImage2dDepthRO: | |
| 2589 | case clang::BuiltinType::OCLImage2dArrayDepthRO: | |
| 2590 | case clang::BuiltinType::OCLImage2dMSAARO: | |
| 2591 | case clang::BuiltinType::OCLImage2dArrayMSAARO: | |
| 2592 | case clang::BuiltinType::OCLImage2dMSAADepthRO: | |
| 2593 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRO: | |
| 2594 | case clang::BuiltinType::OCLImage3dRO: | |
| 2595 | case clang::BuiltinType::OCLImage1dWO: | |
| 2596 | case clang::BuiltinType::OCLImage1dArrayWO: | |
| 2597 | case clang::BuiltinType::OCLImage1dBufferWO: | |
| 2598 | case clang::BuiltinType::OCLImage2dWO: | |
| 2599 | case clang::BuiltinType::OCLImage2dArrayWO: | |
| 2600 | case clang::BuiltinType::OCLImage2dDepthWO: | |
| 2601 | case clang::BuiltinType::OCLImage2dArrayDepthWO: | |
| 2602 | case clang::BuiltinType::OCLImage2dMSAAWO: | |
| 2603 | case clang::BuiltinType::OCLImage2dArrayMSAAWO: | |
| 2604 | case clang::BuiltinType::OCLImage2dMSAADepthWO: | |
| 2605 | case clang::BuiltinType::OCLImage2dArrayMSAADepthWO: | |
| 2606 | case clang::BuiltinType::OCLImage3dWO: | |
| 2607 | case clang::BuiltinType::OCLImage1dRW: | |
| 2608 | case clang::BuiltinType::OCLImage1dArrayRW: | |
| 2609 | case clang::BuiltinType::OCLImage1dBufferRW: | |
| 2610 | case clang::BuiltinType::OCLImage2dRW: | |
| 2611 | case clang::BuiltinType::OCLImage2dArrayRW: | |
| 2612 | case clang::BuiltinType::OCLImage2dDepthRW: | |
| 2613 | case clang::BuiltinType::OCLImage2dArrayDepthRW: | |
| 2614 | case clang::BuiltinType::OCLImage2dMSAARW: | |
| 2615 | case clang::BuiltinType::OCLImage2dArrayMSAARW: | |
| 2616 | case clang::BuiltinType::OCLImage2dMSAADepthRW: | |
| 2617 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRW: | |
| 2618 | case clang::BuiltinType::OCLImage3dRW: | |
| 2619 | case clang::BuiltinType::OCLSampler: | |
| 2620 | case clang::BuiltinType::OCLEvent: | |
| 2621 | case clang::BuiltinType::OCLClkEvent: | |
| 2622 | case clang::BuiltinType::OCLQueue: | |
| 2623 | case clang::BuiltinType::OCLReserveID: | |
| 2624 | case clang::BuiltinType::ShortAccum: | |
| 2625 | case clang::BuiltinType::Accum: | |
| 2626 | case clang::BuiltinType::LongAccum: | |
| 2627 | case clang::BuiltinType::UShortAccum: | |
| 2628 | case clang::BuiltinType::UAccum: | |
| 2629 | case clang::BuiltinType::ULongAccum: | |
| 2630 | case clang::BuiltinType::ShortFract: | |
| 2631 | case clang::BuiltinType::Fract: | |
| 2632 | case clang::BuiltinType::LongFract: | |
| 2633 | case clang::BuiltinType::UShortFract: | |
| 2634 | case clang::BuiltinType::UFract: | |
| 2635 | case clang::BuiltinType::ULongFract: | |
| 2636 | case clang::BuiltinType::SatShortAccum: | |
| 2637 | case clang::BuiltinType::SatAccum: | |
| 2638 | case clang::BuiltinType::SatLongAccum: | |
| 2639 | case clang::BuiltinType::SatUShortAccum: | |
| 2640 | case clang::BuiltinType::SatUAccum: | |
| 2641 | case clang::BuiltinType::SatULongAccum: | |
| 2642 | case clang::BuiltinType::SatShortFract: | |
| 2643 | case clang::BuiltinType::SatFract: | |
| 2644 | case clang::BuiltinType::SatLongFract: | |
| 2645 | case clang::BuiltinType::SatUShortFract: | |
| 2646 | case clang::BuiltinType::SatUFract: | |
| 2647 | case clang::BuiltinType::SatULongFract: | |
| 2648 | case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload: | |
| 2649 | case clang::BuiltinType::OCLIntelSubgroupAVCImePayload: | |
| 2650 | case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload: | |
| 2651 | case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload: | |
| 2652 | case clang::BuiltinType::OCLIntelSubgroupAVCMceResult: | |
| 2653 | case clang::BuiltinType::OCLIntelSubgroupAVCImeResult: | |
| 2654 | case clang::BuiltinType::OCLIntelSubgroupAVCRefResult: | |
| 2655 | case clang::BuiltinType::OCLIntelSubgroupAVCSicResult: | |
| 2656 | case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout: | |
| 2657 | case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout: | |
| 2658 | case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin: | |
| 2659 | case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin: | |
| 2736 | trans_create_node(c, NodeTypeNullLiteral)); | |
| 2737 | ||
| 2738 | case ZigClangBuiltinTypeVoid: | |
| 2739 | case ZigClangBuiltinTypeHalf: | |
| 2740 | case ZigClangBuiltinTypeObjCId: | |
| 2741 | case ZigClangBuiltinTypeObjCClass: | |
| 2742 | case ZigClangBuiltinTypeObjCSel: | |
| 2743 | case ZigClangBuiltinTypeOMPArraySection: | |
| 2744 | case ZigClangBuiltinTypeDependent: | |
| 2745 | case ZigClangBuiltinTypeOverload: | |
| 2746 | case ZigClangBuiltinTypeBoundMember: | |
| 2747 | case ZigClangBuiltinTypePseudoObject: | |
| 2748 | case ZigClangBuiltinTypeUnknownAny: | |
| 2749 | case ZigClangBuiltinTypeBuiltinFn: | |
| 2750 | case ZigClangBuiltinTypeARCUnbridgedCast: | |
| 2751 | case ZigClangBuiltinTypeOCLImage1dRO: | |
| 2752 | case ZigClangBuiltinTypeOCLImage1dArrayRO: | |
| 2753 | case ZigClangBuiltinTypeOCLImage1dBufferRO: | |
| 2754 | case ZigClangBuiltinTypeOCLImage2dRO: | |
| 2755 | case ZigClangBuiltinTypeOCLImage2dArrayRO: | |
| 2756 | case ZigClangBuiltinTypeOCLImage2dDepthRO: | |
| 2757 | case ZigClangBuiltinTypeOCLImage2dArrayDepthRO: | |
| 2758 | case ZigClangBuiltinTypeOCLImage2dMSAARO: | |
| 2759 | case ZigClangBuiltinTypeOCLImage2dArrayMSAARO: | |
| 2760 | case ZigClangBuiltinTypeOCLImage2dMSAADepthRO: | |
| 2761 | case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO: | |
| 2762 | case ZigClangBuiltinTypeOCLImage3dRO: | |
| 2763 | case ZigClangBuiltinTypeOCLImage1dWO: | |
| 2764 | case ZigClangBuiltinTypeOCLImage1dArrayWO: | |
| 2765 | case ZigClangBuiltinTypeOCLImage1dBufferWO: | |
| 2766 | case ZigClangBuiltinTypeOCLImage2dWO: | |
| 2767 | case ZigClangBuiltinTypeOCLImage2dArrayWO: | |
| 2768 | case ZigClangBuiltinTypeOCLImage2dDepthWO: | |
| 2769 | case ZigClangBuiltinTypeOCLImage2dArrayDepthWO: | |
| 2770 | case ZigClangBuiltinTypeOCLImage2dMSAAWO: | |
| 2771 | case ZigClangBuiltinTypeOCLImage2dArrayMSAAWO: | |
| 2772 | case ZigClangBuiltinTypeOCLImage2dMSAADepthWO: | |
| 2773 | case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO: | |
| 2774 | case ZigClangBuiltinTypeOCLImage3dWO: | |
| 2775 | case ZigClangBuiltinTypeOCLImage1dRW: | |
| 2776 | case ZigClangBuiltinTypeOCLImage1dArrayRW: | |
| 2777 | case ZigClangBuiltinTypeOCLImage1dBufferRW: | |
| 2778 | case ZigClangBuiltinTypeOCLImage2dRW: | |
| 2779 | case ZigClangBuiltinTypeOCLImage2dArrayRW: | |
| 2780 | case ZigClangBuiltinTypeOCLImage2dDepthRW: | |
| 2781 | case ZigClangBuiltinTypeOCLImage2dArrayDepthRW: | |
| 2782 | case ZigClangBuiltinTypeOCLImage2dMSAARW: | |
| 2783 | case ZigClangBuiltinTypeOCLImage2dArrayMSAARW: | |
| 2784 | case ZigClangBuiltinTypeOCLImage2dMSAADepthRW: | |
| 2785 | case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW: | |
| 2786 | case ZigClangBuiltinTypeOCLImage3dRW: | |
| 2787 | case ZigClangBuiltinTypeOCLSampler: | |
| 2788 | case ZigClangBuiltinTypeOCLEvent: | |
| 2789 | case ZigClangBuiltinTypeOCLClkEvent: | |
| 2790 | case ZigClangBuiltinTypeOCLQueue: | |
| 2791 | case ZigClangBuiltinTypeOCLReserveID: | |
| 2792 | case ZigClangBuiltinTypeShortAccum: | |
| 2793 | case ZigClangBuiltinTypeAccum: | |
| 2794 | case ZigClangBuiltinTypeLongAccum: | |
| 2795 | case ZigClangBuiltinTypeUShortAccum: | |
| 2796 | case ZigClangBuiltinTypeUAccum: | |
| 2797 | case ZigClangBuiltinTypeULongAccum: | |
| 2798 | case ZigClangBuiltinTypeShortFract: | |
| 2799 | case ZigClangBuiltinTypeFract: | |
| 2800 | case ZigClangBuiltinTypeLongFract: | |
| 2801 | case ZigClangBuiltinTypeUShortFract: | |
| 2802 | case ZigClangBuiltinTypeUFract: | |
| 2803 | case ZigClangBuiltinTypeULongFract: | |
| 2804 | case ZigClangBuiltinTypeSatShortAccum: | |
| 2805 | case ZigClangBuiltinTypeSatAccum: | |
| 2806 | case ZigClangBuiltinTypeSatLongAccum: | |
| 2807 | case ZigClangBuiltinTypeSatUShortAccum: | |
| 2808 | case ZigClangBuiltinTypeSatUAccum: | |
| 2809 | case ZigClangBuiltinTypeSatULongAccum: | |
| 2810 | case ZigClangBuiltinTypeSatShortFract: | |
| 2811 | case ZigClangBuiltinTypeSatFract: | |
| 2812 | case ZigClangBuiltinTypeSatLongFract: | |
| 2813 | case ZigClangBuiltinTypeSatUShortFract: | |
| 2814 | case ZigClangBuiltinTypeSatUFract: | |
| 2815 | case ZigClangBuiltinTypeSatULongFract: | |
| 2816 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload: | |
| 2817 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload: | |
| 2818 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload: | |
| 2819 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload: | |
| 2820 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult: | |
| 2821 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult: | |
| 2822 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult: | |
| 2823 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult: | |
| 2824 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout: | |
| 2825 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout: | |
| 2826 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin: | |
| 2827 | case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin: | |
| 2660 | 2828 | return res; |
| 2661 | 2829 | } |
| 2662 | 2830 | break; |
| 2663 | 2831 | } |
| 2664 | case clang::Type::Pointer: | |
| 2665 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, | |
| 2666 | trans_create_node_unsigned(c, 0)); | |
| 2832 | case ZigClangType_Pointer: | |
| 2833 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral)); | |
| 2667 | 2834 | |
| 2668 | case clang::Type::Typedef: | |
| 2835 | case ZigClangType_Typedef: | |
| 2669 | 2836 | { |
| 2670 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); | |
| 2671 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 2672 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl()); | |
| 2837 | const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty); | |
| 2838 | const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); | |
| 2839 | auto existing_entry = c->decl_table.maybe_get((void*)ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)); | |
| 2673 | 2840 | if (existing_entry) { |
| 2674 | 2841 | return existing_entry->value; |
| 2675 | 2842 | } |
| ... | ... | @@ -2677,19 +2844,20 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2677 | 2844 | return res; |
| 2678 | 2845 | } |
| 2679 | 2846 | |
| 2680 | case clang::Type::Enum: | |
| 2847 | case ZigClangType_Enum: | |
| 2681 | 2848 | { |
| 2682 | const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty); | |
| 2683 | AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl()); | |
| 2849 | const ZigClangEnumType *enum_ty = reinterpret_cast<const ZigClangEnumType *>(ty); | |
| 2850 | AstNode *enum_type = resolve_enum_decl(c, ZigClangEnumType_getDecl(enum_ty)); | |
| 2684 | 2851 | return to_enum_zero_cmp(c, res, enum_type); |
| 2685 | 2852 | } |
| 2686 | 2853 | |
| 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 | 2857 | switch (elaborated_ty->getKeyword()) { |
| 2691 | 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 | 2861 | return to_enum_zero_cmp(c, res, enum_type); |
| 2694 | 2862 | } |
| 2695 | 2863 | case clang::ETK_Struct: |
| ... | ... | @@ -2702,48 +2870,48 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2702 | 2870 | } |
| 2703 | 2871 | } |
| 2704 | 2872 | |
| 2705 | case clang::Type::FunctionProto: | |
| 2706 | case clang::Type::Record: | |
| 2707 | case clang::Type::ConstantArray: | |
| 2708 | case clang::Type::Paren: | |
| 2709 | case clang::Type::Decayed: | |
| 2710 | case clang::Type::Attributed: | |
| 2711 | case clang::Type::IncompleteArray: | |
| 2712 | case clang::Type::BlockPointer: | |
| 2713 | case clang::Type::LValueReference: | |
| 2714 | case clang::Type::RValueReference: | |
| 2715 | case clang::Type::MemberPointer: | |
| 2716 | case clang::Type::VariableArray: | |
| 2717 | case clang::Type::DependentSizedArray: | |
| 2718 | case clang::Type::DependentSizedExtVector: | |
| 2719 | case clang::Type::Vector: | |
| 2720 | case clang::Type::ExtVector: | |
| 2721 | case clang::Type::FunctionNoProto: | |
| 2722 | case clang::Type::UnresolvedUsing: | |
| 2723 | case clang::Type::Adjusted: | |
| 2724 | case clang::Type::TypeOfExpr: | |
| 2725 | case clang::Type::TypeOf: | |
| 2726 | case clang::Type::Decltype: | |
| 2727 | case clang::Type::UnaryTransform: | |
| 2728 | case clang::Type::TemplateTypeParm: | |
| 2729 | case clang::Type::SubstTemplateTypeParm: | |
| 2730 | case clang::Type::SubstTemplateTypeParmPack: | |
| 2731 | case clang::Type::TemplateSpecialization: | |
| 2732 | case clang::Type::Auto: | |
| 2733 | case clang::Type::InjectedClassName: | |
| 2734 | case clang::Type::DependentName: | |
| 2735 | case clang::Type::DependentTemplateSpecialization: | |
| 2736 | case clang::Type::PackExpansion: | |
| 2737 | case clang::Type::ObjCObject: | |
| 2738 | case clang::Type::ObjCInterface: | |
| 2739 | case clang::Type::Complex: | |
| 2740 | case clang::Type::ObjCObjectPointer: | |
| 2741 | case clang::Type::Atomic: | |
| 2742 | case clang::Type::Pipe: | |
| 2743 | case clang::Type::ObjCTypeParam: | |
| 2744 | case clang::Type::DeducedTemplateSpecialization: | |
| 2745 | case clang::Type::DependentAddressSpace: | |
| 2746 | case clang::Type::DependentVector: | |
| 2873 | case ZigClangType_FunctionProto: | |
| 2874 | case ZigClangType_Record: | |
| 2875 | case ZigClangType_ConstantArray: | |
| 2876 | case ZigClangType_Paren: | |
| 2877 | case ZigClangType_Decayed: | |
| 2878 | case ZigClangType_Attributed: | |
| 2879 | case ZigClangType_IncompleteArray: | |
| 2880 | case ZigClangType_BlockPointer: | |
| 2881 | case ZigClangType_LValueReference: | |
| 2882 | case ZigClangType_RValueReference: | |
| 2883 | case ZigClangType_MemberPointer: | |
| 2884 | case ZigClangType_VariableArray: | |
| 2885 | case ZigClangType_DependentSizedArray: | |
| 2886 | case ZigClangType_DependentSizedExtVector: | |
| 2887 | case ZigClangType_Vector: | |
| 2888 | case ZigClangType_ExtVector: | |
| 2889 | case ZigClangType_FunctionNoProto: | |
| 2890 | case ZigClangType_UnresolvedUsing: | |
| 2891 | case ZigClangType_Adjusted: | |
| 2892 | case ZigClangType_TypeOfExpr: | |
| 2893 | case ZigClangType_TypeOf: | |
| 2894 | case ZigClangType_Decltype: | |
| 2895 | case ZigClangType_UnaryTransform: | |
| 2896 | case ZigClangType_TemplateTypeParm: | |
| 2897 | case ZigClangType_SubstTemplateTypeParm: | |
| 2898 | case ZigClangType_SubstTemplateTypeParmPack: | |
| 2899 | case ZigClangType_TemplateSpecialization: | |
| 2900 | case ZigClangType_Auto: | |
| 2901 | case ZigClangType_InjectedClassName: | |
| 2902 | case ZigClangType_DependentName: | |
| 2903 | case ZigClangType_DependentTemplateSpecialization: | |
| 2904 | case ZigClangType_PackExpansion: | |
| 2905 | case ZigClangType_ObjCObject: | |
| 2906 | case ZigClangType_ObjCInterface: | |
| 2907 | case ZigClangType_Complex: | |
| 2908 | case ZigClangType_ObjCObjectPointer: | |
| 2909 | case ZigClangType_Atomic: | |
| 2910 | case ZigClangType_Pipe: | |
| 2911 | case ZigClangType_ObjCTypeParam: | |
| 2912 | case ZigClangType_DeducedTemplateSpecialization: | |
| 2913 | case ZigClangType_DependentAddressSpace: | |
| 2914 | case ZigClangType_DependentVector: | |
| 2747 | 2915 | return res; |
| 2748 | 2916 | } |
| 2749 | 2917 | zig_unreachable(); |
| ... | ... | @@ -2752,11 +2920,12 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2752 | 2920 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) { |
| 2753 | 2921 | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); |
| 2754 | 2922 | |
| 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 | 2925 | if (while_scope->node->data.while_expr.condition == nullptr) |
| 2757 | 2926 | return nullptr; |
| 2758 | 2927 | |
| 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 | 2929 | &while_scope->node->data.while_expr.body); |
| 2761 | 2930 | if (body_scope == nullptr) |
| 2762 | 2931 | return nullptr; |
| ... | ... | @@ -2769,17 +2938,18 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::I |
| 2769 | 2938 | // if (c) t else e |
| 2770 | 2939 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2771 | 2940 | |
| 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 | 2942 | if (then_scope == nullptr) |
| 2774 | 2943 | return nullptr; |
| 2775 | 2944 | |
| 2776 | 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 | 2947 | if (else_scope == nullptr) |
| 2779 | 2948 | return nullptr; |
| 2780 | 2949 | } |
| 2781 | 2950 | |
| 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 | 2953 | if (if_node->data.if_bool_expr.condition == nullptr) |
| 2784 | 2954 | return nullptr; |
| 2785 | 2955 | |
| ... | ... | @@ -2789,18 +2959,18 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::I |
| 2789 | 2959 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) { |
| 2790 | 2960 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 2791 | 2961 | |
| 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 | 2963 | if (callee_raw_node == nullptr) |
| 2794 | 2964 | return nullptr; |
| 2795 | 2965 | |
| 2796 | 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 | 2968 | AstNode *callee_node = nullptr; |
| 2799 | 2969 | if (is_ptr && fn_ty) { |
| 2800 | if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) { | |
| 2970 | if ((ZigClangStmtClass)stmt->getCallee()->getStmtClass() == ZigClangStmt_ImplicitCastExprClass) { | |
| 2801 | 2971 | const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee()); |
| 2802 | if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) { | |
| 2803 | if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) { | |
| 2972 | if ((ZigClangCK)implicit_cast->getCastKind() == ZigClangCK_FunctionToPointerDecay) { | |
| 2973 | if ((ZigClangStmtClass)implicit_cast->getSubExpr()->getStmtClass() == ZigClangStmt_DeclRefExprClass) { | |
| 2804 | 2974 | const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr()); |
| 2805 | 2975 | const clang::Decl *decl = decl_ref->getFoundDecl(); |
| 2806 | 2976 | if (decl->getKind() == clang::Decl::Function) { |
| ... | ... | @@ -2819,7 +2989,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2819 | 2989 | node->data.fn_call_expr.fn_ref_expr = callee_node; |
| 2820 | 2990 | |
| 2821 | 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 | 2993 | for (unsigned i = 0; i < num_args; i += 1) { |
| 2824 | 2994 | AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue); |
| 2825 | 2995 | if (arg_node == nullptr) |
| ... | ... | @@ -2828,7 +2998,9 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2828 | 2998 | node->data.fn_call_expr.params.append(arg_node); |
| 2829 | 2999 | } |
| 2830 | 3000 | |
| 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 | 3004 | node = trans_create_node_bin_op(c, trans_create_node_symbol_str(c, "_"), BinOpTypeAssign, node); |
| 2833 | 3005 | } |
| 2834 | 3006 | |
| ... | ... | @@ -2838,7 +3010,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2838 | 3010 | static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope *scope, |
| 2839 | 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 | 3014 | if (container_node == nullptr) |
| 2843 | 3015 | return nullptr; |
| 2844 | 3016 | |
| ... | ... | @@ -2846,18 +3018,18 @@ static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope |
| 2846 | 3018 | container_node = trans_create_node_unwrap_null(c, container_node); |
| 2847 | 3019 | } |
| 2848 | 3020 | |
| 2849 | const char *name = decl_name(stmt->getMemberDecl()); | |
| 3021 | const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)stmt->getMemberDecl()); | |
| 2850 | 3022 | |
| 2851 | 3023 | AstNode *node = trans_create_node_field_access_str(c, container_node, name); |
| 2852 | 3024 | return maybe_suppress_result(c, result_used, node); |
| 2853 | 3025 | } |
| 2854 | 3026 | |
| 2855 | 3027 | static 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 | 3029 | if (container_node == nullptr) |
| 2858 | 3030 | return nullptr; |
| 2859 | 3031 | |
| 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 | 3033 | if (idx_node == nullptr) |
| 2862 | 3034 | return nullptr; |
| 2863 | 3035 | |
| ... | ... | @@ -2871,11 +3043,12 @@ static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, T |
| 2871 | 3043 | static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, |
| 2872 | 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 | 3047 | if (sub_expr_node == nullptr) |
| 2876 | 3048 | return nullptr; |
| 2877 | 3049 | |
| 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 | 3052 | if (cast == nullptr) |
| 2880 | 3053 | return nullptr; |
| 2881 | 3054 | |
| ... | ... | @@ -2885,7 +3058,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran |
| 2885 | 3058 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, ResultUsed result_used, |
| 2886 | 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 | 3062 | if (type_node == nullptr) |
| 2890 | 3063 | return nullptr; |
| 2891 | 3064 | |
| ... | ... | @@ -2901,7 +3074,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang: |
| 2901 | 3074 | |
| 2902 | 3075 | AstNode *body_node; |
| 2903 | 3076 | TransScope *child_scope; |
| 2904 | if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) { | |
| 3077 | if ((ZigClangStmtClass)stmt->getBody()->getStmtClass() == ZigClangStmt_CompoundStmtClass) { | |
| 2905 | 3078 | // there's already a block in C, so we'll append our condition to it. |
| 2906 | 3079 | // c: do { |
| 2907 | 3080 | // c: a; |
| ... | ... | @@ -2914,7 +3087,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang: |
| 2914 | 3087 | // zig: } |
| 2915 | 3088 | |
| 2916 | 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 | 3091 | nullptr, &child_scope)) |
| 2919 | 3092 | { |
| 2920 | 3093 | return nullptr; |
| ... | ... | @@ -2932,7 +3105,7 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang: |
| 2932 | 3105 | TransScopeBlock *child_block_scope = trans_scope_block_create(c, &while_scope->base); |
| 2933 | 3106 | body_node = child_block_scope->node; |
| 2934 | 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 | 3109 | if (child_scope == nullptr) return nullptr; |
| 2937 | 3110 | if (child_statement != nullptr) { |
| 2938 | 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 | 3113 | } |
| 2941 | 3114 | |
| 2942 | 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 | 3117 | if (condition_node == nullptr) return nullptr; |
| 2945 | 3118 | AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2946 | 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 | 3131 | AstNode *loop_block_node; |
| 2959 | 3132 | TransScopeWhile *while_scope; |
| 2960 | 3133 | TransScope *cond_scope; |
| 2961 | const clang::Stmt *init_stmt = stmt->getInit(); | |
| 3134 | const ZigClangStmt *init_stmt = bitcast(stmt->getInit()); | |
| 2962 | 3135 | if (init_stmt == nullptr) { |
| 2963 | 3136 | while_scope = trans_scope_while_create(c, parent_scope); |
| 2964 | 3137 | loop_block_node = while_scope->node; |
| ... | ... | @@ -2979,35 +3152,27 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang |
| 2979 | 3152 | child_scope->node->data.block.statements.append(while_scope->node); |
| 2980 | 3153 | } |
| 2981 | 3154 | |
| 2982 | const clang::Stmt *cond_stmt = stmt->getCond(); | |
| 2983 | if (cond_stmt == nullptr) { | |
| 3155 | const ZigClangExpr *cond_expr = bitcast(stmt->getCond()); | |
| 3156 | if (cond_expr == nullptr) { | |
| 2984 | 3157 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); |
| 2985 | 3158 | } else { |
| 2986 | if (clang::Expr::classof(cond_stmt)) { | |
| 2987 | const clang::Expr *cond_expr = static_cast<const clang::Expr*>(cond_stmt); | |
| 2988 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue); | |
| 3159 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, | |
| 3160 | cond_expr, TransRValue); | |
| 2989 | 3161 | |
| 2990 | if (while_scope->node->data.while_expr.condition == nullptr) | |
| 2991 | 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 | } | |
| 3162 | if (while_scope->node->data.while_expr.condition == nullptr) | |
| 3163 | return nullptr; | |
| 2998 | 3164 | } |
| 2999 | 3165 | |
| 3000 | const clang::Stmt *inc_stmt = stmt->getInc(); | |
| 3001 | if (inc_stmt != nullptr) { | |
| 3002 | AstNode *inc_node; | |
| 3003 | TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node); | |
| 3004 | if (inc_scope == nullptr) | |
| 3166 | const ZigClangExpr *inc_expr = bitcast(stmt->getInc()); | |
| 3167 | if (inc_expr != nullptr) { | |
| 3168 | AstNode *inc_node = trans_expr(c, ResultUsedNo, cond_scope, inc_expr, TransRValue); | |
| 3169 | if (inc_node == nullptr) | |
| 3005 | 3170 | return nullptr; |
| 3006 | 3171 | while_scope->node->data.while_expr.continue_expr = inc_node; |
| 3007 | 3172 | } |
| 3008 | 3173 | |
| 3009 | 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 | 3176 | if (body_scope == nullptr) |
| 3012 | 3177 | return nullptr; |
| 3013 | 3178 | |
| ... | ... | @@ -3030,7 +3195,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl |
| 3030 | 3195 | switch_scope = trans_scope_switch_create(c, &block_scope->base); |
| 3031 | 3196 | } else { |
| 3032 | 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 | 3199 | if (var_scope == nullptr) |
| 3035 | 3200 | return nullptr; |
| 3036 | 3201 | if (vars_node != nullptr) |
| ... | ... | @@ -3044,7 +3209,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const cl |
| 3044 | 3209 | switch_scope->end_label_name = end_label_name; |
| 3045 | 3210 | block_scope->node->data.block.name = end_label_name; |
| 3046 | 3211 | |
| 3047 | const clang::Expr *cond_expr = stmt->getCond(); | |
| 3212 | const ZigClangExpr *cond_expr = bitcast(stmt->getCond()); | |
| 3048 | 3213 | assert(cond_expr != nullptr); |
| 3049 | 3214 | |
| 3050 | 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 | 3218 | switch_scope->switch_node->data.switch_expr.expr = expr_node; |
| 3054 | 3219 | |
| 3055 | 3220 | AstNode *body_node; |
| 3056 | const clang::Stmt *body_stmt = stmt->getBody(); | |
| 3057 | if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) { | |
| 3058 | if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt, | |
| 3221 | const ZigClangStmt *body_stmt = bitcast(stmt->getBody()); | |
| 3222 | if (ZigClangStmt_getStmtClass(body_stmt) == ZigClangStmt_CompoundStmtClass) { | |
| 3223 | if (trans_compound_stmt_inline(c, &switch_scope->base, (const ZigClangCompoundStmt *)body_stmt, | |
| 3059 | 3224 | block_scope->node, nullptr)) |
| 3060 | 3225 | { |
| 3061 | 3226 | return nullptr; |
| ... | ... | @@ -3092,7 +3257,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang:: |
| 3092 | 3257 | *out_node = nullptr; |
| 3093 | 3258 | |
| 3094 | 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 | 3261 | return ErrorUnexpected; |
| 3097 | 3262 | } |
| 3098 | 3263 | |
| ... | ... | @@ -3105,7 +3270,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const clang:: |
| 3105 | 3270 | { |
| 3106 | 3271 | // Add the prong |
| 3107 | 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 | 3274 | if (item_node == nullptr) |
| 3110 | 3275 | return ErrorUnexpected; |
| 3111 | 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 | 3287 | scope_block->node->data.block.statements.append(case_block); |
| 3123 | 3288 | |
| 3124 | 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 | 3291 | if (new_scope == nullptr) |
| 3127 | 3292 | return ErrorUnexpected; |
| 3128 | 3293 | if (sub_stmt_node != nullptr) |
| ... | ... | @@ -3159,7 +3324,7 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const clan |
| 3159 | 3324 | scope_block->node->data.block.statements.append(case_block); |
| 3160 | 3325 | |
| 3161 | 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 | 3328 | if (new_scope == nullptr) |
| 3164 | 3329 | return ErrorUnexpected; |
| 3165 | 3330 | if (sub_stmt_node != nullptr) |
| ... | ... | @@ -3177,13 +3342,13 @@ static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransSc |
| 3177 | 3342 | return maybe_suppress_result(c, result_used, node); |
| 3178 | 3343 | } |
| 3179 | 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 | 3346 | return nullptr; |
| 3182 | 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 | 3349 | return nullptr; |
| 3185 | 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 | 3352 | return nullptr; |
| 3188 | 3353 | } |
| 3189 | 3354 | zig_unreachable(); |
| ... | ... | @@ -3222,45 +3387,45 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_ |
| 3222 | 3387 | return ErrorNone; |
| 3223 | 3388 | } |
| 3224 | 3389 | |
| 3225 | static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt, | |
| 3390 | static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *stmt, | |
| 3226 | 3391 | ResultUsed result_used, TransLRValue lrvalue, |
| 3227 | 3392 | AstNode **out_node, TransScope **out_child_scope, |
| 3228 | 3393 | TransScope **out_node_scope) |
| 3229 | 3394 | { |
| 3230 | clang::Stmt::StmtClass sc = stmt->getStmtClass(); | |
| 3395 | ZigClangStmtClass sc = ZigClangStmt_getStmtClass(stmt); | |
| 3231 | 3396 | switch (sc) { |
| 3232 | case clang::Stmt::ReturnStmtClass: | |
| 3397 | case ZigClangStmt_ReturnStmtClass: | |
| 3233 | 3398 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3234 | 3399 | trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt)); |
| 3235 | case clang::Stmt::CompoundStmtClass: | |
| 3400 | case ZigClangStmt_CompoundStmtClass: | |
| 3236 | 3401 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3237 | trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope)); | |
| 3238 | case clang::Stmt::IntegerLiteralClass: | |
| 3402 | trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt, out_node_scope)); | |
| 3403 | case ZigClangStmt_IntegerLiteralClass: | |
| 3239 | 3404 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3240 | 3405 | trans_integer_literal(c, result_used, (const clang::IntegerLiteral *)stmt)); |
| 3241 | case clang::Stmt::ConditionalOperatorClass: | |
| 3406 | case ZigClangStmt_ConditionalOperatorClass: | |
| 3242 | 3407 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3243 | 3408 | trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt)); |
| 3244 | case clang::Stmt::BinaryOperatorClass: | |
| 3409 | case ZigClangStmt_BinaryOperatorClass: | |
| 3245 | 3410 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3246 | 3411 | trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt)); |
| 3247 | case clang::Stmt::CompoundAssignOperatorClass: | |
| 3412 | case ZigClangStmt_CompoundAssignOperatorClass: | |
| 3248 | 3413 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3249 | 3414 | trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt)); |
| 3250 | case clang::Stmt::ImplicitCastExprClass: | |
| 3415 | case ZigClangStmt_ImplicitCastExprClass: | |
| 3251 | 3416 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3252 | 3417 | trans_implicit_cast_expr(c, result_used, scope, (const clang::ImplicitCastExpr *)stmt)); |
| 3253 | case clang::Stmt::DeclRefExprClass: | |
| 3418 | case ZigClangStmt_DeclRefExprClass: | |
| 3254 | 3419 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3255 | 3420 | trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue)); |
| 3256 | case clang::Stmt::UnaryOperatorClass: | |
| 3421 | case ZigClangStmt_UnaryOperatorClass: | |
| 3257 | 3422 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3258 | 3423 | trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt)); |
| 3259 | case clang::Stmt::DeclStmtClass: | |
| 3424 | case ZigClangStmt_DeclStmtClass: | |
| 3260 | 3425 | return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope); |
| 3261 | case clang::Stmt::DoStmtClass: | |
| 3262 | case clang::Stmt::WhileStmtClass: { | |
| 3263 | AstNode *while_node = sc == clang::Stmt::DoStmtClass | |
| 3426 | case ZigClangStmt_DoStmtClass: | |
| 3427 | case ZigClangStmt_WhileStmtClass: { | |
| 3428 | AstNode *while_node = sc == ZigClangStmt_DoStmtClass | |
| 3264 | 3429 | ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt) |
| 3265 | 3430 | : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt); |
| 3266 | 3431 | |
| ... | ... | @@ -3273,572 +3438,574 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st |
| 3273 | 3438 | |
| 3274 | 3439 | return wrap_stmt(out_node, out_child_scope, scope, while_node); |
| 3275 | 3440 | } |
| 3276 | case clang::Stmt::IfStmtClass: | |
| 3441 | case ZigClangStmt_IfStmtClass: | |
| 3277 | 3442 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3278 | 3443 | trans_if_statement(c, scope, (const clang::IfStmt *)stmt)); |
| 3279 | case clang::Stmt::CallExprClass: | |
| 3444 | case ZigClangStmt_CallExprClass: | |
| 3280 | 3445 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3281 | 3446 | trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt)); |
| 3282 | case clang::Stmt::NullStmtClass: | |
| 3447 | case ZigClangStmt_NullStmtClass: | |
| 3283 | 3448 | *out_node = trans_create_node(c, NodeTypeBlock); |
| 3284 | 3449 | *out_child_scope = scope; |
| 3285 | 3450 | return ErrorNone; |
| 3286 | case clang::Stmt::MemberExprClass: | |
| 3451 | case ZigClangStmt_MemberExprClass: | |
| 3287 | 3452 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3288 | 3453 | trans_member_expr(c, result_used, scope, (const clang::MemberExpr *)stmt)); |
| 3289 | case clang::Stmt::ArraySubscriptExprClass: | |
| 3454 | case ZigClangStmt_ArraySubscriptExprClass: | |
| 3290 | 3455 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3291 | 3456 | trans_array_subscript_expr(c, result_used, scope, (const clang::ArraySubscriptExpr *)stmt)); |
| 3292 | case clang::Stmt::CStyleCastExprClass: | |
| 3457 | case ZigClangStmt_CStyleCastExprClass: | |
| 3293 | 3458 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3294 | 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 | 3461 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3297 | 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 | 3464 | AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt); |
| 3300 | 3465 | return wrap_stmt(out_node, out_child_scope, scope, node); |
| 3301 | 3466 | } |
| 3302 | case clang::Stmt::StringLiteralClass: | |
| 3467 | case ZigClangStmt_StringLiteralClass: | |
| 3303 | 3468 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3304 | 3469 | trans_string_literal(c, result_used, scope, (const clang::StringLiteral *)stmt)); |
| 3305 | case clang::Stmt::BreakStmtClass: | |
| 3470 | case ZigClangStmt_BreakStmtClass: | |
| 3306 | 3471 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3307 | 3472 | trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt)); |
| 3308 | case clang::Stmt::ContinueStmtClass: | |
| 3473 | case ZigClangStmt_ContinueStmtClass: | |
| 3309 | 3474 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3310 | 3475 | trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt)); |
| 3311 | case clang::Stmt::ParenExprClass: | |
| 3476 | case ZigClangStmt_ParenExprClass: | |
| 3312 | 3477 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3313 | trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue)); | |
| 3314 | case clang::Stmt::SwitchStmtClass: | |
| 3478 | trans_expr(c, result_used, scope, | |
| 3479 | bitcast(((const clang::ParenExpr*)stmt)->getSubExpr()), lrvalue)); | |
| 3480 | case ZigClangStmt_SwitchStmtClass: | |
| 3315 | 3481 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3316 | 3482 | trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt)); |
| 3317 | case clang::Stmt::CaseStmtClass: | |
| 3483 | case ZigClangStmt_CaseStmtClass: | |
| 3318 | 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 | 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 | 3488 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3323 | 3489 | trans_constant_expr(c, result_used, (const clang::ConstantExpr *)stmt)); |
| 3324 | case clang::Stmt::PredefinedExprClass: | |
| 3490 | case ZigClangStmt_PredefinedExprClass: | |
| 3325 | 3491 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3326 | 3492 | trans_predefined_expr(c, result_used, scope, (const clang::PredefinedExpr *)stmt)); |
| 3327 | case clang::Stmt::StmtExprClass: | |
| 3493 | case ZigClangStmt_StmtExprClass: | |
| 3328 | 3494 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3329 | 3495 | trans_stmt_expr(c, result_used, scope, (const clang::StmtExpr *)stmt, out_node_scope)); |
| 3330 | case clang::Stmt::NoStmtClass: | |
| 3331 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoStmtClass"); | |
| 3332 | return ErrorUnexpected; | |
| 3333 | case clang::Stmt::GCCAsmStmtClass: | |
| 3334 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C GCCAsmStmtClass"); | |
| 3496 | case ZigClangStmt_NoStmtClass: | |
| 3497 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C NoStmtClass"); | |
| 3335 | 3498 | return ErrorUnexpected; |
| 3336 | case clang::Stmt::MSAsmStmtClass: | |
| 3337 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSAsmStmtClass"); | |
| 3499 | case ZigClangStmt_GCCAsmStmtClass: | |
| 3500 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GCCAsmStmtClass"); | |
| 3338 | 3501 | return ErrorUnexpected; |
| 3339 | case clang::Stmt::AttributedStmtClass: | |
| 3340 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C AttributedStmtClass"); | |
| 3502 | case ZigClangStmt_MSAsmStmtClass: | |
| 3503 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSAsmStmtClass"); | |
| 3341 | 3504 | return ErrorUnexpected; |
| 3342 | case clang::Stmt::CXXCatchStmtClass: | |
| 3343 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXCatchStmtClass"); | |
| 3505 | case ZigClangStmt_AttributedStmtClass: | |
| 3506 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AttributedStmtClass"); | |
| 3344 | 3507 | return ErrorUnexpected; |
| 3345 | case clang::Stmt::CXXForRangeStmtClass: | |
| 3346 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXForRangeStmtClass"); | |
| 3508 | case ZigClangStmt_CXXCatchStmtClass: | |
| 3509 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXCatchStmtClass"); | |
| 3347 | 3510 | return ErrorUnexpected; |
| 3348 | case clang::Stmt::CXXTryStmtClass: | |
| 3349 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTryStmtClass"); | |
| 3511 | case ZigClangStmt_CXXForRangeStmtClass: | |
| 3512 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXForRangeStmtClass"); | |
| 3350 | 3513 | return ErrorUnexpected; |
| 3351 | case clang::Stmt::CapturedStmtClass: | |
| 3352 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CapturedStmtClass"); | |
| 3514 | case ZigClangStmt_CXXTryStmtClass: | |
| 3515 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTryStmtClass"); | |
| 3353 | 3516 | return ErrorUnexpected; |
| 3354 | case clang::Stmt::CoreturnStmtClass: | |
| 3355 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoreturnStmtClass"); | |
| 3517 | case ZigClangStmt_CapturedStmtClass: | |
| 3518 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CapturedStmtClass"); | |
| 3356 | 3519 | return ErrorUnexpected; |
| 3357 | case clang::Stmt::CoroutineBodyStmtClass: | |
| 3358 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoroutineBodyStmtClass"); | |
| 3520 | case ZigClangStmt_CoreturnStmtClass: | |
| 3521 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoreturnStmtClass"); | |
| 3359 | 3522 | return ErrorUnexpected; |
| 3360 | case clang::Stmt::BinaryConditionalOperatorClass: | |
| 3361 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C BinaryConditionalOperatorClass"); | |
| 3523 | case ZigClangStmt_CoroutineBodyStmtClass: | |
| 3524 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoroutineBodyStmtClass"); | |
| 3362 | 3525 | return ErrorUnexpected; |
| 3363 | case clang::Stmt::AddrLabelExprClass: | |
| 3364 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C AddrLabelExprClass"); | |
| 3526 | case ZigClangStmt_BinaryConditionalOperatorClass: | |
| 3527 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C BinaryConditionalOperatorClass"); | |
| 3365 | 3528 | return ErrorUnexpected; |
| 3366 | case clang::Stmt::ArrayInitIndexExprClass: | |
| 3367 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitIndexExprClass"); | |
| 3529 | case ZigClangStmt_AddrLabelExprClass: | |
| 3530 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AddrLabelExprClass"); | |
| 3368 | 3531 | return ErrorUnexpected; |
| 3369 | case clang::Stmt::ArrayInitLoopExprClass: | |
| 3370 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitLoopExprClass"); | |
| 3532 | case ZigClangStmt_ArrayInitIndexExprClass: | |
| 3533 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayInitIndexExprClass"); | |
| 3371 | 3534 | return ErrorUnexpected; |
| 3372 | case clang::Stmt::ArrayTypeTraitExprClass: | |
| 3373 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayTypeTraitExprClass"); | |
| 3535 | case ZigClangStmt_ArrayInitLoopExprClass: | |
| 3536 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayInitLoopExprClass"); | |
| 3374 | 3537 | return ErrorUnexpected; |
| 3375 | case clang::Stmt::AsTypeExprClass: | |
| 3376 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C AsTypeExprClass"); | |
| 3538 | case ZigClangStmt_ArrayTypeTraitExprClass: | |
| 3539 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayTypeTraitExprClass"); | |
| 3377 | 3540 | return ErrorUnexpected; |
| 3378 | case clang::Stmt::AtomicExprClass: | |
| 3379 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C AtomicExprClass"); | |
| 3541 | case ZigClangStmt_AsTypeExprClass: | |
| 3542 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AsTypeExprClass"); | |
| 3380 | 3543 | return ErrorUnexpected; |
| 3381 | case clang::Stmt::BlockExprClass: | |
| 3382 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C BlockExprClass"); | |
| 3544 | case ZigClangStmt_AtomicExprClass: | |
| 3545 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AtomicExprClass"); | |
| 3383 | 3546 | return ErrorUnexpected; |
| 3384 | case clang::Stmt::CXXBindTemporaryExprClass: | |
| 3385 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBindTemporaryExprClass"); | |
| 3547 | case ZigClangStmt_BlockExprClass: | |
| 3548 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C BlockExprClass"); | |
| 3386 | 3549 | return ErrorUnexpected; |
| 3387 | case clang::Stmt::CXXBoolLiteralExprClass: | |
| 3388 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBoolLiteralExprClass"); | |
| 3550 | case ZigClangStmt_CXXBindTemporaryExprClass: | |
| 3551 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXBindTemporaryExprClass"); | |
| 3389 | 3552 | return ErrorUnexpected; |
| 3390 | case clang::Stmt::CXXConstructExprClass: | |
| 3391 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstructExprClass"); | |
| 3553 | case ZigClangStmt_CXXBoolLiteralExprClass: | |
| 3554 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXBoolLiteralExprClass"); | |
| 3392 | 3555 | return ErrorUnexpected; |
| 3393 | case clang::Stmt::CXXTemporaryObjectExprClass: | |
| 3394 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTemporaryObjectExprClass"); | |
| 3556 | case ZigClangStmt_CXXConstructExprClass: | |
| 3557 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXConstructExprClass"); | |
| 3395 | 3558 | return ErrorUnexpected; |
| 3396 | case clang::Stmt::CXXDefaultArgExprClass: | |
| 3397 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultArgExprClass"); | |
| 3559 | case ZigClangStmt_CXXTemporaryObjectExprClass: | |
| 3560 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTemporaryObjectExprClass"); | |
| 3398 | 3561 | return ErrorUnexpected; |
| 3399 | case clang::Stmt::CXXDefaultInitExprClass: | |
| 3400 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultInitExprClass"); | |
| 3562 | case ZigClangStmt_CXXDefaultArgExprClass: | |
| 3563 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDefaultArgExprClass"); | |
| 3401 | 3564 | return ErrorUnexpected; |
| 3402 | case clang::Stmt::CXXDeleteExprClass: | |
| 3403 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDeleteExprClass"); | |
| 3565 | case ZigClangStmt_CXXDefaultInitExprClass: | |
| 3566 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDefaultInitExprClass"); | |
| 3404 | 3567 | return ErrorUnexpected; |
| 3405 | case clang::Stmt::CXXDependentScopeMemberExprClass: | |
| 3406 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDependentScopeMemberExprClass"); | |
| 3568 | case ZigClangStmt_CXXDeleteExprClass: | |
| 3569 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDeleteExprClass"); | |
| 3407 | 3570 | return ErrorUnexpected; |
| 3408 | case clang::Stmt::CXXFoldExprClass: | |
| 3409 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFoldExprClass"); | |
| 3571 | case ZigClangStmt_CXXDependentScopeMemberExprClass: | |
| 3572 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDependentScopeMemberExprClass"); | |
| 3410 | 3573 | return ErrorUnexpected; |
| 3411 | case clang::Stmt::CXXInheritedCtorInitExprClass: | |
| 3412 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXInheritedCtorInitExprClass"); | |
| 3574 | case ZigClangStmt_CXXFoldExprClass: | |
| 3575 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXFoldExprClass"); | |
| 3413 | 3576 | return ErrorUnexpected; |
| 3414 | case clang::Stmt::CXXNewExprClass: | |
| 3415 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNewExprClass"); | |
| 3577 | case ZigClangStmt_CXXInheritedCtorInitExprClass: | |
| 3578 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXInheritedCtorInitExprClass"); | |
| 3416 | 3579 | return ErrorUnexpected; |
| 3417 | case clang::Stmt::CXXNoexceptExprClass: | |
| 3418 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNoexceptExprClass"); | |
| 3580 | case ZigClangStmt_CXXNewExprClass: | |
| 3581 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNewExprClass"); | |
| 3419 | 3582 | return ErrorUnexpected; |
| 3420 | case clang::Stmt::CXXNullPtrLiteralExprClass: | |
| 3421 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNullPtrLiteralExprClass"); | |
| 3583 | case ZigClangStmt_CXXNoexceptExprClass: | |
| 3584 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNoexceptExprClass"); | |
| 3422 | 3585 | return ErrorUnexpected; |
| 3423 | case clang::Stmt::CXXPseudoDestructorExprClass: | |
| 3424 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXPseudoDestructorExprClass"); | |
| 3586 | case ZigClangStmt_CXXNullPtrLiteralExprClass: | |
| 3587 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNullPtrLiteralExprClass"); | |
| 3425 | 3588 | return ErrorUnexpected; |
| 3426 | case clang::Stmt::CXXScalarValueInitExprClass: | |
| 3427 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXScalarValueInitExprClass"); | |
| 3589 | case ZigClangStmt_CXXPseudoDestructorExprClass: | |
| 3590 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXPseudoDestructorExprClass"); | |
| 3428 | 3591 | return ErrorUnexpected; |
| 3429 | case clang::Stmt::CXXStdInitializerListExprClass: | |
| 3430 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStdInitializerListExprClass"); | |
| 3592 | case ZigClangStmt_CXXScalarValueInitExprClass: | |
| 3593 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXScalarValueInitExprClass"); | |
| 3431 | 3594 | return ErrorUnexpected; |
| 3432 | case clang::Stmt::CXXThisExprClass: | |
| 3433 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThisExprClass"); | |
| 3595 | case ZigClangStmt_CXXStdInitializerListExprClass: | |
| 3596 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXStdInitializerListExprClass"); | |
| 3434 | 3597 | return ErrorUnexpected; |
| 3435 | case clang::Stmt::CXXThrowExprClass: | |
| 3436 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThrowExprClass"); | |
| 3598 | case ZigClangStmt_CXXThisExprClass: | |
| 3599 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXThisExprClass"); | |
| 3437 | 3600 | return ErrorUnexpected; |
| 3438 | case clang::Stmt::CXXTypeidExprClass: | |
| 3439 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTypeidExprClass"); | |
| 3601 | case ZigClangStmt_CXXThrowExprClass: | |
| 3602 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXThrowExprClass"); | |
| 3440 | 3603 | return ErrorUnexpected; |
| 3441 | case clang::Stmt::CXXUnresolvedConstructExprClass: | |
| 3442 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUnresolvedConstructExprClass"); | |
| 3604 | case ZigClangStmt_CXXTypeidExprClass: | |
| 3605 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTypeidExprClass"); | |
| 3443 | 3606 | return ErrorUnexpected; |
| 3444 | case clang::Stmt::CXXUuidofExprClass: | |
| 3445 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUuidofExprClass"); | |
| 3607 | case ZigClangStmt_CXXUnresolvedConstructExprClass: | |
| 3608 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXUnresolvedConstructExprClass"); | |
| 3446 | 3609 | return ErrorUnexpected; |
| 3447 | case clang::Stmt::CUDAKernelCallExprClass: | |
| 3448 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CUDAKernelCallExprClass"); | |
| 3610 | case ZigClangStmt_CXXUuidofExprClass: | |
| 3611 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXUuidofExprClass"); | |
| 3449 | 3612 | return ErrorUnexpected; |
| 3450 | case clang::Stmt::CXXMemberCallExprClass: | |
| 3451 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXMemberCallExprClass"); | |
| 3613 | case ZigClangStmt_CUDAKernelCallExprClass: | |
| 3614 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CUDAKernelCallExprClass"); | |
| 3452 | 3615 | return ErrorUnexpected; |
| 3453 | case clang::Stmt::CXXOperatorCallExprClass: | |
| 3454 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXOperatorCallExprClass"); | |
| 3616 | case ZigClangStmt_CXXMemberCallExprClass: | |
| 3617 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXMemberCallExprClass"); | |
| 3455 | 3618 | return ErrorUnexpected; |
| 3456 | case clang::Stmt::UserDefinedLiteralClass: | |
| 3457 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C UserDefinedLiteralClass"); | |
| 3619 | case ZigClangStmt_CXXOperatorCallExprClass: | |
| 3620 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXOperatorCallExprClass"); | |
| 3458 | 3621 | return ErrorUnexpected; |
| 3459 | case clang::Stmt::CXXFunctionalCastExprClass: | |
| 3460 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFunctionalCastExprClass"); | |
| 3622 | case ZigClangStmt_UserDefinedLiteralClass: | |
| 3623 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UserDefinedLiteralClass"); | |
| 3461 | 3624 | return ErrorUnexpected; |
| 3462 | case clang::Stmt::CXXConstCastExprClass: | |
| 3463 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstCastExprClass"); | |
| 3625 | case ZigClangStmt_CXXFunctionalCastExprClass: | |
| 3626 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXFunctionalCastExprClass"); | |
| 3464 | 3627 | return ErrorUnexpected; |
| 3465 | case clang::Stmt::CXXDynamicCastExprClass: | |
| 3466 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDynamicCastExprClass"); | |
| 3628 | case ZigClangStmt_CXXConstCastExprClass: | |
| 3629 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXConstCastExprClass"); | |
| 3467 | 3630 | return ErrorUnexpected; |
| 3468 | case clang::Stmt::CXXReinterpretCastExprClass: | |
| 3469 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXReinterpretCastExprClass"); | |
| 3631 | case ZigClangStmt_CXXDynamicCastExprClass: | |
| 3632 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDynamicCastExprClass"); | |
| 3470 | 3633 | return ErrorUnexpected; |
| 3471 | case clang::Stmt::CXXStaticCastExprClass: | |
| 3472 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStaticCastExprClass"); | |
| 3634 | case ZigClangStmt_CXXReinterpretCastExprClass: | |
| 3635 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXReinterpretCastExprClass"); | |
| 3473 | 3636 | return ErrorUnexpected; |
| 3474 | case clang::Stmt::ObjCBridgedCastExprClass: | |
| 3475 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBridgedCastExprClass"); | |
| 3637 | case ZigClangStmt_CXXStaticCastExprClass: | |
| 3638 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXStaticCastExprClass"); | |
| 3476 | 3639 | return ErrorUnexpected; |
| 3477 | case clang::Stmt::CharacterLiteralClass: | |
| 3478 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CharacterLiteralClass"); | |
| 3640 | case ZigClangStmt_ObjCBridgedCastExprClass: | |
| 3641 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass"); | |
| 3479 | 3642 | return ErrorUnexpected; |
| 3480 | case clang::Stmt::ChooseExprClass: | |
| 3481 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ChooseExprClass"); | |
| 3643 | case ZigClangStmt_CharacterLiteralClass: | |
| 3644 | return wrap_stmt(out_node, out_child_scope, scope, | |
| 3645 | trans_character_literal(c, result_used, (const clang::CharacterLiteral *)stmt)); | |
| 3482 | 3646 | return ErrorUnexpected; |
| 3483 | case clang::Stmt::CompoundLiteralExprClass: | |
| 3484 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CompoundLiteralExprClass"); | |
| 3647 | case ZigClangStmt_ChooseExprClass: | |
| 3648 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ChooseExprClass"); | |
| 3485 | 3649 | return ErrorUnexpected; |
| 3486 | case clang::Stmt::ConvertVectorExprClass: | |
| 3487 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ConvertVectorExprClass"); | |
| 3650 | case ZigClangStmt_CompoundLiteralExprClass: | |
| 3651 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CompoundLiteralExprClass"); | |
| 3488 | 3652 | return ErrorUnexpected; |
| 3489 | case clang::Stmt::CoawaitExprClass: | |
| 3490 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoawaitExprClass"); | |
| 3653 | case ZigClangStmt_ConvertVectorExprClass: | |
| 3654 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ConvertVectorExprClass"); | |
| 3491 | 3655 | return ErrorUnexpected; |
| 3492 | case clang::Stmt::CoyieldExprClass: | |
| 3493 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoyieldExprClass"); | |
| 3656 | case ZigClangStmt_CoawaitExprClass: | |
| 3657 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoawaitExprClass"); | |
| 3494 | 3658 | return ErrorUnexpected; |
| 3495 | case clang::Stmt::DependentCoawaitExprClass: | |
| 3496 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentCoawaitExprClass"); | |
| 3659 | case ZigClangStmt_CoyieldExprClass: | |
| 3660 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoyieldExprClass"); | |
| 3497 | 3661 | return ErrorUnexpected; |
| 3498 | case clang::Stmt::DependentScopeDeclRefExprClass: | |
| 3499 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentScopeDeclRefExprClass"); | |
| 3662 | case ZigClangStmt_DependentCoawaitExprClass: | |
| 3663 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DependentCoawaitExprClass"); | |
| 3500 | 3664 | return ErrorUnexpected; |
| 3501 | case clang::Stmt::DesignatedInitExprClass: | |
| 3502 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitExprClass"); | |
| 3665 | case ZigClangStmt_DependentScopeDeclRefExprClass: | |
| 3666 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DependentScopeDeclRefExprClass"); | |
| 3503 | 3667 | return ErrorUnexpected; |
| 3504 | case clang::Stmt::DesignatedInitUpdateExprClass: | |
| 3505 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitUpdateExprClass"); | |
| 3668 | case ZigClangStmt_DesignatedInitExprClass: | |
| 3669 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DesignatedInitExprClass"); | |
| 3506 | 3670 | return ErrorUnexpected; |
| 3507 | case clang::Stmt::ExpressionTraitExprClass: | |
| 3508 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExpressionTraitExprClass"); | |
| 3671 | case ZigClangStmt_DesignatedInitUpdateExprClass: | |
| 3672 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DesignatedInitUpdateExprClass"); | |
| 3509 | 3673 | return ErrorUnexpected; |
| 3510 | case clang::Stmt::ExtVectorElementExprClass: | |
| 3511 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExtVectorElementExprClass"); | |
| 3674 | case ZigClangStmt_ExpressionTraitExprClass: | |
| 3675 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExpressionTraitExprClass"); | |
| 3512 | 3676 | return ErrorUnexpected; |
| 3513 | case clang::Stmt::FixedPointLiteralClass: | |
| 3514 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C FixedPointLiteralClass"); | |
| 3677 | case ZigClangStmt_ExtVectorElementExprClass: | |
| 3678 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExtVectorElementExprClass"); | |
| 3515 | 3679 | return ErrorUnexpected; |
| 3516 | case clang::Stmt::FloatingLiteralClass: | |
| 3517 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C FloatingLiteralClass"); | |
| 3680 | case ZigClangStmt_FixedPointLiteralClass: | |
| 3681 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass"); | |
| 3518 | 3682 | return ErrorUnexpected; |
| 3519 | case clang::Stmt::ExprWithCleanupsClass: | |
| 3520 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExprWithCleanupsClass"); | |
| 3683 | case ZigClangStmt_FloatingLiteralClass: | |
| 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 | 3688 | return ErrorUnexpected; |
| 3522 | case clang::Stmt::FunctionParmPackExprClass: | |
| 3523 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C FunctionParmPackExprClass"); | |
| 3689 | case ZigClangStmt_FunctionParmPackExprClass: | |
| 3690 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FunctionParmPackExprClass"); | |
| 3524 | 3691 | return ErrorUnexpected; |
| 3525 | case clang::Stmt::GNUNullExprClass: | |
| 3526 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C GNUNullExprClass"); | |
| 3692 | case ZigClangStmt_GNUNullExprClass: | |
| 3693 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GNUNullExprClass"); | |
| 3527 | 3694 | return ErrorUnexpected; |
| 3528 | case clang::Stmt::GenericSelectionExprClass: | |
| 3529 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C GenericSelectionExprClass"); | |
| 3695 | case ZigClangStmt_GenericSelectionExprClass: | |
| 3696 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GenericSelectionExprClass"); | |
| 3530 | 3697 | return ErrorUnexpected; |
| 3531 | case clang::Stmt::ImaginaryLiteralClass: | |
| 3532 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImaginaryLiteralClass"); | |
| 3698 | case ZigClangStmt_ImaginaryLiteralClass: | |
| 3699 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ImaginaryLiteralClass"); | |
| 3533 | 3700 | return ErrorUnexpected; |
| 3534 | case clang::Stmt::ImplicitValueInitExprClass: | |
| 3535 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImplicitValueInitExprClass"); | |
| 3701 | case ZigClangStmt_ImplicitValueInitExprClass: | |
| 3702 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ImplicitValueInitExprClass"); | |
| 3536 | 3703 | return ErrorUnexpected; |
| 3537 | case clang::Stmt::InitListExprClass: | |
| 3538 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C InitListExprClass"); | |
| 3704 | case ZigClangStmt_InitListExprClass: | |
| 3705 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C InitListExprClass"); | |
| 3539 | 3706 | return ErrorUnexpected; |
| 3540 | case clang::Stmt::LambdaExprClass: | |
| 3541 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C LambdaExprClass"); | |
| 3707 | case ZigClangStmt_LambdaExprClass: | |
| 3708 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C LambdaExprClass"); | |
| 3542 | 3709 | return ErrorUnexpected; |
| 3543 | case clang::Stmt::MSPropertyRefExprClass: | |
| 3544 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertyRefExprClass"); | |
| 3710 | case ZigClangStmt_MSPropertyRefExprClass: | |
| 3711 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSPropertyRefExprClass"); | |
| 3545 | 3712 | return ErrorUnexpected; |
| 3546 | case clang::Stmt::MSPropertySubscriptExprClass: | |
| 3547 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertySubscriptExprClass"); | |
| 3713 | case ZigClangStmt_MSPropertySubscriptExprClass: | |
| 3714 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSPropertySubscriptExprClass"); | |
| 3548 | 3715 | return ErrorUnexpected; |
| 3549 | case clang::Stmt::MaterializeTemporaryExprClass: | |
| 3550 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MaterializeTemporaryExprClass"); | |
| 3716 | case ZigClangStmt_MaterializeTemporaryExprClass: | |
| 3717 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MaterializeTemporaryExprClass"); | |
| 3551 | 3718 | return ErrorUnexpected; |
| 3552 | case clang::Stmt::NoInitExprClass: | |
| 3553 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoInitExprClass"); | |
| 3719 | case ZigClangStmt_NoInitExprClass: | |
| 3720 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C NoInitExprClass"); | |
| 3554 | 3721 | return ErrorUnexpected; |
| 3555 | case clang::Stmt::OMPArraySectionExprClass: | |
| 3556 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPArraySectionExprClass"); | |
| 3722 | case ZigClangStmt_OMPArraySectionExprClass: | |
| 3723 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPArraySectionExprClass"); | |
| 3557 | 3724 | return ErrorUnexpected; |
| 3558 | case clang::Stmt::ObjCArrayLiteralClass: | |
| 3559 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCArrayLiteralClass"); | |
| 3725 | case ZigClangStmt_ObjCArrayLiteralClass: | |
| 3726 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCArrayLiteralClass"); | |
| 3560 | 3727 | return ErrorUnexpected; |
| 3561 | case clang::Stmt::ObjCAvailabilityCheckExprClass: | |
| 3562 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAvailabilityCheckExprClass"); | |
| 3728 | case ZigClangStmt_ObjCAvailabilityCheckExprClass: | |
| 3729 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAvailabilityCheckExprClass"); | |
| 3563 | 3730 | return ErrorUnexpected; |
| 3564 | case clang::Stmt::ObjCBoolLiteralExprClass: | |
| 3565 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoolLiteralExprClass"); | |
| 3731 | case ZigClangStmt_ObjCBoolLiteralExprClass: | |
| 3732 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBoolLiteralExprClass"); | |
| 3566 | 3733 | return ErrorUnexpected; |
| 3567 | case clang::Stmt::ObjCBoxedExprClass: | |
| 3568 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoxedExprClass"); | |
| 3734 | case ZigClangStmt_ObjCBoxedExprClass: | |
| 3735 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBoxedExprClass"); | |
| 3569 | 3736 | return ErrorUnexpected; |
| 3570 | case clang::Stmt::ObjCDictionaryLiteralClass: | |
| 3571 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCDictionaryLiteralClass"); | |
| 3737 | case ZigClangStmt_ObjCDictionaryLiteralClass: | |
| 3738 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCDictionaryLiteralClass"); | |
| 3572 | 3739 | return ErrorUnexpected; |
| 3573 | case clang::Stmt::ObjCEncodeExprClass: | |
| 3574 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCEncodeExprClass"); | |
| 3740 | case ZigClangStmt_ObjCEncodeExprClass: | |
| 3741 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCEncodeExprClass"); | |
| 3575 | 3742 | return ErrorUnexpected; |
| 3576 | case clang::Stmt::ObjCIndirectCopyRestoreExprClass: | |
| 3577 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIndirectCopyRestoreExprClass"); | |
| 3743 | case ZigClangStmt_ObjCIndirectCopyRestoreExprClass: | |
| 3744 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIndirectCopyRestoreExprClass"); | |
| 3578 | 3745 | return ErrorUnexpected; |
| 3579 | case clang::Stmt::ObjCIsaExprClass: | |
| 3580 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIsaExprClass"); | |
| 3746 | case ZigClangStmt_ObjCIsaExprClass: | |
| 3747 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIsaExprClass"); | |
| 3581 | 3748 | return ErrorUnexpected; |
| 3582 | case clang::Stmt::ObjCIvarRefExprClass: | |
| 3583 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIvarRefExprClass"); | |
| 3749 | case ZigClangStmt_ObjCIvarRefExprClass: | |
| 3750 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIvarRefExprClass"); | |
| 3584 | 3751 | return ErrorUnexpected; |
| 3585 | case clang::Stmt::ObjCMessageExprClass: | |
| 3586 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCMessageExprClass"); | |
| 3752 | case ZigClangStmt_ObjCMessageExprClass: | |
| 3753 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCMessageExprClass"); | |
| 3587 | 3754 | return ErrorUnexpected; |
| 3588 | case clang::Stmt::ObjCPropertyRefExprClass: | |
| 3589 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCPropertyRefExprClass"); | |
| 3755 | case ZigClangStmt_ObjCPropertyRefExprClass: | |
| 3756 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCPropertyRefExprClass"); | |
| 3590 | 3757 | return ErrorUnexpected; |
| 3591 | case clang::Stmt::ObjCProtocolExprClass: | |
| 3592 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProtocolExprClass"); | |
| 3758 | case ZigClangStmt_ObjCProtocolExprClass: | |
| 3759 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCProtocolExprClass"); | |
| 3593 | 3760 | return ErrorUnexpected; |
| 3594 | case clang::Stmt::ObjCSelectorExprClass: | |
| 3595 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSelectorExprClass"); | |
| 3761 | case ZigClangStmt_ObjCSelectorExprClass: | |
| 3762 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCSelectorExprClass"); | |
| 3596 | 3763 | return ErrorUnexpected; |
| 3597 | case clang::Stmt::ObjCStringLiteralClass: | |
| 3598 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCStringLiteralClass"); | |
| 3764 | case ZigClangStmt_ObjCStringLiteralClass: | |
| 3765 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCStringLiteralClass"); | |
| 3599 | 3766 | return ErrorUnexpected; |
| 3600 | case clang::Stmt::ObjCSubscriptRefExprClass: | |
| 3601 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSubscriptRefExprClass"); | |
| 3767 | case ZigClangStmt_ObjCSubscriptRefExprClass: | |
| 3768 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCSubscriptRefExprClass"); | |
| 3602 | 3769 | return ErrorUnexpected; |
| 3603 | case clang::Stmt::OffsetOfExprClass: | |
| 3604 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OffsetOfExprClass"); | |
| 3770 | case ZigClangStmt_OffsetOfExprClass: | |
| 3771 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OffsetOfExprClass"); | |
| 3605 | 3772 | return ErrorUnexpected; |
| 3606 | case clang::Stmt::OpaqueValueExprClass: | |
| 3607 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OpaqueValueExprClass"); | |
| 3773 | case ZigClangStmt_OpaqueValueExprClass: | |
| 3774 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OpaqueValueExprClass"); | |
| 3608 | 3775 | return ErrorUnexpected; |
| 3609 | case clang::Stmt::UnresolvedLookupExprClass: | |
| 3610 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedLookupExprClass"); | |
| 3776 | case ZigClangStmt_UnresolvedLookupExprClass: | |
| 3777 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UnresolvedLookupExprClass"); | |
| 3611 | 3778 | return ErrorUnexpected; |
| 3612 | case clang::Stmt::UnresolvedMemberExprClass: | |
| 3613 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedMemberExprClass"); | |
| 3779 | case ZigClangStmt_UnresolvedMemberExprClass: | |
| 3780 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UnresolvedMemberExprClass"); | |
| 3614 | 3781 | return ErrorUnexpected; |
| 3615 | case clang::Stmt::PackExpansionExprClass: | |
| 3616 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C PackExpansionExprClass"); | |
| 3782 | case ZigClangStmt_PackExpansionExprClass: | |
| 3783 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C PackExpansionExprClass"); | |
| 3617 | 3784 | return ErrorUnexpected; |
| 3618 | case clang::Stmt::ParenListExprClass: | |
| 3619 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ParenListExprClass"); | |
| 3785 | case ZigClangStmt_ParenListExprClass: | |
| 3786 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ParenListExprClass"); | |
| 3620 | 3787 | return ErrorUnexpected; |
| 3621 | case clang::Stmt::PseudoObjectExprClass: | |
| 3622 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C PseudoObjectExprClass"); | |
| 3788 | case ZigClangStmt_PseudoObjectExprClass: | |
| 3789 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C PseudoObjectExprClass"); | |
| 3623 | 3790 | return ErrorUnexpected; |
| 3624 | case clang::Stmt::ShuffleVectorExprClass: | |
| 3625 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ShuffleVectorExprClass"); | |
| 3791 | case ZigClangStmt_ShuffleVectorExprClass: | |
| 3792 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ShuffleVectorExprClass"); | |
| 3626 | 3793 | return ErrorUnexpected; |
| 3627 | case clang::Stmt::SizeOfPackExprClass: | |
| 3628 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SizeOfPackExprClass"); | |
| 3794 | case ZigClangStmt_SizeOfPackExprClass: | |
| 3795 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SizeOfPackExprClass"); | |
| 3629 | 3796 | return ErrorUnexpected; |
| 3630 | case clang::Stmt::SubstNonTypeTemplateParmExprClass: | |
| 3631 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmExprClass"); | |
| 3797 | case ZigClangStmt_SubstNonTypeTemplateParmExprClass: | |
| 3798 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SubstNonTypeTemplateParmExprClass"); | |
| 3632 | 3799 | return ErrorUnexpected; |
| 3633 | case clang::Stmt::SubstNonTypeTemplateParmPackExprClass: | |
| 3634 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmPackExprClass"); | |
| 3800 | case ZigClangStmt_SubstNonTypeTemplateParmPackExprClass: | |
| 3801 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SubstNonTypeTemplateParmPackExprClass"); | |
| 3635 | 3802 | return ErrorUnexpected; |
| 3636 | case clang::Stmt::TypeTraitExprClass: | |
| 3637 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeTraitExprClass"); | |
| 3803 | case ZigClangStmt_TypeTraitExprClass: | |
| 3804 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C TypeTraitExprClass"); | |
| 3638 | 3805 | return ErrorUnexpected; |
| 3639 | case clang::Stmt::TypoExprClass: | |
| 3640 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypoExprClass"); | |
| 3806 | case ZigClangStmt_TypoExprClass: | |
| 3807 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C TypoExprClass"); | |
| 3641 | 3808 | return ErrorUnexpected; |
| 3642 | case clang::Stmt::VAArgExprClass: | |
| 3643 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C VAArgExprClass"); | |
| 3809 | case ZigClangStmt_VAArgExprClass: | |
| 3810 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C VAArgExprClass"); | |
| 3644 | 3811 | return ErrorUnexpected; |
| 3645 | case clang::Stmt::GotoStmtClass: | |
| 3646 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C GotoStmtClass"); | |
| 3812 | case ZigClangStmt_GotoStmtClass: | |
| 3813 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GotoStmtClass"); | |
| 3647 | 3814 | return ErrorUnexpected; |
| 3648 | case clang::Stmt::IndirectGotoStmtClass: | |
| 3649 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C IndirectGotoStmtClass"); | |
| 3815 | case ZigClangStmt_IndirectGotoStmtClass: | |
| 3816 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C IndirectGotoStmtClass"); | |
| 3650 | 3817 | return ErrorUnexpected; |
| 3651 | case clang::Stmt::LabelStmtClass: | |
| 3652 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C LabelStmtClass"); | |
| 3818 | case ZigClangStmt_LabelStmtClass: | |
| 3819 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C LabelStmtClass"); | |
| 3653 | 3820 | return ErrorUnexpected; |
| 3654 | case clang::Stmt::MSDependentExistsStmtClass: | |
| 3655 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSDependentExistsStmtClass"); | |
| 3821 | case ZigClangStmt_MSDependentExistsStmtClass: | |
| 3822 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSDependentExistsStmtClass"); | |
| 3656 | 3823 | return ErrorUnexpected; |
| 3657 | case clang::Stmt::OMPAtomicDirectiveClass: | |
| 3658 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPAtomicDirectiveClass"); | |
| 3824 | case ZigClangStmt_OMPAtomicDirectiveClass: | |
| 3825 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPAtomicDirectiveClass"); | |
| 3659 | 3826 | return ErrorUnexpected; |
| 3660 | case clang::Stmt::OMPBarrierDirectiveClass: | |
| 3661 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPBarrierDirectiveClass"); | |
| 3827 | case ZigClangStmt_OMPBarrierDirectiveClass: | |
| 3828 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPBarrierDirectiveClass"); | |
| 3662 | 3829 | return ErrorUnexpected; |
| 3663 | case clang::Stmt::OMPCancelDirectiveClass: | |
| 3664 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancelDirectiveClass"); | |
| 3830 | case ZigClangStmt_OMPCancelDirectiveClass: | |
| 3831 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCancelDirectiveClass"); | |
| 3665 | 3832 | return ErrorUnexpected; |
| 3666 | case clang::Stmt::OMPCancellationPointDirectiveClass: | |
| 3667 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancellationPointDirectiveClass"); | |
| 3833 | case ZigClangStmt_OMPCancellationPointDirectiveClass: | |
| 3834 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCancellationPointDirectiveClass"); | |
| 3668 | 3835 | return ErrorUnexpected; |
| 3669 | case clang::Stmt::OMPCriticalDirectiveClass: | |
| 3670 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCriticalDirectiveClass"); | |
| 3836 | case ZigClangStmt_OMPCriticalDirectiveClass: | |
| 3837 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCriticalDirectiveClass"); | |
| 3671 | 3838 | return ErrorUnexpected; |
| 3672 | case clang::Stmt::OMPFlushDirectiveClass: | |
| 3673 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPFlushDirectiveClass"); | |
| 3839 | case ZigClangStmt_OMPFlushDirectiveClass: | |
| 3840 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPFlushDirectiveClass"); | |
| 3674 | 3841 | return ErrorUnexpected; |
| 3675 | case clang::Stmt::OMPDistributeDirectiveClass: | |
| 3676 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeDirectiveClass"); | |
| 3842 | case ZigClangStmt_OMPDistributeDirectiveClass: | |
| 3843 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeDirectiveClass"); | |
| 3677 | 3844 | return ErrorUnexpected; |
| 3678 | case clang::Stmt::OMPDistributeParallelForDirectiveClass: | |
| 3679 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForDirectiveClass"); | |
| 3845 | case ZigClangStmt_OMPDistributeParallelForDirectiveClass: | |
| 3846 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeParallelForDirectiveClass"); | |
| 3680 | 3847 | return ErrorUnexpected; |
| 3681 | case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass: | |
| 3682 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass"); | |
| 3848 | case ZigClangStmt_OMPDistributeParallelForSimdDirectiveClass: | |
| 3849 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeParallelForSimdDirectiveClass"); | |
| 3683 | 3850 | return ErrorUnexpected; |
| 3684 | case clang::Stmt::OMPDistributeSimdDirectiveClass: | |
| 3685 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeSimdDirectiveClass"); | |
| 3851 | case ZigClangStmt_OMPDistributeSimdDirectiveClass: | |
| 3852 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeSimdDirectiveClass"); | |
| 3686 | 3853 | return ErrorUnexpected; |
| 3687 | case clang::Stmt::OMPForDirectiveClass: | |
| 3688 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForDirectiveClass"); | |
| 3854 | case ZigClangStmt_OMPForDirectiveClass: | |
| 3855 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPForDirectiveClass"); | |
| 3689 | 3856 | return ErrorUnexpected; |
| 3690 | case clang::Stmt::OMPForSimdDirectiveClass: | |
| 3691 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForSimdDirectiveClass"); | |
| 3857 | case ZigClangStmt_OMPForSimdDirectiveClass: | |
| 3858 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPForSimdDirectiveClass"); | |
| 3692 | 3859 | return ErrorUnexpected; |
| 3693 | case clang::Stmt::OMPParallelForDirectiveClass: | |
| 3694 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForDirectiveClass"); | |
| 3860 | case ZigClangStmt_OMPParallelForDirectiveClass: | |
| 3861 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelForDirectiveClass"); | |
| 3695 | 3862 | return ErrorUnexpected; |
| 3696 | case clang::Stmt::OMPParallelForSimdDirectiveClass: | |
| 3697 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForSimdDirectiveClass"); | |
| 3863 | case ZigClangStmt_OMPParallelForSimdDirectiveClass: | |
| 3864 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelForSimdDirectiveClass"); | |
| 3698 | 3865 | return ErrorUnexpected; |
| 3699 | case clang::Stmt::OMPSimdDirectiveClass: | |
| 3700 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSimdDirectiveClass"); | |
| 3866 | case ZigClangStmt_OMPSimdDirectiveClass: | |
| 3867 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSimdDirectiveClass"); | |
| 3701 | 3868 | return ErrorUnexpected; |
| 3702 | case clang::Stmt::OMPTargetParallelForSimdDirectiveClass: | |
| 3703 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForSimdDirectiveClass"); | |
| 3869 | case ZigClangStmt_OMPTargetParallelForSimdDirectiveClass: | |
| 3870 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelForSimdDirectiveClass"); | |
| 3704 | 3871 | return ErrorUnexpected; |
| 3705 | case clang::Stmt::OMPTargetSimdDirectiveClass: | |
| 3706 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetSimdDirectiveClass"); | |
| 3872 | case ZigClangStmt_OMPTargetSimdDirectiveClass: | |
| 3873 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetSimdDirectiveClass"); | |
| 3707 | 3874 | return ErrorUnexpected; |
| 3708 | case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass: | |
| 3709 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass"); | |
| 3875 | case ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass: | |
| 3876 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeDirectiveClass"); | |
| 3710 | 3877 | return ErrorUnexpected; |
| 3711 | case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: | |
| 3712 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); | |
| 3878 | case ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass: | |
| 3879 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); | |
| 3713 | 3880 | return ErrorUnexpected; |
| 3714 | case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: | |
| 3715 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); | |
| 3881 | case ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass: | |
| 3882 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); | |
| 3716 | 3883 | return ErrorUnexpected; |
| 3717 | case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: | |
| 3718 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); | |
| 3884 | case ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass: | |
| 3885 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); | |
| 3719 | 3886 | return ErrorUnexpected; |
| 3720 | case clang::Stmt::OMPTaskLoopDirectiveClass: | |
| 3721 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopDirectiveClass"); | |
| 3887 | case ZigClangStmt_OMPTaskLoopDirectiveClass: | |
| 3888 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskLoopDirectiveClass"); | |
| 3722 | 3889 | return ErrorUnexpected; |
| 3723 | case clang::Stmt::OMPTaskLoopSimdDirectiveClass: | |
| 3724 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopSimdDirectiveClass"); | |
| 3890 | case ZigClangStmt_OMPTaskLoopSimdDirectiveClass: | |
| 3891 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskLoopSimdDirectiveClass"); | |
| 3725 | 3892 | return ErrorUnexpected; |
| 3726 | case clang::Stmt::OMPTeamsDistributeDirectiveClass: | |
| 3727 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeDirectiveClass"); | |
| 3893 | case ZigClangStmt_OMPTeamsDistributeDirectiveClass: | |
| 3894 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeDirectiveClass"); | |
| 3728 | 3895 | return ErrorUnexpected; |
| 3729 | case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass: | |
| 3730 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); | |
| 3896 | case ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass: | |
| 3897 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); | |
| 3731 | 3898 | return ErrorUnexpected; |
| 3732 | case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: | |
| 3733 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); | |
| 3899 | case ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass: | |
| 3900 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); | |
| 3734 | 3901 | return ErrorUnexpected; |
| 3735 | case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass: | |
| 3736 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass"); | |
| 3902 | case ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass: | |
| 3903 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeSimdDirectiveClass"); | |
| 3737 | 3904 | return ErrorUnexpected; |
| 3738 | case clang::Stmt::OMPMasterDirectiveClass: | |
| 3739 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPMasterDirectiveClass"); | |
| 3905 | case ZigClangStmt_OMPMasterDirectiveClass: | |
| 3906 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPMasterDirectiveClass"); | |
| 3740 | 3907 | return ErrorUnexpected; |
| 3741 | case clang::Stmt::OMPOrderedDirectiveClass: | |
| 3742 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPOrderedDirectiveClass"); | |
| 3908 | case ZigClangStmt_OMPOrderedDirectiveClass: | |
| 3909 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPOrderedDirectiveClass"); | |
| 3743 | 3910 | return ErrorUnexpected; |
| 3744 | case clang::Stmt::OMPParallelDirectiveClass: | |
| 3745 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelDirectiveClass"); | |
| 3911 | case ZigClangStmt_OMPParallelDirectiveClass: | |
| 3912 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelDirectiveClass"); | |
| 3746 | 3913 | return ErrorUnexpected; |
| 3747 | case clang::Stmt::OMPParallelSectionsDirectiveClass: | |
| 3748 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelSectionsDirectiveClass"); | |
| 3914 | case ZigClangStmt_OMPParallelSectionsDirectiveClass: | |
| 3915 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelSectionsDirectiveClass"); | |
| 3749 | 3916 | return ErrorUnexpected; |
| 3750 | case clang::Stmt::OMPSectionDirectiveClass: | |
| 3751 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionDirectiveClass"); | |
| 3917 | case ZigClangStmt_OMPSectionDirectiveClass: | |
| 3918 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSectionDirectiveClass"); | |
| 3752 | 3919 | return ErrorUnexpected; |
| 3753 | case clang::Stmt::OMPSectionsDirectiveClass: | |
| 3754 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionsDirectiveClass"); | |
| 3920 | case ZigClangStmt_OMPSectionsDirectiveClass: | |
| 3921 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSectionsDirectiveClass"); | |
| 3755 | 3922 | return ErrorUnexpected; |
| 3756 | case clang::Stmt::OMPSingleDirectiveClass: | |
| 3757 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSingleDirectiveClass"); | |
| 3923 | case ZigClangStmt_OMPSingleDirectiveClass: | |
| 3924 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSingleDirectiveClass"); | |
| 3758 | 3925 | return ErrorUnexpected; |
| 3759 | case clang::Stmt::OMPTargetDataDirectiveClass: | |
| 3760 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDataDirectiveClass"); | |
| 3926 | case ZigClangStmt_OMPTargetDataDirectiveClass: | |
| 3927 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetDataDirectiveClass"); | |
| 3761 | 3928 | return ErrorUnexpected; |
| 3762 | case clang::Stmt::OMPTargetDirectiveClass: | |
| 3763 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDirectiveClass"); | |
| 3929 | case ZigClangStmt_OMPTargetDirectiveClass: | |
| 3930 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetDirectiveClass"); | |
| 3764 | 3931 | return ErrorUnexpected; |
| 3765 | case clang::Stmt::OMPTargetEnterDataDirectiveClass: | |
| 3766 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetEnterDataDirectiveClass"); | |
| 3932 | case ZigClangStmt_OMPTargetEnterDataDirectiveClass: | |
| 3933 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetEnterDataDirectiveClass"); | |
| 3767 | 3934 | return ErrorUnexpected; |
| 3768 | case clang::Stmt::OMPTargetExitDataDirectiveClass: | |
| 3769 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetExitDataDirectiveClass"); | |
| 3935 | case ZigClangStmt_OMPTargetExitDataDirectiveClass: | |
| 3936 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetExitDataDirectiveClass"); | |
| 3770 | 3937 | return ErrorUnexpected; |
| 3771 | case clang::Stmt::OMPTargetParallelDirectiveClass: | |
| 3772 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelDirectiveClass"); | |
| 3938 | case ZigClangStmt_OMPTargetParallelDirectiveClass: | |
| 3939 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelDirectiveClass"); | |
| 3773 | 3940 | return ErrorUnexpected; |
| 3774 | case clang::Stmt::OMPTargetParallelForDirectiveClass: | |
| 3775 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForDirectiveClass"); | |
| 3941 | case ZigClangStmt_OMPTargetParallelForDirectiveClass: | |
| 3942 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelForDirectiveClass"); | |
| 3776 | 3943 | return ErrorUnexpected; |
| 3777 | case clang::Stmt::OMPTargetTeamsDirectiveClass: | |
| 3778 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDirectiveClass"); | |
| 3944 | case ZigClangStmt_OMPTargetTeamsDirectiveClass: | |
| 3945 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDirectiveClass"); | |
| 3779 | 3946 | return ErrorUnexpected; |
| 3780 | case clang::Stmt::OMPTargetUpdateDirectiveClass: | |
| 3781 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetUpdateDirectiveClass"); | |
| 3947 | case ZigClangStmt_OMPTargetUpdateDirectiveClass: | |
| 3948 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetUpdateDirectiveClass"); | |
| 3782 | 3949 | return ErrorUnexpected; |
| 3783 | case clang::Stmt::OMPTaskDirectiveClass: | |
| 3784 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskDirectiveClass"); | |
| 3950 | case ZigClangStmt_OMPTaskDirectiveClass: | |
| 3951 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskDirectiveClass"); | |
| 3785 | 3952 | return ErrorUnexpected; |
| 3786 | case clang::Stmt::OMPTaskgroupDirectiveClass: | |
| 3787 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskgroupDirectiveClass"); | |
| 3953 | case ZigClangStmt_OMPTaskgroupDirectiveClass: | |
| 3954 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskgroupDirectiveClass"); | |
| 3788 | 3955 | return ErrorUnexpected; |
| 3789 | case clang::Stmt::OMPTaskwaitDirectiveClass: | |
| 3790 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskwaitDirectiveClass"); | |
| 3956 | case ZigClangStmt_OMPTaskwaitDirectiveClass: | |
| 3957 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskwaitDirectiveClass"); | |
| 3791 | 3958 | return ErrorUnexpected; |
| 3792 | case clang::Stmt::OMPTaskyieldDirectiveClass: | |
| 3793 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskyieldDirectiveClass"); | |
| 3959 | case ZigClangStmt_OMPTaskyieldDirectiveClass: | |
| 3960 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskyieldDirectiveClass"); | |
| 3794 | 3961 | return ErrorUnexpected; |
| 3795 | case clang::Stmt::OMPTeamsDirectiveClass: | |
| 3796 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDirectiveClass"); | |
| 3962 | case ZigClangStmt_OMPTeamsDirectiveClass: | |
| 3963 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDirectiveClass"); | |
| 3797 | 3964 | return ErrorUnexpected; |
| 3798 | case clang::Stmt::ObjCAtCatchStmtClass: | |
| 3799 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtCatchStmtClass"); | |
| 3965 | case ZigClangStmt_ObjCAtCatchStmtClass: | |
| 3966 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtCatchStmtClass"); | |
| 3800 | 3967 | return ErrorUnexpected; |
| 3801 | case clang::Stmt::ObjCAtFinallyStmtClass: | |
| 3802 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtFinallyStmtClass"); | |
| 3968 | case ZigClangStmt_ObjCAtFinallyStmtClass: | |
| 3969 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtFinallyStmtClass"); | |
| 3803 | 3970 | return ErrorUnexpected; |
| 3804 | case clang::Stmt::ObjCAtSynchronizedStmtClass: | |
| 3805 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtSynchronizedStmtClass"); | |
| 3971 | case ZigClangStmt_ObjCAtSynchronizedStmtClass: | |
| 3972 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtSynchronizedStmtClass"); | |
| 3806 | 3973 | return ErrorUnexpected; |
| 3807 | case clang::Stmt::ObjCAtThrowStmtClass: | |
| 3808 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtThrowStmtClass"); | |
| 3974 | case ZigClangStmt_ObjCAtThrowStmtClass: | |
| 3975 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtThrowStmtClass"); | |
| 3809 | 3976 | return ErrorUnexpected; |
| 3810 | case clang::Stmt::ObjCAtTryStmtClass: | |
| 3811 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtTryStmtClass"); | |
| 3977 | case ZigClangStmt_ObjCAtTryStmtClass: | |
| 3978 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtTryStmtClass"); | |
| 3812 | 3979 | return ErrorUnexpected; |
| 3813 | case clang::Stmt::ObjCAutoreleasePoolStmtClass: | |
| 3814 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAutoreleasePoolStmtClass"); | |
| 3980 | case ZigClangStmt_ObjCAutoreleasePoolStmtClass: | |
| 3981 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAutoreleasePoolStmtClass"); | |
| 3815 | 3982 | return ErrorUnexpected; |
| 3816 | case clang::Stmt::ObjCForCollectionStmtClass: | |
| 3817 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCForCollectionStmtClass"); | |
| 3983 | case ZigClangStmt_ObjCForCollectionStmtClass: | |
| 3984 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCForCollectionStmtClass"); | |
| 3818 | 3985 | return ErrorUnexpected; |
| 3819 | case clang::Stmt::SEHExceptStmtClass: | |
| 3820 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHExceptStmtClass"); | |
| 3986 | case ZigClangStmt_SEHExceptStmtClass: | |
| 3987 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHExceptStmtClass"); | |
| 3821 | 3988 | return ErrorUnexpected; |
| 3822 | case clang::Stmt::SEHFinallyStmtClass: | |
| 3823 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHFinallyStmtClass"); | |
| 3989 | case ZigClangStmt_SEHFinallyStmtClass: | |
| 3990 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHFinallyStmtClass"); | |
| 3824 | 3991 | return ErrorUnexpected; |
| 3825 | case clang::Stmt::SEHLeaveStmtClass: | |
| 3826 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHLeaveStmtClass"); | |
| 3992 | case ZigClangStmt_SEHLeaveStmtClass: | |
| 3993 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHLeaveStmtClass"); | |
| 3827 | 3994 | return ErrorUnexpected; |
| 3828 | case clang::Stmt::SEHTryStmtClass: | |
| 3829 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHTryStmtClass"); | |
| 3995 | case ZigClangStmt_SEHTryStmtClass: | |
| 3996 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHTryStmtClass"); | |
| 3830 | 3997 | return ErrorUnexpected; |
| 3831 | 3998 | } |
| 3832 | 3999 | zig_unreachable(); |
| 3833 | 4000 | } |
| 3834 | 4001 | |
| 3835 | 4002 | // Returns null if there was an error |
| 3836 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, | |
| 4003 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr, | |
| 3837 | 4004 | TransLRValue lrval) |
| 3838 | 4005 | { |
| 3839 | 4006 | AstNode *result_node; |
| 3840 | 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 | 4009 | return nullptr; |
| 3843 | 4010 | } |
| 3844 | 4011 | return result_node; |
| ... | ... | @@ -3846,7 +4013,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope |
| 3846 | 4013 | |
| 3847 | 4014 | // Statements have no result and no concept of L or R value. |
| 3848 | 4015 | // Returns child scope, or null if there was an error |
| 3849 | static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node) { | |
| 4016 | static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt *stmt, AstNode **out_node) { | |
| 3850 | 4017 | TransScope *child_scope; |
| 3851 | 4018 | if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) { |
| 3852 | 4019 | return nullptr; |
| ... | ... | @@ -3854,34 +4021,36 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt * |
| 3854 | 4021 | return child_scope; |
| 3855 | 4022 | } |
| 3856 | 4023 | |
| 3857 | static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { | |
| 3858 | Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); | |
| 4024 | static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) { | |
| 4025 | Buf *fn_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)fn_decl)); | |
| 3859 | 4026 | |
| 3860 | 4027 | if (get_global(c, fn_name)) { |
| 3861 | 4028 | // we already saw this function |
| 3862 | 4029 | return; |
| 3863 | 4030 | } |
| 3864 | 4031 | |
| 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 | 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 | 4037 | return; |
| 3869 | 4038 | } |
| 3870 | 4039 | |
| 3871 | 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); | |
| 3873 | 4042 | |
| 3874 | clang::StorageClass sc = fn_decl->getStorageClass(); | |
| 3875 | if (sc == clang::SC_None) { | |
| 4043 | ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl); | |
| 4044 | if (sc == ZigClangStorageClass_None) { | |
| 3876 | 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; | |
| 3878 | } else if (sc == clang::SC_Extern || sc == clang::SC_Static) { | |
| 4046 | proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false; | |
| 4047 | } else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) { | |
| 3879 | 4048 | proto_node->data.fn_proto.visib_mod = c->visib_mod; |
| 3880 | } else if (sc == clang::SC_PrivateExtern) { | |
| 3881 | emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern"); | |
| 4049 | } else if (sc == ZigClangStorageClass_PrivateExtern) { | |
| 4050 | emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern"); | |
| 3882 | 4051 | return; |
| 3883 | 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 | 4054 | return; |
| 3886 | 4055 | } |
| 3887 | 4056 | |
| ... | ... | @@ -3889,8 +4058,8 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { |
| 3889 | 4058 | |
| 3890 | 4059 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { |
| 3891 | 4060 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); |
| 3892 | const clang::ParmVarDecl *param = fn_decl->getParamDecl(i); | |
| 3893 | const char *name = decl_name(param); | |
| 4061 | const ZigClangParmVarDecl *param = ZigClangFunctionDecl_getParamDecl(fn_decl, i); | |
| 4062 | const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)param); | |
| 3894 | 4063 | |
| 3895 | 4064 | Buf *proto_param_name; |
| 3896 | 4065 | if (strlen(name) != 0) { |
| ... | ... | @@ -3908,7 +4077,7 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { |
| 3908 | 4077 | param_node->data.param_decl.name = scope_var->zig_name; |
| 3909 | 4078 | } |
| 3910 | 4079 | |
| 3911 | if (!fn_decl->hasBody()) { | |
| 4080 | if (!ZigClangFunctionDecl_hasBody(fn_decl)) { | |
| 3912 | 4081 | // just a prototype |
| 3913 | 4082 | add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node); |
| 3914 | 4083 | return; |
| ... | ... | @@ -3916,11 +4085,11 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { |
| 3916 | 4085 | |
| 3917 | 4086 | // actual function definition with body |
| 3918 | 4087 | c->ptr_params.clear(); |
| 3919 | clang::Stmt *body = fn_decl->getBody(); | |
| 4088 | const ZigClangStmt *body = ZigClangFunctionDecl_getBody(fn_decl); | |
| 3920 | 4089 | AstNode *actual_body_node; |
| 3921 | 4090 | TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node); |
| 3922 | 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 | 4093 | return; |
| 3925 | 4094 | } |
| 3926 | 4095 | assert(actual_body_node != nullptr); |
| ... | ... | @@ -3958,20 +4127,20 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { |
| 3958 | 4127 | add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node); |
| 3959 | 4128 | } |
| 3960 | 4129 | |
| 3961 | static AstNode *resolve_typdef_as_builtin(Context *c, const clang::TypedefNameDecl *typedef_decl, const char *primitive_name) { | |
| 4130 | static AstNode *resolve_typdef_as_builtin(Context *c, const ZigClangTypedefNameDecl *typedef_decl, const char *primitive_name) { | |
| 3962 | 4131 | AstNode *node = trans_create_node_symbol_str(c, primitive_name); |
| 3963 | 4132 | c->decl_table.put(typedef_decl, node); |
| 3964 | 4133 | return node; |
| 3965 | 4134 | } |
| 3966 | 4135 | |
| 3967 | static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) { | |
| 3968 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl()); | |
| 4136 | static AstNode *resolve_typedef_decl(Context *c, const ZigClangTypedefNameDecl *typedef_decl) { | |
| 4137 | auto existing_entry = c->decl_table.maybe_get((void*)ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)); | |
| 3969 | 4138 | if (existing_entry) { |
| 3970 | 4139 | return existing_entry->value; |
| 3971 | 4140 | } |
| 3972 | 4141 | |
| 3973 | clang::QualType child_qt = typedef_decl->getUnderlyingType(); | |
| 3974 | Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); | |
| 4142 | ZigClangQualType child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl); | |
| 4143 | Buf *type_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl)); | |
| 3975 | 4144 | |
| 3976 | 4145 | if (buf_eql_str(type_name, "uint8_t")) { |
| 3977 | 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 | 4174 | |
| 4006 | 4175 | // trans_qual_type here might cause us to look at this typedef again so we put the item in the map first |
| 4007 | 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); | |
| 4009 | 4178 | |
| 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 | 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 | 4183 | c->decl_table.put(typedef_decl, nullptr); |
| 4014 | 4184 | // TODO add global var with type_name equal to @compileError("unable to resolve C type") |
| 4015 | 4185 | return nullptr; |
| ... | ... | @@ -4019,33 +4189,33 @@ static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *t |
| 4019 | 4189 | return symbol_node; |
| 4020 | 4190 | } |
| 4021 | 4191 | |
| 4022 | struct AstNode *demote_enum_to_opaque(Context *c, const clang::EnumDecl *enum_decl, | |
| 4023 | Buf *full_type_name, Buf *bare_name) | |
| 4192 | struct AstNode *demote_enum_to_opaque(Context *c, const ZigClangEnumDecl *enum_decl, Buf *full_type_name, | |
| 4193 | Buf *bare_name) | |
| 4024 | 4194 | { |
| 4025 | 4195 | AstNode *opaque_node = trans_create_node_opaque(c); |
| 4026 | 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 | 4198 | return opaque_node; |
| 4029 | 4199 | } |
| 4030 | 4200 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); |
| 4031 | 4201 | add_global_weak_alias(c, bare_name, full_type_name); |
| 4032 | 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 | 4204 | return symbol_node; |
| 4035 | 4205 | } |
| 4036 | 4206 | |
| 4037 | static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) { | |
| 4038 | auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl()); | |
| 4207 | static AstNode *resolve_enum_decl(Context *c, const ZigClangEnumDecl *enum_decl) { | |
| 4208 | auto existing_entry = c->decl_table.maybe_get(ZigClangEnumDecl_getCanonicalDecl(enum_decl)); | |
| 4039 | 4209 | if (existing_entry) { |
| 4040 | 4210 | return existing_entry->value; |
| 4041 | 4211 | } |
| 4042 | 4212 | |
| 4043 | const char *raw_name = decl_name(enum_decl); | |
| 4213 | const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_decl); | |
| 4044 | 4214 | bool is_anonymous = (raw_name[0] == 0); |
| 4045 | 4215 | Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); |
| 4046 | 4216 | Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name)); |
| 4047 | 4217 | |
| 4048 | const clang::EnumDecl *enum_def = enum_decl->getDefinition(); | |
| 4218 | const ZigClangEnumDecl *enum_def = ZigClangEnumDecl_getDefinition(enum_decl); | |
| 4049 | 4219 | if (!enum_def) { |
| 4050 | 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 | 4223 | |
| 4054 | 4224 | bool pure_enum = true; |
| 4055 | 4225 | uint32_t field_count = 0; |
| 4056 | for (auto it = enum_def->enumerator_begin(), | |
| 4057 | it_end = enum_def->enumerator_end(); | |
| 4226 | for (auto it = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_begin(), | |
| 4227 | it_end = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_end(); | |
| 4058 | 4228 | it != it_end; ++it, field_count += 1) |
| 4059 | 4229 | { |
| 4060 | 4230 | const clang::EnumConstantDecl *enum_const = *it; |
| ... | ... | @@ -4062,7 +4232,8 @@ static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) |
| 4062 | 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 | 4237 | assert(tag_int_type); |
| 4067 | 4238 | |
| 4068 | 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 | 4242 | // TODO only emit this tag type if the enum tag type is not the default. |
| 4072 | 4243 | // I don't know what the default is, need to figure out how clang is deciding. |
| 4073 | 4244 | // it appears to at least be different across gcc/msvc |
| 4074 | if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) && | |
| 4075 | !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int)) | |
| 4245 | if (!c_is_builtin_type(c, ZigClangEnumDecl_getIntegerType(enum_decl), ZigClangBuiltinTypeUInt) && | |
| 4246 | !c_is_builtin_type(c, ZigClangEnumDecl_getIntegerType(enum_decl), ZigClangBuiltinTypeInt)) | |
| 4076 | 4247 | { |
| 4077 | 4248 | enum_node->data.container_decl.init_arg_expr = tag_int_type; |
| 4078 | 4249 | } |
| 4079 | 4250 | enum_node->data.container_decl.fields.resize(field_count); |
| 4080 | 4251 | uint32_t i = 0; |
| 4081 | for (auto it = enum_def->enumerator_begin(), | |
| 4082 | it_end = enum_def->enumerator_end(); | |
| 4252 | for (auto it = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_begin(), | |
| 4253 | it_end = reinterpret_cast<const clang::EnumDecl *>(enum_def)->enumerator_end(); | |
| 4083 | 4254 | it != it_end; ++it, i += 1) |
| 4084 | 4255 | { |
| 4085 | 4256 | const clang::EnumConstantDecl *enum_const = *it; |
| 4086 | 4257 | |
| 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 | 4259 | Buf *field_name; |
| 4089 | 4260 | if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) { |
| 4090 | 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 | 4263 | field_name = enum_val_name; |
| 4093 | 4264 | } |
| 4094 | 4265 | |
| 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 | 4268 | AstNode *field_node = trans_create_node(c, NodeTypeStructField); |
| 4097 | 4269 | field_node->data.struct_field.name = field_name; |
| 4098 | 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 | 4274 | // in C each enum value is in the global namespace. so we put them there too. |
| 4103 | 4275 | // at this point we can rely on the enum emitting successfully |
| 4104 | 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 | 4278 | add_global_var(c, enum_val_name, int_node); |
| 4107 | 4279 | } else { |
| 4108 | 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 | 4284 | } |
| 4113 | 4285 | |
| 4114 | 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 | 4288 | return enum_node; |
| 4117 | 4289 | } else { |
| 4118 | 4290 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); |
| 4119 | 4291 | add_global_weak_alias(c, bare_name, full_type_name); |
| 4120 | 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 | 4294 | return enum_node; |
| 4123 | 4295 | } |
| 4124 | 4296 | } |
| 4125 | 4297 | |
| 4126 | static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl, | |
| 4298 | static AstNode *demote_struct_to_opaque(Context *c, const ZigClangRecordDecl *record_decl, | |
| 4127 | 4299 | Buf *full_type_name, Buf *bare_name) |
| 4128 | 4300 | { |
| 4129 | 4301 | AstNode *opaque_node = trans_create_node_opaque(c); |
| 4130 | 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 | 4304 | return opaque_node; |
| 4133 | 4305 | } |
| 4134 | 4306 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); |
| 4135 | 4307 | add_global_weak_alias(c, bare_name, full_type_name); |
| 4136 | 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 | 4310 | return symbol_node; |
| 4139 | 4311 | } |
| 4140 | 4312 | |
| 4141 | static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) { | |
| 4142 | auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl()); | |
| 4313 | static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl) { | |
| 4314 | auto existing_entry = c->decl_table.maybe_get(ZigClangRecordDecl_getCanonicalDecl(record_decl)); | |
| 4143 | 4315 | if (existing_entry) { |
| 4144 | 4316 | return existing_entry->value; |
| 4145 | 4317 | } |
| 4146 | 4318 | |
| 4147 | const char *raw_name = decl_name(record_decl); | |
| 4319 | const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)record_decl); | |
| 4148 | 4320 | const char *container_kind_name; |
| 4149 | 4321 | ContainerKind container_kind; |
| 4150 | if (record_decl->isUnion()) { | |
| 4322 | if (ZigClangRecordDecl_isUnion(record_decl)) { | |
| 4151 | 4323 | container_kind_name = "union"; |
| 4152 | 4324 | container_kind = ContainerKindUnion; |
| 4153 | } else if (record_decl->isStruct()) { | |
| 4325 | } else if (ZigClangRecordDecl_isStruct(record_decl)) { | |
| 4154 | 4326 | container_kind_name = "struct"; |
| 4155 | 4327 | container_kind = ContainerKindStruct; |
| 4156 | 4328 | } else { |
| 4157 | emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct or union", raw_name); | |
| 4158 | c->decl_table.put(record_decl->getCanonicalDecl(), nullptr); | |
| 4329 | emit_warning(c, ZigClangRecordDecl_getLocation(record_decl), | |
| 4330 | "skipping record %s, not a struct or union", raw_name); | |
| 4331 | c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), nullptr); | |
| 4159 | 4332 | return nullptr; |
| 4160 | 4333 | } |
| 4161 | 4334 | |
| 4162 | bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0; | |
| 4335 | bool is_anonymous = ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) || raw_name[0] == 0; | |
| 4163 | 4336 | Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); |
| 4164 | 4337 | Buf *full_type_name = (bare_name == nullptr) ? |
| 4165 | 4338 | nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name)); |
| 4166 | 4339 | |
| 4167 | clang::RecordDecl *record_def = record_decl->getDefinition(); | |
| 4340 | const ZigClangRecordDecl *record_def = ZigClangRecordDecl_getDefinition(record_decl); | |
| 4168 | 4341 | if (record_def == nullptr) { |
| 4169 | 4342 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); |
| 4170 | 4343 | } |
| 4171 | 4344 | |
| 4172 | 4345 | // count fields and validate |
| 4173 | 4346 | uint32_t field_count = 0; |
| 4174 | for (auto it = record_def->field_begin(), | |
| 4175 | it_end = record_def->field_end(); | |
| 4347 | for (auto it = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_begin(), | |
| 4348 | it_end = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_end(); | |
| 4176 | 4349 | it != it_end; ++it, field_count += 1) |
| 4177 | 4350 | { |
| 4178 | 4351 | const clang::FieldDecl *field_decl = *it; |
| 4179 | 4352 | |
| 4180 | 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 | 4355 | container_kind_name, |
| 4183 | 4356 | is_anonymous ? "(anon)" : buf_ptr(bare_name)); |
| 4184 | 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 | 4368 | |
| 4196 | 4369 | // must be before fields in case a circular reference happens |
| 4197 | 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 | 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 | } |
| 4202 | 4375 | |
| 4203 | 4376 | uint32_t i = 0; |
| 4204 | for (auto it = record_def->field_begin(), | |
| 4205 | it_end = record_def->field_end(); | |
| 4377 | for (auto it = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_begin(), | |
| 4378 | it_end = reinterpret_cast<const clang::RecordDecl *>(record_def)->field_end(); | |
| 4206 | 4379 | it != it_end; ++it, i += 1) |
| 4207 | 4380 | { |
| 4208 | 4381 | const clang::FieldDecl *field_decl = *it; |
| 4209 | 4382 | |
| 4210 | 4383 | AstNode *field_node = trans_create_node(c, NodeTypeStructField); |
| 4211 | field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl)); | |
| 4212 | field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation()); | |
| 4384 | field_node->data.struct_field.name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)field_decl)); | |
| 4385 | field_node->data.struct_field.type = trans_qual_type(c, bitcast(field_decl->getType()), | |
| 4386 | bitcast(field_decl->getLocation())); | |
| 4213 | 4387 | |
| 4214 | 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 | 4390 | "%s %s demoted to opaque type - unresolved type", |
| 4217 | 4391 | container_kind_name, |
| 4218 | 4392 | is_anonymous ? "(anon)" : buf_ptr(bare_name)); |
| ... | ... | @@ -4232,17 +4406,19 @@ static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_ |
| 4232 | 4406 | } |
| 4233 | 4407 | } |
| 4234 | 4408 | |
| 4235 | static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) { | |
| 4236 | switch (ap_value->getKind()) { | |
| 4237 | case clang::APValue::Int: | |
| 4238 | return trans_create_node_apint(c, ap_value->getInt()); | |
| 4239 | case clang::APValue::Uninitialized: | |
| 4409 | static AstNode *trans_ap_value(Context *c, const ZigClangAPValue *ap_value, ZigClangQualType qt, | |
| 4410 | ZigClangSourceLocation source_loc) | |
| 4411 | { | |
| 4412 | switch (ZigClangAPValue_getKind(ap_value)) { | |
| 4413 | case ZigClangAPValueInt: | |
| 4414 | return trans_create_node_apint(c, ZigClangAPValue_getInt(ap_value)); | |
| 4415 | case ZigClangAPValueUninitialized: | |
| 4240 | 4416 | return trans_create_node(c, NodeTypeUndefinedLiteral); |
| 4241 | case clang::APValue::Array: { | |
| 4417 | case ZigClangAPValueArray: { | |
| 4242 | 4418 | emit_warning(c, source_loc, "TODO add a test case for this code"); |
| 4243 | 4419 | |
| 4244 | unsigned init_count = ap_value->getArrayInitializedElts(); | |
| 4245 | unsigned all_count = ap_value->getArraySize(); | |
| 4420 | unsigned init_count = ZigClangAPValue_getArrayInitializedElts(ap_value); | |
| 4421 | unsigned all_count = ZigClangAPValue_getArraySize(ap_value); | |
| 4246 | 4422 | unsigned leftover_count = all_count - init_count; |
| 4247 | 4423 | AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr); |
| 4248 | 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 | 4428 | init_node->data.container_init_expr.type = arr_type_node; |
| 4253 | 4429 | init_node->data.container_init_expr.kind = ContainerInitKindArray; |
| 4254 | 4430 | |
| 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()); | |
| 4256 | 4433 | |
| 4257 | 4434 | for (size_t i = 0; i < init_count; i += 1) { |
| 4258 | clang::APValue &elem_ap_val = ap_value->getArrayInitializedElt(i); | |
| 4259 | AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc); | |
| 4435 | const ZigClangAPValue *elem_ap_val = ZigClangAPValue_getArrayInitializedElt(ap_value, i); | |
| 4436 | AstNode *elem_node = trans_ap_value(c, elem_ap_val, child_qt, source_loc); | |
| 4260 | 4437 | if (elem_node == nullptr) |
| 4261 | 4438 | return nullptr; |
| 4262 | 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 | 4442 | return init_node; |
| 4266 | 4443 | } |
| 4267 | 4444 | |
| 4268 | clang::APValue &filler_ap_val = ap_value->getArrayFiller(); | |
| 4269 | AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc); | |
| 4445 | const ZigClangAPValue *filler_ap_val = ZigClangAPValue_getArrayFiller(ap_value); | |
| 4446 | AstNode *filler_node = trans_ap_value(c, filler_ap_val, child_qt, source_loc); | |
| 4270 | 4447 | if (filler_node == nullptr) |
| 4271 | 4448 | return nullptr; |
| 4272 | 4449 | |
| ... | ... | @@ -4293,37 +4470,37 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual |
| 4293 | 4470 | |
| 4294 | 4471 | return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node); |
| 4295 | 4472 | } |
| 4296 | case clang::APValue::LValue: { | |
| 4297 | const clang::APValue::LValueBase lval_base = ap_value->getLValueBase(); | |
| 4298 | if (const clang::Expr *expr = lval_base.dyn_cast<const clang::Expr *>()) { | |
| 4473 | case ZigClangAPValueLValue: { | |
| 4474 | const ZigClangAPValueLValueBase lval_base = ZigClangAPValue_getLValueBase(ap_value); | |
| 4475 | if (const ZigClangExpr *expr = ZigClangAPValueLValueBase_dyn_cast_Expr(lval_base)) { | |
| 4299 | 4476 | return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue); |
| 4300 | 4477 | } |
| 4301 | 4478 | //const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>(); |
| 4302 | 4479 | emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl"); |
| 4303 | 4480 | return nullptr; |
| 4304 | 4481 | } |
| 4305 | case clang::APValue::Float: | |
| 4482 | case ZigClangAPValueFloat: | |
| 4306 | 4483 | emit_warning(c, source_loc, "unsupported initializer value kind: Float"); |
| 4307 | 4484 | return nullptr; |
| 4308 | case clang::APValue::ComplexInt: | |
| 4485 | case ZigClangAPValueComplexInt: | |
| 4309 | 4486 | emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt"); |
| 4310 | 4487 | return nullptr; |
| 4311 | case clang::APValue::ComplexFloat: | |
| 4488 | case ZigClangAPValueComplexFloat: | |
| 4312 | 4489 | emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat"); |
| 4313 | 4490 | return nullptr; |
| 4314 | case clang::APValue::Vector: | |
| 4491 | case ZigClangAPValueVector: | |
| 4315 | 4492 | emit_warning(c, source_loc, "unsupported initializer value kind: Vector"); |
| 4316 | 4493 | return nullptr; |
| 4317 | case clang::APValue::Struct: | |
| 4494 | case ZigClangAPValueStruct: | |
| 4318 | 4495 | emit_warning(c, source_loc, "unsupported initializer value kind: Struct"); |
| 4319 | 4496 | return nullptr; |
| 4320 | case clang::APValue::Union: | |
| 4497 | case ZigClangAPValueUnion: | |
| 4321 | 4498 | emit_warning(c, source_loc, "unsupported initializer value kind: Union"); |
| 4322 | 4499 | return nullptr; |
| 4323 | case clang::APValue::MemberPointer: | |
| 4500 | case ZigClangAPValueMemberPointer: | |
| 4324 | 4501 | emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer"); |
| 4325 | 4502 | return nullptr; |
| 4326 | case clang::APValue::AddrLabelDiff: | |
| 4503 | case ZigClangAPValueAddrLabelDiff: | |
| 4327 | 4504 | emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff"); |
| 4328 | 4505 | return nullptr; |
| 4329 | 4506 | } |
| ... | ... | @@ -4331,42 +4508,42 @@ static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::Qual |
| 4331 | 4508 | } |
| 4332 | 4509 | |
| 4333 | 4510 | static 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)); | |
| 4335 | 4512 | |
| 4336 | 4513 | switch (var_decl->getTLSKind()) { |
| 4337 | 4514 | case clang::VarDecl::TLS_None: |
| 4338 | 4515 | break; |
| 4339 | 4516 | case clang::VarDecl::TLS_Static: |
| 4340 | emit_warning(c, var_decl->getLocation(), | |
| 4517 | emit_warning(c, bitcast(var_decl->getLocation()), | |
| 4341 | 4518 | "ignoring variable '%s' - static thread local storage", buf_ptr(name)); |
| 4342 | 4519 | return; |
| 4343 | 4520 | case clang::VarDecl::TLS_Dynamic: |
| 4344 | emit_warning(c, var_decl->getLocation(), | |
| 4521 | emit_warning(c, bitcast(var_decl->getLocation()), | |
| 4345 | 4522 | "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name)); |
| 4346 | 4523 | return; |
| 4347 | 4524 | } |
| 4348 | 4525 | |
| 4349 | clang::QualType qt = var_decl->getType(); | |
| 4350 | AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation()); | |
| 4526 | ZigClangQualType qt = bitcast(var_decl->getType()); | |
| 4527 | AstNode *var_type = trans_qual_type(c, qt, bitcast(var_decl->getLocation())); | |
| 4351 | 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 | 4530 | return; |
| 4354 | 4531 | } |
| 4355 | 4532 | |
| 4356 | 4533 | bool is_extern = var_decl->hasExternalStorage(); |
| 4357 | 4534 | bool is_static = var_decl->isFileVarDecl(); |
| 4358 | bool is_const = qt.isConstQualified(); | |
| 4535 | bool is_const = ZigClangQualType_isConstQualified(qt); | |
| 4359 | 4536 | |
| 4360 | 4537 | if (is_static && !is_extern) { |
| 4361 | 4538 | AstNode *init_node; |
| 4362 | 4539 | if (var_decl->hasInit()) { |
| 4363 | clang::APValue *ap_value = var_decl->evaluateValue(); | |
| 4540 | const ZigClangAPValue *ap_value = bitcast(var_decl->evaluateValue()); | |
| 4364 | 4541 | if (ap_value == nullptr) { |
| 4365 | emit_warning(c, var_decl->getLocation(), | |
| 4542 | emit_warning(c, bitcast(var_decl->getLocation()), | |
| 4366 | 4543 | "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name)); |
| 4367 | 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 | 4547 | if (init_node == nullptr) |
| 4371 | 4548 | return; |
| 4372 | 4549 | } else { |
| ... | ... | @@ -4385,33 +4562,32 @@ static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) { |
| 4385 | 4562 | return; |
| 4386 | 4563 | } |
| 4387 | 4564 | |
| 4388 | emit_warning(c, var_decl->getLocation(), | |
| 4565 | emit_warning(c, bitcast(var_decl->getLocation()), | |
| 4389 | 4566 | "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name)); |
| 4390 | 4567 | return; |
| 4391 | 4568 | } |
| 4392 | 4569 | |
| 4393 | static bool decl_visitor(void *context, const ZigClangDecl *zdecl) { | |
| 4394 | const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zdecl); | |
| 4570 | static bool decl_visitor(void *context, const ZigClangDecl *decl) { | |
| 4395 | 4571 | Context *c = (Context*)context; |
| 4396 | 4572 | |
| 4397 | switch (decl->getKind()) { | |
| 4398 | case clang::Decl::Function: | |
| 4399 | visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl)); | |
| 4573 | switch (ZigClangDecl_getKind(decl)) { | |
| 4574 | case ZigClangDeclFunction: | |
| 4575 | visit_fn_decl(c, reinterpret_cast<const ZigClangFunctionDecl*>(decl)); | |
| 4400 | 4576 | break; |
| 4401 | case clang::Decl::Typedef: | |
| 4402 | resolve_typedef_decl(c, static_cast<const clang::TypedefNameDecl *>(decl)); | |
| 4577 | case ZigClangDeclTypedef: | |
| 4578 | resolve_typedef_decl(c, reinterpret_cast<const ZigClangTypedefNameDecl *>(decl)); | |
| 4403 | 4579 | break; |
| 4404 | case clang::Decl::Enum: | |
| 4405 | resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl)); | |
| 4580 | case ZigClangDeclEnum: | |
| 4581 | resolve_enum_decl(c, reinterpret_cast<const ZigClangEnumDecl *>(decl)); | |
| 4406 | 4582 | break; |
| 4407 | case clang::Decl::Record: | |
| 4408 | resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl)); | |
| 4583 | case ZigClangDeclRecord: | |
| 4584 | resolve_record_decl(c, reinterpret_cast<const ZigClangRecordDecl *>(decl)); | |
| 4409 | 4585 | break; |
| 4410 | case clang::Decl::Var: | |
| 4411 | visit_var_decl(c, static_cast<const clang::VarDecl *>(decl)); | |
| 4586 | case ZigClangDeclVar: | |
| 4587 | visit_var_decl(c, reinterpret_cast<const clang::VarDecl *>(decl)); | |
| 4412 | 4588 | break; |
| 4413 | 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 | } |
| 4416 | 4592 | |
| 4417 | 4593 | return true; |
| ... | ... | @@ -4720,6 +4896,8 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok |
| 4720 | 4896 | case CTokIdAsterisk: |
| 4721 | 4897 | case CTokIdBang: |
| 4722 | 4898 | case CTokIdTilde: |
| 4899 | case CTokIdShl: | |
| 4900 | case CTokIdLt: | |
| 4723 | 4901 | // not able to make sense of this |
| 4724 | 4902 | return nullptr; |
| 4725 | 4903 | } |
| ... | ... | @@ -4751,6 +4929,13 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t |
| 4751 | 4929 | *tok_i += 1; |
| 4752 | 4930 | |
| 4753 | 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 | 4939 | } else { |
| 4755 | 4940 | return node; |
| 4756 | 4941 | } |
| ... | ... | @@ -4846,10 +5031,10 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) { |
| 4846 | 5031 | clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity); |
| 4847 | 5032 | const char *raw_name = macro->getName()->getNameStart(); |
| 4848 | 5033 | clang::SourceRange range = macro->getSourceRange(); |
| 4849 | clang::SourceLocation begin_loc = range.getBegin(); | |
| 4850 | clang::SourceLocation end_loc = range.getEnd(); | |
| 5034 | ZigClangSourceLocation begin_loc = bitcast(range.getBegin()); | |
| 5035 | ZigClangSourceLocation end_loc = bitcast(range.getEnd()); | |
| 4851 | 5036 | |
| 4852 | if (begin_loc == end_loc) { | |
| 5037 | if (ZigClangSourceLocation_eq(begin_loc, end_loc)) { | |
| 4853 | 5038 | // this means it is a macro without a value |
| 4854 | 5039 | // we don't care about such things |
| 4855 | 5040 | continue; |
| ... | ... | @@ -4859,21 +5044,22 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) { |
| 4859 | 5044 | continue; |
| 4860 | 5045 | } |
| 4861 | 5046 | |
| 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 | 5048 | process_macro(c, &ctok, name, begin_c); |
| 4864 | 5049 | } |
| 4865 | 5050 | } |
| 4866 | 5051 | } |
| 4867 | 5052 | } |
| 4868 | 5053 | |
| 4869 | Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file, | |
| 4870 | CodeGen *codegen, Buf *tmp_dep_file) | |
| 5054 | Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, | |
| 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 | 5059 | Context context = {0}; |
| 4873 | 5060 | Context *c = &context; |
| 4874 | 5061 | c->warnings_on = codegen->verbose_cimport; |
| 4875 | c->errors = errors; | |
| 4876 | if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) { | |
| 5062 | if (mode == Stage2TranslateModeImport) { | |
| 4877 | 5063 | c->visib_mod = VisibModPub; |
| 4878 | 5064 | c->want_export = false; |
| 4879 | 5065 | } else { |
| ... | ... | @@ -4887,161 +5073,10 @@ Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const c |
| 4887 | 5073 | c->codegen = codegen; |
| 4888 | 5074 | c->global_scope = trans_scope_root_create(c); |
| 4889 | 5075 | |
| 4890 | ZigList<const char *> clang_argv = {0}; | |
| 4891 | ||
| 4892 | clang_argv.append("-x"); | |
| 4893 | clang_argv.append("c"); | |
| 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 | ||
| 5076 | ZigClangASTUnit *ast_unit = ZigClangLoadFromCommandLine(args_begin, args_end, errors_ptr, errors_len, | |
| 5077 | resources_path); | |
| 5078 | if (ast_unit == nullptr) { | |
| 5079 | if (*errors_len == 0) return ErrorNoMem; | |
| 5045 | 5080 | return ErrorCCompileErrors; |
| 5046 | 5081 | } |
| 5047 | 5082 | |
| ... | ... | @@ -5059,5 +5094,7 @@ Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const c |
| 5059 | 5094 | |
| 5060 | 5095 | *out_root_node = c->root; |
| 5061 | 5096 | |
| 5097 | ZigClangASTUnit_delete(ast_unit); | |
| 5098 | ||
| 5062 | 5099 | return ErrorNone; |
| 5063 | 5100 | } |
src/translate_c.hpp+4-2| ... | ... | @@ -11,7 +11,9 @@ |
| 11 | 11 | |
| 12 | 12 | #include "all_types.hpp" |
| 13 | 13 | |
| 14 | Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file, | |
| 15 | CodeGen *codegen, Buf *tmp_dep_file); | |
| 14 | Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, | |
| 15 | Stage2ErrorMsg **errors_ptr, size_t *errors_len, | |
| 16 | const char **args_begin, const char **args_end, | |
| 17 | Stage2TranslateMode mode, const char *resources_path); | |
| 16 | 18 | |
| 17 | 19 | #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 | ||
| 10 | Error 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 | ||
| 19 | void 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 | ||
| 24 | void stage2_zen(const char **ptr, size_t *len) { | |
| 25 | const char *msg = "stage0 called stage2_zen"; | |
| 26 | stage2_panic(msg, strlen(msg)); | |
| 27 | } | |
| 28 | ||
| 29 | void 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 | ||
| 36 | void 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 | ||
| 41 | int 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 | |
| 30 | enum 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 | |
| 79 | enum Stage2TranslateMode { | |
| 80 | Stage2TranslateModeImport, | |
| 81 | Stage2TranslateModeTranslate, | |
| 82 | }; | |
| 83 | ||
| 84 | // ABI warning | |
| 85 | struct 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 | |
| 97 | struct Stage2Ast; | |
| 98 | ||
| 99 | // ABI warning | |
| 100 | ZIG_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 | |
| 106 | ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len); | |
| 107 | ||
| 108 | // ABI warning | |
| 109 | ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file); | |
| 110 | ||
| 111 | // ABI warning | |
| 112 | ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len); | |
| 113 | ||
| 114 | // ABI warning | |
| 115 | ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); | |
| 116 | ||
| 117 | // ABI warning | |
| 118 | ZIG_EXTERN_C int stage2_fmt(int argc, char **argv); | |
| 119 | ||
| 120 | #endif |
src/util.cpp+9-1| ... | ... | @@ -10,17 +10,25 @@ |
| 10 | 10 | #include <stdarg.h> |
| 11 | 11 | |
| 12 | 12 | #include "util.hpp" |
| 13 | #include "userland.h" | |
| 13 | 14 | |
| 14 | 15 | void zig_panic(const char *format, ...) { |
| 15 | 16 | va_list ap; |
| 16 | 17 | va_start(ap, format); |
| 17 | 18 | vfprintf(stderr, format, ap); |
| 18 | fprintf(stderr, "\n"); | |
| 19 | 19 | fflush(stderr); |
| 20 | 20 | va_end(ap); |
| 21 | stage2_panic(nullptr, 0); | |
| 21 | 22 | abort(); |
| 22 | 23 | } |
| 23 | 24 | |
| 25 | void 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 | ||
| 24 | 32 | uint32_t int_hash(int i) { |
| 25 | 33 | return (uint32_t)(i % UINT32_MAX); |
| 26 | 34 | } |
src/util.hpp+4| ... | ... | @@ -48,6 +48,10 @@ void zig_panic(const char *format, ...); |
| 48 | 48 | |
| 49 | 49 | #define zig_unreachable() zig_panic("unreachable: %s:%s:%d", __FILE__, __func__, __LINE__) |
| 50 | 50 | |
| 51 | // Assertions in stage1 are always on, and they call zig @panic. | |
| 52 | #undef assert | |
| 53 | void assert(bool ok); | |
| 54 | ||
| 51 | 55 | #if defined(_MSC_VER) |
| 52 | 56 | static inline int clzll(unsigned long long mask) { |
| 53 | 57 | unsigned long lz; |
src/zig_clang.cpp+1667-50| ... | ... | @@ -28,41 +28,41 @@ |
| 28 | 28 | #endif |
| 29 | 29 | |
| 30 | 30 | // Detect additions to the enum |
| 31 | void zig2clang_BO(ZigClangBO op) { | |
| 31 | void ZigClang_detect_enum_BO(clang::BinaryOperatorKind op) { | |
| 32 | 32 | switch (op) { |
| 33 | case ZigClangBO_PtrMemD: | |
| 34 | case ZigClangBO_PtrMemI: | |
| 35 | case ZigClangBO_Cmp: | |
| 36 | case ZigClangBO_Mul: | |
| 37 | case ZigClangBO_Div: | |
| 38 | case ZigClangBO_Rem: | |
| 39 | case ZigClangBO_Add: | |
| 40 | case ZigClangBO_Sub: | |
| 41 | case ZigClangBO_Shl: | |
| 42 | case ZigClangBO_Shr: | |
| 43 | case ZigClangBO_LT: | |
| 44 | case ZigClangBO_GT: | |
| 45 | case ZigClangBO_LE: | |
| 46 | case ZigClangBO_GE: | |
| 47 | case ZigClangBO_EQ: | |
| 48 | case ZigClangBO_NE: | |
| 49 | case ZigClangBO_And: | |
| 50 | case ZigClangBO_Xor: | |
| 51 | case ZigClangBO_Or: | |
| 52 | case ZigClangBO_LAnd: | |
| 53 | case ZigClangBO_LOr: | |
| 54 | case ZigClangBO_Assign: | |
| 55 | case ZigClangBO_Comma: | |
| 56 | case ZigClangBO_MulAssign: | |
| 57 | case ZigClangBO_DivAssign: | |
| 58 | case ZigClangBO_RemAssign: | |
| 59 | case ZigClangBO_AddAssign: | |
| 60 | case ZigClangBO_SubAssign: | |
| 61 | case ZigClangBO_ShlAssign: | |
| 62 | case ZigClangBO_ShrAssign: | |
| 63 | case ZigClangBO_AndAssign: | |
| 64 | case ZigClangBO_XorAssign: | |
| 65 | case ZigClangBO_OrAssign: | |
| 33 | case clang::BO_PtrMemD: | |
| 34 | case clang::BO_PtrMemI: | |
| 35 | case clang::BO_Cmp: | |
| 36 | case clang::BO_Mul: | |
| 37 | case clang::BO_Div: | |
| 38 | case clang::BO_Rem: | |
| 39 | case clang::BO_Add: | |
| 40 | case clang::BO_Sub: | |
| 41 | case clang::BO_Shl: | |
| 42 | case clang::BO_Shr: | |
| 43 | case clang::BO_LT: | |
| 44 | case clang::BO_GT: | |
| 45 | case clang::BO_LE: | |
| 46 | case clang::BO_GE: | |
| 47 | case clang::BO_EQ: | |
| 48 | case clang::BO_NE: | |
| 49 | case clang::BO_And: | |
| 50 | case clang::BO_Xor: | |
| 51 | case clang::BO_Or: | |
| 52 | case clang::BO_LAnd: | |
| 53 | case clang::BO_LOr: | |
| 54 | case clang::BO_Assign: | |
| 55 | case clang::BO_Comma: | |
| 56 | case clang::BO_MulAssign: | |
| 57 | case clang::BO_DivAssign: | |
| 58 | case clang::BO_RemAssign: | |
| 59 | case clang::BO_AddAssign: | |
| 60 | case clang::BO_SubAssign: | |
| 61 | case clang::BO_ShlAssign: | |
| 62 | case clang::BO_ShrAssign: | |
| 63 | case clang::BO_AndAssign: | |
| 64 | case clang::BO_XorAssign: | |
| 65 | case clang::BO_OrAssign: | |
| 66 | 66 | break; |
| 67 | 67 | } |
| 68 | 68 | } |
| ... | ... | @@ -101,23 +101,23 @@ static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAs |
| 101 | 101 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, ""); |
| 102 | 102 | static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, ""); |
| 103 | 103 | |
| 104 | // This function detects additions to the enum | |
| 105 | void zig2clang_UO(ZigClangUO op) { | |
| 104 | // Detect additions to the enum | |
| 105 | void ZigClang_detect_enum_UO(clang::UnaryOperatorKind op) { | |
| 106 | 106 | switch (op) { |
| 107 | case ZigClangUO_AddrOf: | |
| 108 | case ZigClangUO_Coawait: | |
| 109 | case ZigClangUO_Deref: | |
| 110 | case ZigClangUO_Extension: | |
| 111 | case ZigClangUO_Imag: | |
| 112 | case ZigClangUO_LNot: | |
| 113 | case ZigClangUO_Minus: | |
| 114 | case ZigClangUO_Not: | |
| 115 | case ZigClangUO_Plus: | |
| 116 | case ZigClangUO_PostDec: | |
| 117 | case ZigClangUO_PostInc: | |
| 118 | case ZigClangUO_PreDec: | |
| 119 | case ZigClangUO_PreInc: | |
| 120 | case ZigClangUO_Real: | |
| 107 | case clang::UO_AddrOf: | |
| 108 | case clang::UO_Coawait: | |
| 109 | case clang::UO_Deref: | |
| 110 | case clang::UO_Extension: | |
| 111 | case clang::UO_Imag: | |
| 112 | case clang::UO_LNot: | |
| 113 | case clang::UO_Minus: | |
| 114 | case clang::UO_Not: | |
| 115 | case clang::UO_Plus: | |
| 116 | case clang::UO_PostDec: | |
| 117 | case clang::UO_PostInc: | |
| 118 | case clang::UO_PreDec: | |
| 119 | case clang::UO_PreInc: | |
| 120 | case clang::UO_Real: | |
| 121 | 121 | break; |
| 122 | 122 | } |
| 123 | 123 | } |
| ... | ... | @@ -137,6 +137,1125 @@ static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, " |
| 137 | 137 | static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, ""); |
| 138 | 138 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, ""); |
| 139 | 139 | |
| 140 | // Detect additions to the enum | |
| 141 | void 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 | ||
| 206 | static_assert((clang::CastKind)ZigClangCK_Dependent == clang::CK_Dependent, ""); | |
| 207 | static_assert((clang::CastKind)ZigClangCK_BitCast == clang::CK_BitCast, ""); | |
| 208 | static_assert((clang::CastKind)ZigClangCK_LValueBitCast == clang::CK_LValueBitCast, ""); | |
| 209 | static_assert((clang::CastKind)ZigClangCK_LValueToRValue == clang::CK_LValueToRValue, ""); | |
| 210 | static_assert((clang::CastKind)ZigClangCK_NoOp == clang::CK_NoOp, ""); | |
| 211 | static_assert((clang::CastKind)ZigClangCK_BaseToDerived == clang::CK_BaseToDerived, ""); | |
| 212 | static_assert((clang::CastKind)ZigClangCK_DerivedToBase == clang::CK_DerivedToBase, ""); | |
| 213 | static_assert((clang::CastKind)ZigClangCK_UncheckedDerivedToBase == clang::CK_UncheckedDerivedToBase, ""); | |
| 214 | static_assert((clang::CastKind)ZigClangCK_Dynamic == clang::CK_Dynamic, ""); | |
| 215 | static_assert((clang::CastKind)ZigClangCK_ToUnion == clang::CK_ToUnion, ""); | |
| 216 | static_assert((clang::CastKind)ZigClangCK_ArrayToPointerDecay == clang::CK_ArrayToPointerDecay, ""); | |
| 217 | static_assert((clang::CastKind)ZigClangCK_FunctionToPointerDecay == clang::CK_FunctionToPointerDecay, ""); | |
| 218 | static_assert((clang::CastKind)ZigClangCK_NullToPointer == clang::CK_NullToPointer, ""); | |
| 219 | static_assert((clang::CastKind)ZigClangCK_NullToMemberPointer == clang::CK_NullToMemberPointer, ""); | |
| 220 | static_assert((clang::CastKind)ZigClangCK_BaseToDerivedMemberPointer == clang::CK_BaseToDerivedMemberPointer, ""); | |
| 221 | static_assert((clang::CastKind)ZigClangCK_DerivedToBaseMemberPointer == clang::CK_DerivedToBaseMemberPointer, ""); | |
| 222 | static_assert((clang::CastKind)ZigClangCK_MemberPointerToBoolean == clang::CK_MemberPointerToBoolean, ""); | |
| 223 | static_assert((clang::CastKind)ZigClangCK_ReinterpretMemberPointer == clang::CK_ReinterpretMemberPointer, ""); | |
| 224 | static_assert((clang::CastKind)ZigClangCK_UserDefinedConversion == clang::CK_UserDefinedConversion, ""); | |
| 225 | static_assert((clang::CastKind)ZigClangCK_ConstructorConversion == clang::CK_ConstructorConversion, ""); | |
| 226 | static_assert((clang::CastKind)ZigClangCK_IntegralToPointer == clang::CK_IntegralToPointer, ""); | |
| 227 | static_assert((clang::CastKind)ZigClangCK_PointerToIntegral == clang::CK_PointerToIntegral, ""); | |
| 228 | static_assert((clang::CastKind)ZigClangCK_PointerToBoolean == clang::CK_PointerToBoolean, ""); | |
| 229 | static_assert((clang::CastKind)ZigClangCK_ToVoid == clang::CK_ToVoid, ""); | |
| 230 | static_assert((clang::CastKind)ZigClangCK_VectorSplat == clang::CK_VectorSplat, ""); | |
| 231 | static_assert((clang::CastKind)ZigClangCK_IntegralCast == clang::CK_IntegralCast, ""); | |
| 232 | static_assert((clang::CastKind)ZigClangCK_IntegralToBoolean == clang::CK_IntegralToBoolean, ""); | |
| 233 | static_assert((clang::CastKind)ZigClangCK_IntegralToFloating == clang::CK_IntegralToFloating, ""); | |
| 234 | static_assert((clang::CastKind)ZigClangCK_FixedPointCast == clang::CK_FixedPointCast, ""); | |
| 235 | static_assert((clang::CastKind)ZigClangCK_FixedPointToBoolean == clang::CK_FixedPointToBoolean, ""); | |
| 236 | static_assert((clang::CastKind)ZigClangCK_FloatingToIntegral == clang::CK_FloatingToIntegral, ""); | |
| 237 | static_assert((clang::CastKind)ZigClangCK_FloatingToBoolean == clang::CK_FloatingToBoolean, ""); | |
| 238 | static_assert((clang::CastKind)ZigClangCK_BooleanToSignedIntegral == clang::CK_BooleanToSignedIntegral, ""); | |
| 239 | static_assert((clang::CastKind)ZigClangCK_FloatingCast == clang::CK_FloatingCast, ""); | |
| 240 | static_assert((clang::CastKind)ZigClangCK_CPointerToObjCPointerCast == clang::CK_CPointerToObjCPointerCast, ""); | |
| 241 | static_assert((clang::CastKind)ZigClangCK_BlockPointerToObjCPointerCast == clang::CK_BlockPointerToObjCPointerCast, ""); | |
| 242 | static_assert((clang::CastKind)ZigClangCK_AnyPointerToBlockPointerCast == clang::CK_AnyPointerToBlockPointerCast, ""); | |
| 243 | static_assert((clang::CastKind)ZigClangCK_ObjCObjectLValueCast == clang::CK_ObjCObjectLValueCast, ""); | |
| 244 | static_assert((clang::CastKind)ZigClangCK_FloatingRealToComplex == clang::CK_FloatingRealToComplex, ""); | |
| 245 | static_assert((clang::CastKind)ZigClangCK_FloatingComplexToReal == clang::CK_FloatingComplexToReal, ""); | |
| 246 | static_assert((clang::CastKind)ZigClangCK_FloatingComplexToBoolean == clang::CK_FloatingComplexToBoolean, ""); | |
| 247 | static_assert((clang::CastKind)ZigClangCK_FloatingComplexCast == clang::CK_FloatingComplexCast, ""); | |
| 248 | static_assert((clang::CastKind)ZigClangCK_FloatingComplexToIntegralComplex == clang::CK_FloatingComplexToIntegralComplex, ""); | |
| 249 | static_assert((clang::CastKind)ZigClangCK_IntegralRealToComplex == clang::CK_IntegralRealToComplex, ""); | |
| 250 | static_assert((clang::CastKind)ZigClangCK_IntegralComplexToReal == clang::CK_IntegralComplexToReal, ""); | |
| 251 | static_assert((clang::CastKind)ZigClangCK_IntegralComplexToBoolean == clang::CK_IntegralComplexToBoolean, ""); | |
| 252 | static_assert((clang::CastKind)ZigClangCK_IntegralComplexCast == clang::CK_IntegralComplexCast, ""); | |
| 253 | static_assert((clang::CastKind)ZigClangCK_IntegralComplexToFloatingComplex == clang::CK_IntegralComplexToFloatingComplex, ""); | |
| 254 | static_assert((clang::CastKind)ZigClangCK_ARCProduceObject == clang::CK_ARCProduceObject, ""); | |
| 255 | static_assert((clang::CastKind)ZigClangCK_ARCConsumeObject == clang::CK_ARCConsumeObject, ""); | |
| 256 | static_assert((clang::CastKind)ZigClangCK_ARCReclaimReturnedObject == clang::CK_ARCReclaimReturnedObject, ""); | |
| 257 | static_assert((clang::CastKind)ZigClangCK_ARCExtendBlockObject == clang::CK_ARCExtendBlockObject, ""); | |
| 258 | static_assert((clang::CastKind)ZigClangCK_AtomicToNonAtomic == clang::CK_AtomicToNonAtomic, ""); | |
| 259 | static_assert((clang::CastKind)ZigClangCK_NonAtomicToAtomic == clang::CK_NonAtomicToAtomic, ""); | |
| 260 | static_assert((clang::CastKind)ZigClangCK_CopyAndAutoreleaseBlockObject == clang::CK_CopyAndAutoreleaseBlockObject, ""); | |
| 261 | static_assert((clang::CastKind)ZigClangCK_BuiltinFnToFnPtr == clang::CK_BuiltinFnToFnPtr, ""); | |
| 262 | static_assert((clang::CastKind)ZigClangCK_ZeroToOCLOpaqueType == clang::CK_ZeroToOCLOpaqueType, ""); | |
| 263 | static_assert((clang::CastKind)ZigClangCK_AddressSpaceConversion == clang::CK_AddressSpaceConversion, ""); | |
| 264 | static_assert((clang::CastKind)ZigClangCK_IntToOCLSampler == clang::CK_IntToOCLSampler, ""); | |
| 265 | ||
| 266 | // Detect additions to the enum | |
| 267 | void 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 | ||
| 320 | static_assert((clang::Type::TypeClass)ZigClangType_Builtin == clang::Type::Builtin, ""); | |
| 321 | static_assert((clang::Type::TypeClass)ZigClangType_Complex == clang::Type::Complex, ""); | |
| 322 | static_assert((clang::Type::TypeClass)ZigClangType_Pointer == clang::Type::Pointer, ""); | |
| 323 | static_assert((clang::Type::TypeClass)ZigClangType_BlockPointer == clang::Type::BlockPointer, ""); | |
| 324 | static_assert((clang::Type::TypeClass)ZigClangType_LValueReference == clang::Type::LValueReference, ""); | |
| 325 | static_assert((clang::Type::TypeClass)ZigClangType_RValueReference == clang::Type::RValueReference, ""); | |
| 326 | static_assert((clang::Type::TypeClass)ZigClangType_MemberPointer == clang::Type::MemberPointer, ""); | |
| 327 | static_assert((clang::Type::TypeClass)ZigClangType_ConstantArray == clang::Type::ConstantArray, ""); | |
| 328 | static_assert((clang::Type::TypeClass)ZigClangType_IncompleteArray == clang::Type::IncompleteArray, ""); | |
| 329 | static_assert((clang::Type::TypeClass)ZigClangType_VariableArray == clang::Type::VariableArray, ""); | |
| 330 | static_assert((clang::Type::TypeClass)ZigClangType_DependentSizedArray == clang::Type::DependentSizedArray, ""); | |
| 331 | static_assert((clang::Type::TypeClass)ZigClangType_DependentSizedExtVector == clang::Type::DependentSizedExtVector, ""); | |
| 332 | static_assert((clang::Type::TypeClass)ZigClangType_DependentAddressSpace == clang::Type::DependentAddressSpace, ""); | |
| 333 | static_assert((clang::Type::TypeClass)ZigClangType_Vector == clang::Type::Vector, ""); | |
| 334 | static_assert((clang::Type::TypeClass)ZigClangType_DependentVector == clang::Type::DependentVector, ""); | |
| 335 | static_assert((clang::Type::TypeClass)ZigClangType_ExtVector == clang::Type::ExtVector, ""); | |
| 336 | static_assert((clang::Type::TypeClass)ZigClangType_FunctionProto == clang::Type::FunctionProto, ""); | |
| 337 | static_assert((clang::Type::TypeClass)ZigClangType_FunctionNoProto == clang::Type::FunctionNoProto, ""); | |
| 338 | static_assert((clang::Type::TypeClass)ZigClangType_UnresolvedUsing == clang::Type::UnresolvedUsing, ""); | |
| 339 | static_assert((clang::Type::TypeClass)ZigClangType_Paren == clang::Type::Paren, ""); | |
| 340 | static_assert((clang::Type::TypeClass)ZigClangType_Typedef == clang::Type::Typedef, ""); | |
| 341 | static_assert((clang::Type::TypeClass)ZigClangType_Adjusted == clang::Type::Adjusted, ""); | |
| 342 | static_assert((clang::Type::TypeClass)ZigClangType_Decayed == clang::Type::Decayed, ""); | |
| 343 | static_assert((clang::Type::TypeClass)ZigClangType_TypeOfExpr == clang::Type::TypeOfExpr, ""); | |
| 344 | static_assert((clang::Type::TypeClass)ZigClangType_TypeOf == clang::Type::TypeOf, ""); | |
| 345 | static_assert((clang::Type::TypeClass)ZigClangType_Decltype == clang::Type::Decltype, ""); | |
| 346 | static_assert((clang::Type::TypeClass)ZigClangType_UnaryTransform == clang::Type::UnaryTransform, ""); | |
| 347 | static_assert((clang::Type::TypeClass)ZigClangType_Record == clang::Type::Record, ""); | |
| 348 | static_assert((clang::Type::TypeClass)ZigClangType_Enum == clang::Type::Enum, ""); | |
| 349 | static_assert((clang::Type::TypeClass)ZigClangType_Elaborated == clang::Type::Elaborated, ""); | |
| 350 | static_assert((clang::Type::TypeClass)ZigClangType_Attributed == clang::Type::Attributed, ""); | |
| 351 | static_assert((clang::Type::TypeClass)ZigClangType_TemplateTypeParm == clang::Type::TemplateTypeParm, ""); | |
| 352 | static_assert((clang::Type::TypeClass)ZigClangType_SubstTemplateTypeParm == clang::Type::SubstTemplateTypeParm, ""); | |
| 353 | static_assert((clang::Type::TypeClass)ZigClangType_SubstTemplateTypeParmPack == clang::Type::SubstTemplateTypeParmPack, ""); | |
| 354 | static_assert((clang::Type::TypeClass)ZigClangType_TemplateSpecialization == clang::Type::TemplateSpecialization, ""); | |
| 355 | static_assert((clang::Type::TypeClass)ZigClangType_Auto == clang::Type::Auto, ""); | |
| 356 | static_assert((clang::Type::TypeClass)ZigClangType_DeducedTemplateSpecialization == clang::Type::DeducedTemplateSpecialization, ""); | |
| 357 | static_assert((clang::Type::TypeClass)ZigClangType_InjectedClassName == clang::Type::InjectedClassName, ""); | |
| 358 | static_assert((clang::Type::TypeClass)ZigClangType_DependentName == clang::Type::DependentName, ""); | |
| 359 | static_assert((clang::Type::TypeClass)ZigClangType_DependentTemplateSpecialization == clang::Type::DependentTemplateSpecialization, ""); | |
| 360 | static_assert((clang::Type::TypeClass)ZigClangType_PackExpansion == clang::Type::PackExpansion, ""); | |
| 361 | static_assert((clang::Type::TypeClass)ZigClangType_ObjCTypeParam == clang::Type::ObjCTypeParam, ""); | |
| 362 | static_assert((clang::Type::TypeClass)ZigClangType_ObjCObject == clang::Type::ObjCObject, ""); | |
| 363 | static_assert((clang::Type::TypeClass)ZigClangType_ObjCInterface == clang::Type::ObjCInterface, ""); | |
| 364 | static_assert((clang::Type::TypeClass)ZigClangType_ObjCObjectPointer == clang::Type::ObjCObjectPointer, ""); | |
| 365 | static_assert((clang::Type::TypeClass)ZigClangType_Pipe == clang::Type::Pipe, ""); | |
| 366 | static_assert((clang::Type::TypeClass)ZigClangType_Atomic == clang::Type::Atomic, ""); | |
| 367 | ||
| 368 | // Detect additions to the enum | |
| 369 | void 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 | ||
| 572 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_NoStmtClass == clang::Stmt::NoStmtClass, ""); | |
| 573 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_NullStmtClass == clang::Stmt::NullStmtClass, ""); | |
| 574 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CompoundStmtClass == clang::Stmt::CompoundStmtClass, ""); | |
| 575 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_LabelStmtClass == clang::Stmt::LabelStmtClass, ""); | |
| 576 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_AttributedStmtClass == clang::Stmt::AttributedStmtClass, ""); | |
| 577 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_IfStmtClass == clang::Stmt::IfStmtClass, ""); | |
| 578 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_SwitchStmtClass == clang::Stmt::SwitchStmtClass, ""); | |
| 579 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_WhileStmtClass == clang::Stmt::WhileStmtClass, ""); | |
| 580 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_DoStmtClass == clang::Stmt::DoStmtClass, ""); | |
| 581 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ForStmtClass == clang::Stmt::ForStmtClass, ""); | |
| 582 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_GotoStmtClass == clang::Stmt::GotoStmtClass, ""); | |
| 583 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_IndirectGotoStmtClass == clang::Stmt::IndirectGotoStmtClass, ""); | |
| 584 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ContinueStmtClass == clang::Stmt::ContinueStmtClass, ""); | |
| 585 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_BreakStmtClass == clang::Stmt::BreakStmtClass, ""); | |
| 586 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ReturnStmtClass == clang::Stmt::ReturnStmtClass, ""); | |
| 587 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_DeclStmtClass == clang::Stmt::DeclStmtClass, ""); | |
| 588 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CaseStmtClass == clang::Stmt::CaseStmtClass, ""); | |
| 589 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_DefaultStmtClass == clang::Stmt::DefaultStmtClass, ""); | |
| 590 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CapturedStmtClass == clang::Stmt::CapturedStmtClass, ""); | |
| 591 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_GCCAsmStmtClass == clang::Stmt::GCCAsmStmtClass, ""); | |
| 592 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSAsmStmtClass == clang::Stmt::MSAsmStmtClass, ""); | |
| 593 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtTryStmtClass == clang::Stmt::ObjCAtTryStmtClass, ""); | |
| 594 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtCatchStmtClass == clang::Stmt::ObjCAtCatchStmtClass, ""); | |
| 595 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtFinallyStmtClass == clang::Stmt::ObjCAtFinallyStmtClass, ""); | |
| 596 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtThrowStmtClass == clang::Stmt::ObjCAtThrowStmtClass, ""); | |
| 597 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAtSynchronizedStmtClass == clang::Stmt::ObjCAtSynchronizedStmtClass, ""); | |
| 598 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCForCollectionStmtClass == clang::Stmt::ObjCForCollectionStmtClass, ""); | |
| 599 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAutoreleasePoolStmtClass == clang::Stmt::ObjCAutoreleasePoolStmtClass, ""); | |
| 600 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXCatchStmtClass == clang::Stmt::CXXCatchStmtClass, ""); | |
| 601 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXTryStmtClass == clang::Stmt::CXXTryStmtClass, ""); | |
| 602 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXForRangeStmtClass == clang::Stmt::CXXForRangeStmtClass, ""); | |
| 603 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoroutineBodyStmtClass == clang::Stmt::CoroutineBodyStmtClass, ""); | |
| 604 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoreturnStmtClass == clang::Stmt::CoreturnStmtClass, ""); | |
| 605 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_PredefinedExprClass == clang::Stmt::PredefinedExprClass, ""); | |
| 606 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_DeclRefExprClass == clang::Stmt::DeclRefExprClass, ""); | |
| 607 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_IntegerLiteralClass == clang::Stmt::IntegerLiteralClass, ""); | |
| 608 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_FixedPointLiteralClass == clang::Stmt::FixedPointLiteralClass, ""); | |
| 609 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_FloatingLiteralClass == clang::Stmt::FloatingLiteralClass, ""); | |
| 610 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ImaginaryLiteralClass == clang::Stmt::ImaginaryLiteralClass, ""); | |
| 611 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_StringLiteralClass == clang::Stmt::StringLiteralClass, ""); | |
| 612 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CharacterLiteralClass == clang::Stmt::CharacterLiteralClass, ""); | |
| 613 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ParenExprClass == clang::Stmt::ParenExprClass, ""); | |
| 614 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnaryOperatorClass == clang::Stmt::UnaryOperatorClass, ""); | |
| 615 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OffsetOfExprClass == clang::Stmt::OffsetOfExprClass, ""); | |
| 616 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnaryExprOrTypeTraitExprClass == clang::Stmt::UnaryExprOrTypeTraitExprClass, ""); | |
| 617 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArraySubscriptExprClass == clang::Stmt::ArraySubscriptExprClass, ""); | |
| 618 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPArraySectionExprClass == clang::Stmt::OMPArraySectionExprClass, ""); | |
| 619 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CallExprClass == clang::Stmt::CallExprClass, ""); | |
| 620 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_MemberExprClass == clang::Stmt::MemberExprClass, ""); | |
| 621 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_BinaryOperatorClass == clang::Stmt::BinaryOperatorClass, ""); | |
| 622 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CompoundAssignOperatorClass == clang::Stmt::CompoundAssignOperatorClass, ""); | |
| 623 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ConditionalOperatorClass == clang::Stmt::ConditionalOperatorClass, ""); | |
| 624 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_BinaryConditionalOperatorClass == clang::Stmt::BinaryConditionalOperatorClass, ""); | |
| 625 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ImplicitCastExprClass == clang::Stmt::ImplicitCastExprClass, ""); | |
| 626 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CStyleCastExprClass == clang::Stmt::CStyleCastExprClass, ""); | |
| 627 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CompoundLiteralExprClass == clang::Stmt::CompoundLiteralExprClass, ""); | |
| 628 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ExtVectorElementExprClass == clang::Stmt::ExtVectorElementExprClass, ""); | |
| 629 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_InitListExprClass == clang::Stmt::InitListExprClass, ""); | |
| 630 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_DesignatedInitExprClass == clang::Stmt::DesignatedInitExprClass, ""); | |
| 631 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_DesignatedInitUpdateExprClass == clang::Stmt::DesignatedInitUpdateExprClass, ""); | |
| 632 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ImplicitValueInitExprClass == clang::Stmt::ImplicitValueInitExprClass, ""); | |
| 633 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_NoInitExprClass == clang::Stmt::NoInitExprClass, ""); | |
| 634 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArrayInitLoopExprClass == clang::Stmt::ArrayInitLoopExprClass, ""); | |
| 635 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArrayInitIndexExprClass == clang::Stmt::ArrayInitIndexExprClass, ""); | |
| 636 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ParenListExprClass == clang::Stmt::ParenListExprClass, ""); | |
| 637 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_VAArgExprClass == clang::Stmt::VAArgExprClass, ""); | |
| 638 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_GenericSelectionExprClass == clang::Stmt::GenericSelectionExprClass, ""); | |
| 639 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_PseudoObjectExprClass == clang::Stmt::PseudoObjectExprClass, ""); | |
| 640 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ConstantExprClass == clang::Stmt::ConstantExprClass, ""); | |
| 641 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_AtomicExprClass == clang::Stmt::AtomicExprClass, ""); | |
| 642 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_AddrLabelExprClass == clang::Stmt::AddrLabelExprClass, ""); | |
| 643 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_StmtExprClass == clang::Stmt::StmtExprClass, ""); | |
| 644 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ChooseExprClass == clang::Stmt::ChooseExprClass, ""); | |
| 645 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_GNUNullExprClass == clang::Stmt::GNUNullExprClass, ""); | |
| 646 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXOperatorCallExprClass == clang::Stmt::CXXOperatorCallExprClass, ""); | |
| 647 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXMemberCallExprClass == clang::Stmt::CXXMemberCallExprClass, ""); | |
| 648 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXStaticCastExprClass == clang::Stmt::CXXStaticCastExprClass, ""); | |
| 649 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDynamicCastExprClass == clang::Stmt::CXXDynamicCastExprClass, ""); | |
| 650 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXReinterpretCastExprClass == clang::Stmt::CXXReinterpretCastExprClass, ""); | |
| 651 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXConstCastExprClass == clang::Stmt::CXXConstCastExprClass, ""); | |
| 652 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXFunctionalCastExprClass == clang::Stmt::CXXFunctionalCastExprClass, ""); | |
| 653 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXTypeidExprClass == clang::Stmt::CXXTypeidExprClass, ""); | |
| 654 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_UserDefinedLiteralClass == clang::Stmt::UserDefinedLiteralClass, ""); | |
| 655 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXBoolLiteralExprClass == clang::Stmt::CXXBoolLiteralExprClass, ""); | |
| 656 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXNullPtrLiteralExprClass == clang::Stmt::CXXNullPtrLiteralExprClass, ""); | |
| 657 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXThisExprClass == clang::Stmt::CXXThisExprClass, ""); | |
| 658 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXThrowExprClass == clang::Stmt::CXXThrowExprClass, ""); | |
| 659 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDefaultArgExprClass == clang::Stmt::CXXDefaultArgExprClass, ""); | |
| 660 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDefaultInitExprClass == clang::Stmt::CXXDefaultInitExprClass, ""); | |
| 661 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXScalarValueInitExprClass == clang::Stmt::CXXScalarValueInitExprClass, ""); | |
| 662 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXStdInitializerListExprClass == clang::Stmt::CXXStdInitializerListExprClass, ""); | |
| 663 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXNewExprClass == clang::Stmt::CXXNewExprClass, ""); | |
| 664 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDeleteExprClass == clang::Stmt::CXXDeleteExprClass, ""); | |
| 665 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXPseudoDestructorExprClass == clang::Stmt::CXXPseudoDestructorExprClass, ""); | |
| 666 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_TypeTraitExprClass == clang::Stmt::TypeTraitExprClass, ""); | |
| 667 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ArrayTypeTraitExprClass == clang::Stmt::ArrayTypeTraitExprClass, ""); | |
| 668 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ExpressionTraitExprClass == clang::Stmt::ExpressionTraitExprClass, ""); | |
| 669 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_DependentScopeDeclRefExprClass == clang::Stmt::DependentScopeDeclRefExprClass, ""); | |
| 670 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXConstructExprClass == clang::Stmt::CXXConstructExprClass, ""); | |
| 671 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXInheritedCtorInitExprClass == clang::Stmt::CXXInheritedCtorInitExprClass, ""); | |
| 672 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXBindTemporaryExprClass == clang::Stmt::CXXBindTemporaryExprClass, ""); | |
| 673 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ExprWithCleanupsClass == clang::Stmt::ExprWithCleanupsClass, ""); | |
| 674 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXTemporaryObjectExprClass == clang::Stmt::CXXTemporaryObjectExprClass, ""); | |
| 675 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXUnresolvedConstructExprClass == clang::Stmt::CXXUnresolvedConstructExprClass, ""); | |
| 676 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXDependentScopeMemberExprClass == clang::Stmt::CXXDependentScopeMemberExprClass, ""); | |
| 677 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnresolvedLookupExprClass == clang::Stmt::UnresolvedLookupExprClass, ""); | |
| 678 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_UnresolvedMemberExprClass == clang::Stmt::UnresolvedMemberExprClass, ""); | |
| 679 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXNoexceptExprClass == clang::Stmt::CXXNoexceptExprClass, ""); | |
| 680 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_PackExpansionExprClass == clang::Stmt::PackExpansionExprClass, ""); | |
| 681 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_SizeOfPackExprClass == clang::Stmt::SizeOfPackExprClass, ""); | |
| 682 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_SubstNonTypeTemplateParmExprClass == clang::Stmt::SubstNonTypeTemplateParmExprClass, ""); | |
| 683 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_SubstNonTypeTemplateParmPackExprClass == clang::Stmt::SubstNonTypeTemplateParmPackExprClass, ""); | |
| 684 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_FunctionParmPackExprClass == clang::Stmt::FunctionParmPackExprClass, ""); | |
| 685 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_MaterializeTemporaryExprClass == clang::Stmt::MaterializeTemporaryExprClass, ""); | |
| 686 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_LambdaExprClass == clang::Stmt::LambdaExprClass, ""); | |
| 687 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXFoldExprClass == clang::Stmt::CXXFoldExprClass, ""); | |
| 688 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoawaitExprClass == clang::Stmt::CoawaitExprClass, ""); | |
| 689 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_DependentCoawaitExprClass == clang::Stmt::DependentCoawaitExprClass, ""); | |
| 690 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CoyieldExprClass == clang::Stmt::CoyieldExprClass, ""); | |
| 691 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCStringLiteralClass == clang::Stmt::ObjCStringLiteralClass, ""); | |
| 692 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCBoxedExprClass == clang::Stmt::ObjCBoxedExprClass, ""); | |
| 693 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCArrayLiteralClass == clang::Stmt::ObjCArrayLiteralClass, ""); | |
| 694 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCDictionaryLiteralClass == clang::Stmt::ObjCDictionaryLiteralClass, ""); | |
| 695 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCEncodeExprClass == clang::Stmt::ObjCEncodeExprClass, ""); | |
| 696 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCMessageExprClass == clang::Stmt::ObjCMessageExprClass, ""); | |
| 697 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCSelectorExprClass == clang::Stmt::ObjCSelectorExprClass, ""); | |
| 698 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCProtocolExprClass == clang::Stmt::ObjCProtocolExprClass, ""); | |
| 699 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCIvarRefExprClass == clang::Stmt::ObjCIvarRefExprClass, ""); | |
| 700 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCPropertyRefExprClass == clang::Stmt::ObjCPropertyRefExprClass, ""); | |
| 701 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCIsaExprClass == clang::Stmt::ObjCIsaExprClass, ""); | |
| 702 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCIndirectCopyRestoreExprClass == clang::Stmt::ObjCIndirectCopyRestoreExprClass, ""); | |
| 703 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCBoolLiteralExprClass == clang::Stmt::ObjCBoolLiteralExprClass, ""); | |
| 704 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCSubscriptRefExprClass == clang::Stmt::ObjCSubscriptRefExprClass, ""); | |
| 705 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCAvailabilityCheckExprClass == clang::Stmt::ObjCAvailabilityCheckExprClass, ""); | |
| 706 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ObjCBridgedCastExprClass == clang::Stmt::ObjCBridgedCastExprClass, ""); | |
| 707 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CUDAKernelCallExprClass == clang::Stmt::CUDAKernelCallExprClass, ""); | |
| 708 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ShuffleVectorExprClass == clang::Stmt::ShuffleVectorExprClass, ""); | |
| 709 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_ConvertVectorExprClass == clang::Stmt::ConvertVectorExprClass, ""); | |
| 710 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_BlockExprClass == clang::Stmt::BlockExprClass, ""); | |
| 711 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OpaqueValueExprClass == clang::Stmt::OpaqueValueExprClass, ""); | |
| 712 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_TypoExprClass == clang::Stmt::TypoExprClass, ""); | |
| 713 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSPropertyRefExprClass == clang::Stmt::MSPropertyRefExprClass, ""); | |
| 714 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSPropertySubscriptExprClass == clang::Stmt::MSPropertySubscriptExprClass, ""); | |
| 715 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_CXXUuidofExprClass == clang::Stmt::CXXUuidofExprClass, ""); | |
| 716 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHTryStmtClass == clang::Stmt::SEHTryStmtClass, ""); | |
| 717 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHExceptStmtClass == clang::Stmt::SEHExceptStmtClass, ""); | |
| 718 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHFinallyStmtClass == clang::Stmt::SEHFinallyStmtClass, ""); | |
| 719 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_SEHLeaveStmtClass == clang::Stmt::SEHLeaveStmtClass, ""); | |
| 720 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_MSDependentExistsStmtClass == clang::Stmt::MSDependentExistsStmtClass, ""); | |
| 721 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_AsTypeExprClass == clang::Stmt::AsTypeExprClass, ""); | |
| 722 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelDirectiveClass == clang::Stmt::OMPParallelDirectiveClass, ""); | |
| 723 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSimdDirectiveClass == clang::Stmt::OMPSimdDirectiveClass, ""); | |
| 724 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPForDirectiveClass == clang::Stmt::OMPForDirectiveClass, ""); | |
| 725 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPForSimdDirectiveClass == clang::Stmt::OMPForSimdDirectiveClass, ""); | |
| 726 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSectionsDirectiveClass == clang::Stmt::OMPSectionsDirectiveClass, ""); | |
| 727 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSectionDirectiveClass == clang::Stmt::OMPSectionDirectiveClass, ""); | |
| 728 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSingleDirectiveClass == clang::Stmt::OMPSingleDirectiveClass, ""); | |
| 729 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMasterDirectiveClass == clang::Stmt::OMPMasterDirectiveClass, ""); | |
| 730 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPCriticalDirectiveClass == clang::Stmt::OMPCriticalDirectiveClass, ""); | |
| 731 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelForDirectiveClass == clang::Stmt::OMPParallelForDirectiveClass, ""); | |
| 732 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelForSimdDirectiveClass == clang::Stmt::OMPParallelForSimdDirectiveClass, ""); | |
| 733 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelSectionsDirectiveClass == clang::Stmt::OMPParallelSectionsDirectiveClass, ""); | |
| 734 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskDirectiveClass == clang::Stmt::OMPTaskDirectiveClass, ""); | |
| 735 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskyieldDirectiveClass == clang::Stmt::OMPTaskyieldDirectiveClass, ""); | |
| 736 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPBarrierDirectiveClass == clang::Stmt::OMPBarrierDirectiveClass, ""); | |
| 737 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskwaitDirectiveClass == clang::Stmt::OMPTaskwaitDirectiveClass, ""); | |
| 738 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskgroupDirectiveClass == clang::Stmt::OMPTaskgroupDirectiveClass, ""); | |
| 739 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPFlushDirectiveClass == clang::Stmt::OMPFlushDirectiveClass, ""); | |
| 740 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPOrderedDirectiveClass == clang::Stmt::OMPOrderedDirectiveClass, ""); | |
| 741 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPAtomicDirectiveClass == clang::Stmt::OMPAtomicDirectiveClass, ""); | |
| 742 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetDirectiveClass == clang::Stmt::OMPTargetDirectiveClass, ""); | |
| 743 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetDataDirectiveClass == clang::Stmt::OMPTargetDataDirectiveClass, ""); | |
| 744 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetEnterDataDirectiveClass == clang::Stmt::OMPTargetEnterDataDirectiveClass, ""); | |
| 745 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetExitDataDirectiveClass == clang::Stmt::OMPTargetExitDataDirectiveClass, ""); | |
| 746 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelDirectiveClass == clang::Stmt::OMPTargetParallelDirectiveClass, ""); | |
| 747 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelForDirectiveClass == clang::Stmt::OMPTargetParallelForDirectiveClass, ""); | |
| 748 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetUpdateDirectiveClass == clang::Stmt::OMPTargetUpdateDirectiveClass, ""); | |
| 749 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDirectiveClass == clang::Stmt::OMPTeamsDirectiveClass, ""); | |
| 750 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPCancellationPointDirectiveClass == clang::Stmt::OMPCancellationPointDirectiveClass, ""); | |
| 751 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPCancelDirectiveClass == clang::Stmt::OMPCancelDirectiveClass, ""); | |
| 752 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskLoopDirectiveClass == clang::Stmt::OMPTaskLoopDirectiveClass, ""); | |
| 753 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskLoopSimdDirectiveClass == clang::Stmt::OMPTaskLoopSimdDirectiveClass, ""); | |
| 754 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeDirectiveClass == clang::Stmt::OMPDistributeDirectiveClass, ""); | |
| 755 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeParallelForDirectiveClass == clang::Stmt::OMPDistributeParallelForDirectiveClass, ""); | |
| 756 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPDistributeParallelForSimdDirectiveClass, ""); | |
| 757 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeSimdDirectiveClass == clang::Stmt::OMPDistributeSimdDirectiveClass, ""); | |
| 758 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelForSimdDirectiveClass == clang::Stmt::OMPTargetParallelForSimdDirectiveClass, ""); | |
| 759 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetSimdDirectiveClass == clang::Stmt::OMPTargetSimdDirectiveClass, ""); | |
| 760 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeDirectiveClass == clang::Stmt::OMPTeamsDistributeDirectiveClass, ""); | |
| 761 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass == clang::Stmt::OMPTeamsDistributeSimdDirectiveClass, ""); | |
| 762 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass, ""); | |
| 763 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass == clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass, ""); | |
| 764 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDirectiveClass == clang::Stmt::OMPTargetTeamsDirectiveClass, ""); | |
| 765 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeDirectiveClass, ""); | |
| 766 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass, ""); | |
| 767 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass, ""); | |
| 768 | static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass, ""); | |
| 769 | ||
| 770 | void 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 | ||
| 788 | static_assert((clang::APValue::ValueKind)ZigClangAPValueUninitialized == clang::APValue::Uninitialized, ""); | |
| 789 | static_assert((clang::APValue::ValueKind)ZigClangAPValueInt == clang::APValue::Int, ""); | |
| 790 | static_assert((clang::APValue::ValueKind)ZigClangAPValueFloat == clang::APValue::Float, ""); | |
| 791 | static_assert((clang::APValue::ValueKind)ZigClangAPValueComplexInt == clang::APValue::ComplexInt, ""); | |
| 792 | static_assert((clang::APValue::ValueKind)ZigClangAPValueComplexFloat == clang::APValue::ComplexFloat, ""); | |
| 793 | static_assert((clang::APValue::ValueKind)ZigClangAPValueLValue == clang::APValue::LValue, ""); | |
| 794 | static_assert((clang::APValue::ValueKind)ZigClangAPValueVector == clang::APValue::Vector, ""); | |
| 795 | static_assert((clang::APValue::ValueKind)ZigClangAPValueArray == clang::APValue::Array, ""); | |
| 796 | static_assert((clang::APValue::ValueKind)ZigClangAPValueStruct == clang::APValue::Struct, ""); | |
| 797 | static_assert((clang::APValue::ValueKind)ZigClangAPValueUnion == clang::APValue::Union, ""); | |
| 798 | static_assert((clang::APValue::ValueKind)ZigClangAPValueMemberPointer == clang::APValue::MemberPointer, ""); | |
| 799 | static_assert((clang::APValue::ValueKind)ZigClangAPValueAddrLabelDiff == clang::APValue::AddrLabelDiff, ""); | |
| 800 | ||
| 801 | ||
| 802 | void 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 | ||
| 882 | static_assert((clang::Decl::Kind)ZigClangDeclAccessSpec == clang::Decl::AccessSpec, ""); | |
| 883 | static_assert((clang::Decl::Kind)ZigClangDeclBlock == clang::Decl::Block, ""); | |
| 884 | static_assert((clang::Decl::Kind)ZigClangDeclCaptured == clang::Decl::Captured, ""); | |
| 885 | static_assert((clang::Decl::Kind)ZigClangDeclClassScopeFunctionSpecialization == clang::Decl::ClassScopeFunctionSpecialization, ""); | |
| 886 | static_assert((clang::Decl::Kind)ZigClangDeclEmpty == clang::Decl::Empty, ""); | |
| 887 | static_assert((clang::Decl::Kind)ZigClangDeclExport == clang::Decl::Export, ""); | |
| 888 | static_assert((clang::Decl::Kind)ZigClangDeclExternCContext == clang::Decl::ExternCContext, ""); | |
| 889 | static_assert((clang::Decl::Kind)ZigClangDeclFileScopeAsm == clang::Decl::FileScopeAsm, ""); | |
| 890 | static_assert((clang::Decl::Kind)ZigClangDeclFriend == clang::Decl::Friend, ""); | |
| 891 | static_assert((clang::Decl::Kind)ZigClangDeclFriendTemplate == clang::Decl::FriendTemplate, ""); | |
| 892 | static_assert((clang::Decl::Kind)ZigClangDeclImport == clang::Decl::Import, ""); | |
| 893 | static_assert((clang::Decl::Kind)ZigClangDeclLinkageSpec == clang::Decl::LinkageSpec, ""); | |
| 894 | static_assert((clang::Decl::Kind)ZigClangDeclLabel == clang::Decl::Label, ""); | |
| 895 | static_assert((clang::Decl::Kind)ZigClangDeclNamespace == clang::Decl::Namespace, ""); | |
| 896 | static_assert((clang::Decl::Kind)ZigClangDeclNamespaceAlias == clang::Decl::NamespaceAlias, ""); | |
| 897 | static_assert((clang::Decl::Kind)ZigClangDeclObjCCompatibleAlias == clang::Decl::ObjCCompatibleAlias, ""); | |
| 898 | static_assert((clang::Decl::Kind)ZigClangDeclObjCCategory == clang::Decl::ObjCCategory, ""); | |
| 899 | static_assert((clang::Decl::Kind)ZigClangDeclObjCCategoryImpl == clang::Decl::ObjCCategoryImpl, ""); | |
| 900 | static_assert((clang::Decl::Kind)ZigClangDeclObjCImplementation == clang::Decl::ObjCImplementation, ""); | |
| 901 | static_assert((clang::Decl::Kind)ZigClangDeclObjCInterface == clang::Decl::ObjCInterface, ""); | |
| 902 | static_assert((clang::Decl::Kind)ZigClangDeclObjCProtocol == clang::Decl::ObjCProtocol, ""); | |
| 903 | static_assert((clang::Decl::Kind)ZigClangDeclObjCMethod == clang::Decl::ObjCMethod, ""); | |
| 904 | static_assert((clang::Decl::Kind)ZigClangDeclObjCProperty == clang::Decl::ObjCProperty, ""); | |
| 905 | static_assert((clang::Decl::Kind)ZigClangDeclBuiltinTemplate == clang::Decl::BuiltinTemplate, ""); | |
| 906 | static_assert((clang::Decl::Kind)ZigClangDeclClassTemplate == clang::Decl::ClassTemplate, ""); | |
| 907 | static_assert((clang::Decl::Kind)ZigClangDeclFunctionTemplate == clang::Decl::FunctionTemplate, ""); | |
| 908 | static_assert((clang::Decl::Kind)ZigClangDeclTypeAliasTemplate == clang::Decl::TypeAliasTemplate, ""); | |
| 909 | static_assert((clang::Decl::Kind)ZigClangDeclVarTemplate == clang::Decl::VarTemplate, ""); | |
| 910 | static_assert((clang::Decl::Kind)ZigClangDeclTemplateTemplateParm == clang::Decl::TemplateTemplateParm, ""); | |
| 911 | static_assert((clang::Decl::Kind)ZigClangDeclEnum == clang::Decl::Enum, ""); | |
| 912 | static_assert((clang::Decl::Kind)ZigClangDeclRecord == clang::Decl::Record, ""); | |
| 913 | static_assert((clang::Decl::Kind)ZigClangDeclCXXRecord == clang::Decl::CXXRecord, ""); | |
| 914 | static_assert((clang::Decl::Kind)ZigClangDeclClassTemplateSpecialization == clang::Decl::ClassTemplateSpecialization, ""); | |
| 915 | static_assert((clang::Decl::Kind)ZigClangDeclClassTemplatePartialSpecialization == clang::Decl::ClassTemplatePartialSpecialization, ""); | |
| 916 | static_assert((clang::Decl::Kind)ZigClangDeclTemplateTypeParm == clang::Decl::TemplateTypeParm, ""); | |
| 917 | static_assert((clang::Decl::Kind)ZigClangDeclObjCTypeParam == clang::Decl::ObjCTypeParam, ""); | |
| 918 | static_assert((clang::Decl::Kind)ZigClangDeclTypeAlias == clang::Decl::TypeAlias, ""); | |
| 919 | static_assert((clang::Decl::Kind)ZigClangDeclTypedef == clang::Decl::Typedef, ""); | |
| 920 | static_assert((clang::Decl::Kind)ZigClangDeclUnresolvedUsingTypename == clang::Decl::UnresolvedUsingTypename, ""); | |
| 921 | static_assert((clang::Decl::Kind)ZigClangDeclUsing == clang::Decl::Using, ""); | |
| 922 | static_assert((clang::Decl::Kind)ZigClangDeclUsingDirective == clang::Decl::UsingDirective, ""); | |
| 923 | static_assert((clang::Decl::Kind)ZigClangDeclUsingPack == clang::Decl::UsingPack, ""); | |
| 924 | static_assert((clang::Decl::Kind)ZigClangDeclUsingShadow == clang::Decl::UsingShadow, ""); | |
| 925 | static_assert((clang::Decl::Kind)ZigClangDeclConstructorUsingShadow == clang::Decl::ConstructorUsingShadow, ""); | |
| 926 | static_assert((clang::Decl::Kind)ZigClangDeclBinding == clang::Decl::Binding, ""); | |
| 927 | static_assert((clang::Decl::Kind)ZigClangDeclField == clang::Decl::Field, ""); | |
| 928 | static_assert((clang::Decl::Kind)ZigClangDeclObjCAtDefsField == clang::Decl::ObjCAtDefsField, ""); | |
| 929 | static_assert((clang::Decl::Kind)ZigClangDeclObjCIvar == clang::Decl::ObjCIvar, ""); | |
| 930 | static_assert((clang::Decl::Kind)ZigClangDeclFunction == clang::Decl::Function, ""); | |
| 931 | static_assert((clang::Decl::Kind)ZigClangDeclCXXDeductionGuide == clang::Decl::CXXDeductionGuide, ""); | |
| 932 | static_assert((clang::Decl::Kind)ZigClangDeclCXXMethod == clang::Decl::CXXMethod, ""); | |
| 933 | static_assert((clang::Decl::Kind)ZigClangDeclCXXConstructor == clang::Decl::CXXConstructor, ""); | |
| 934 | static_assert((clang::Decl::Kind)ZigClangDeclCXXConversion == clang::Decl::CXXConversion, ""); | |
| 935 | static_assert((clang::Decl::Kind)ZigClangDeclCXXDestructor == clang::Decl::CXXDestructor, ""); | |
| 936 | static_assert((clang::Decl::Kind)ZigClangDeclMSProperty == clang::Decl::MSProperty, ""); | |
| 937 | static_assert((clang::Decl::Kind)ZigClangDeclNonTypeTemplateParm == clang::Decl::NonTypeTemplateParm, ""); | |
| 938 | static_assert((clang::Decl::Kind)ZigClangDeclVar == clang::Decl::Var, ""); | |
| 939 | static_assert((clang::Decl::Kind)ZigClangDeclDecomposition == clang::Decl::Decomposition, ""); | |
| 940 | static_assert((clang::Decl::Kind)ZigClangDeclImplicitParam == clang::Decl::ImplicitParam, ""); | |
| 941 | static_assert((clang::Decl::Kind)ZigClangDeclOMPCapturedExpr == clang::Decl::OMPCapturedExpr, ""); | |
| 942 | static_assert((clang::Decl::Kind)ZigClangDeclParmVar == clang::Decl::ParmVar, ""); | |
| 943 | static_assert((clang::Decl::Kind)ZigClangDeclVarTemplateSpecialization == clang::Decl::VarTemplateSpecialization, ""); | |
| 944 | static_assert((clang::Decl::Kind)ZigClangDeclVarTemplatePartialSpecialization == clang::Decl::VarTemplatePartialSpecialization, ""); | |
| 945 | static_assert((clang::Decl::Kind)ZigClangDeclEnumConstant == clang::Decl::EnumConstant, ""); | |
| 946 | static_assert((clang::Decl::Kind)ZigClangDeclIndirectField == clang::Decl::IndirectField, ""); | |
| 947 | static_assert((clang::Decl::Kind)ZigClangDeclOMPDeclareReduction == clang::Decl::OMPDeclareReduction, ""); | |
| 948 | static_assert((clang::Decl::Kind)ZigClangDeclUnresolvedUsingValue == clang::Decl::UnresolvedUsingValue, ""); | |
| 949 | static_assert((clang::Decl::Kind)ZigClangDeclOMPRequires == clang::Decl::OMPRequires, ""); | |
| 950 | static_assert((clang::Decl::Kind)ZigClangDeclOMPThreadPrivate == clang::Decl::OMPThreadPrivate, ""); | |
| 951 | static_assert((clang::Decl::Kind)ZigClangDeclObjCPropertyImpl == clang::Decl::ObjCPropertyImpl, ""); | |
| 952 | static_assert((clang::Decl::Kind)ZigClangDeclPragmaComment == clang::Decl::PragmaComment, ""); | |
| 953 | static_assert((clang::Decl::Kind)ZigClangDeclPragmaDetectMismatch == clang::Decl::PragmaDetectMismatch, ""); | |
| 954 | static_assert((clang::Decl::Kind)ZigClangDeclStaticAssert == clang::Decl::StaticAssert, ""); | |
| 955 | static_assert((clang::Decl::Kind)ZigClangDeclTranslationUnit == clang::Decl::TranslationUnit, ""); | |
| 956 | ||
| 957 | void 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 | ||
| 1079 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dRO == clang::BuiltinType::OCLImage1dRO, ""); | |
| 1080 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dArrayRO == clang::BuiltinType::OCLImage1dArrayRO, ""); | |
| 1081 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dBufferRO == clang::BuiltinType::OCLImage1dBufferRO, ""); | |
| 1082 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dRO == clang::BuiltinType::OCLImage2dRO, ""); | |
| 1083 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayRO == clang::BuiltinType::OCLImage2dArrayRO, ""); | |
| 1084 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dDepthRO == clang::BuiltinType::OCLImage2dDepthRO, ""); | |
| 1085 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayDepthRO == clang::BuiltinType::OCLImage2dArrayDepthRO, ""); | |
| 1086 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAARO == clang::BuiltinType::OCLImage2dMSAARO, ""); | |
| 1087 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAARO == clang::BuiltinType::OCLImage2dArrayMSAARO, ""); | |
| 1088 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAADepthRO == clang::BuiltinType::OCLImage2dMSAADepthRO, ""); | |
| 1089 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO == clang::BuiltinType::OCLImage2dArrayMSAADepthRO, ""); | |
| 1090 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage3dRO == clang::BuiltinType::OCLImage3dRO, ""); | |
| 1091 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dWO == clang::BuiltinType::OCLImage1dWO, ""); | |
| 1092 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dArrayWO == clang::BuiltinType::OCLImage1dArrayWO, ""); | |
| 1093 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dBufferWO == clang::BuiltinType::OCLImage1dBufferWO, ""); | |
| 1094 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dWO == clang::BuiltinType::OCLImage2dWO, ""); | |
| 1095 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayWO == clang::BuiltinType::OCLImage2dArrayWO, ""); | |
| 1096 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dDepthWO == clang::BuiltinType::OCLImage2dDepthWO, ""); | |
| 1097 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayDepthWO == clang::BuiltinType::OCLImage2dArrayDepthWO, ""); | |
| 1098 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAAWO == clang::BuiltinType::OCLImage2dMSAAWO, ""); | |
| 1099 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAAWO == clang::BuiltinType::OCLImage2dArrayMSAAWO, ""); | |
| 1100 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAADepthWO == clang::BuiltinType::OCLImage2dMSAADepthWO, ""); | |
| 1101 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO == clang::BuiltinType::OCLImage2dArrayMSAADepthWO, ""); | |
| 1102 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage3dWO == clang::BuiltinType::OCLImage3dWO, ""); | |
| 1103 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dRW == clang::BuiltinType::OCLImage1dRW, ""); | |
| 1104 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dArrayRW == clang::BuiltinType::OCLImage1dArrayRW, ""); | |
| 1105 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage1dBufferRW == clang::BuiltinType::OCLImage1dBufferRW, ""); | |
| 1106 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dRW == clang::BuiltinType::OCLImage2dRW, ""); | |
| 1107 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayRW == clang::BuiltinType::OCLImage2dArrayRW, ""); | |
| 1108 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dDepthRW == clang::BuiltinType::OCLImage2dDepthRW, ""); | |
| 1109 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayDepthRW == clang::BuiltinType::OCLImage2dArrayDepthRW, ""); | |
| 1110 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAARW == clang::BuiltinType::OCLImage2dMSAARW, ""); | |
| 1111 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAARW == clang::BuiltinType::OCLImage2dArrayMSAARW, ""); | |
| 1112 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dMSAADepthRW == clang::BuiltinType::OCLImage2dMSAADepthRW, ""); | |
| 1113 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW == clang::BuiltinType::OCLImage2dArrayMSAADepthRW, ""); | |
| 1114 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLImage3dRW == clang::BuiltinType::OCLImage3dRW, ""); | |
| 1115 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload == clang::BuiltinType::OCLIntelSubgroupAVCMcePayload, ""); | |
| 1116 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload == clang::BuiltinType::OCLIntelSubgroupAVCImePayload, ""); | |
| 1117 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload == clang::BuiltinType::OCLIntelSubgroupAVCRefPayload, ""); | |
| 1118 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload == clang::BuiltinType::OCLIntelSubgroupAVCSicPayload, ""); | |
| 1119 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult == clang::BuiltinType::OCLIntelSubgroupAVCMceResult, ""); | |
| 1120 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult == clang::BuiltinType::OCLIntelSubgroupAVCImeResult, ""); | |
| 1121 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult == clang::BuiltinType::OCLIntelSubgroupAVCRefResult, ""); | |
| 1122 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult == clang::BuiltinType::OCLIntelSubgroupAVCSicResult, ""); | |
| 1123 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout == clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout, ""); | |
| 1124 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout == clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout, ""); | |
| 1125 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin == clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin, ""); | |
| 1126 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin == clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin, ""); | |
| 1127 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeVoid == clang::BuiltinType::Void, ""); | |
| 1128 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeBool == clang::BuiltinType::Bool, ""); | |
| 1129 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar_U == clang::BuiltinType::Char_U, ""); | |
| 1130 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUChar == clang::BuiltinType::UChar, ""); | |
| 1131 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeWChar_U == clang::BuiltinType::WChar_U, ""); | |
| 1132 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar8 == clang::BuiltinType::Char8, ""); | |
| 1133 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar16 == clang::BuiltinType::Char16, ""); | |
| 1134 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar32 == clang::BuiltinType::Char32, ""); | |
| 1135 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUShort == clang::BuiltinType::UShort, ""); | |
| 1136 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUInt == clang::BuiltinType::UInt, ""); | |
| 1137 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULong == clang::BuiltinType::ULong, ""); | |
| 1138 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULongLong == clang::BuiltinType::ULongLong, ""); | |
| 1139 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUInt128 == clang::BuiltinType::UInt128, ""); | |
| 1140 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeChar_S == clang::BuiltinType::Char_S, ""); | |
| 1141 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSChar == clang::BuiltinType::SChar, ""); | |
| 1142 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeWChar_S == clang::BuiltinType::WChar_S, ""); | |
| 1143 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeShort == clang::BuiltinType::Short, ""); | |
| 1144 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeInt == clang::BuiltinType::Int, ""); | |
| 1145 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLong == clang::BuiltinType::Long, ""); | |
| 1146 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongLong == clang::BuiltinType::LongLong, ""); | |
| 1147 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeInt128 == clang::BuiltinType::Int128, ""); | |
| 1148 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeShortAccum == clang::BuiltinType::ShortAccum, ""); | |
| 1149 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeAccum == clang::BuiltinType::Accum, ""); | |
| 1150 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongAccum == clang::BuiltinType::LongAccum, ""); | |
| 1151 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUShortAccum == clang::BuiltinType::UShortAccum, ""); | |
| 1152 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUAccum == clang::BuiltinType::UAccum, ""); | |
| 1153 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULongAccum == clang::BuiltinType::ULongAccum, ""); | |
| 1154 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeShortFract == clang::BuiltinType::ShortFract, ""); | |
| 1155 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFract == clang::BuiltinType::Fract, ""); | |
| 1156 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongFract == clang::BuiltinType::LongFract, ""); | |
| 1157 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUShortFract == clang::BuiltinType::UShortFract, ""); | |
| 1158 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUFract == clang::BuiltinType::UFract, ""); | |
| 1159 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeULongFract == clang::BuiltinType::ULongFract, ""); | |
| 1160 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatShortAccum == clang::BuiltinType::SatShortAccum, ""); | |
| 1161 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatAccum == clang::BuiltinType::SatAccum, ""); | |
| 1162 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatLongAccum == clang::BuiltinType::SatLongAccum, ""); | |
| 1163 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUShortAccum == clang::BuiltinType::SatUShortAccum, ""); | |
| 1164 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUAccum == clang::BuiltinType::SatUAccum, ""); | |
| 1165 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatULongAccum == clang::BuiltinType::SatULongAccum, ""); | |
| 1166 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatShortFract == clang::BuiltinType::SatShortFract, ""); | |
| 1167 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatFract == clang::BuiltinType::SatFract, ""); | |
| 1168 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatLongFract == clang::BuiltinType::SatLongFract, ""); | |
| 1169 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUShortFract == clang::BuiltinType::SatUShortFract, ""); | |
| 1170 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatUFract == clang::BuiltinType::SatUFract, ""); | |
| 1171 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeSatULongFract == clang::BuiltinType::SatULongFract, ""); | |
| 1172 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeHalf == clang::BuiltinType::Half, ""); | |
| 1173 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFloat == clang::BuiltinType::Float, ""); | |
| 1174 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeDouble == clang::BuiltinType::Double, ""); | |
| 1175 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeLongDouble == clang::BuiltinType::LongDouble, ""); | |
| 1176 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFloat16 == clang::BuiltinType::Float16, ""); | |
| 1177 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeFloat128 == clang::BuiltinType::Float128, ""); | |
| 1178 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeNullPtr == clang::BuiltinType::NullPtr, ""); | |
| 1179 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeObjCId == clang::BuiltinType::ObjCId, ""); | |
| 1180 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeObjCClass == clang::BuiltinType::ObjCClass, ""); | |
| 1181 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeObjCSel == clang::BuiltinType::ObjCSel, ""); | |
| 1182 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLSampler == clang::BuiltinType::OCLSampler, ""); | |
| 1183 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLEvent == clang::BuiltinType::OCLEvent, ""); | |
| 1184 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLClkEvent == clang::BuiltinType::OCLClkEvent, ""); | |
| 1185 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLQueue == clang::BuiltinType::OCLQueue, ""); | |
| 1186 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOCLReserveID == clang::BuiltinType::OCLReserveID, ""); | |
| 1187 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeDependent == clang::BuiltinType::Dependent, ""); | |
| 1188 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOverload == clang::BuiltinType::Overload, ""); | |
| 1189 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeBoundMember == clang::BuiltinType::BoundMember, ""); | |
| 1190 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypePseudoObject == clang::BuiltinType::PseudoObject, ""); | |
| 1191 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeUnknownAny == clang::BuiltinType::UnknownAny, ""); | |
| 1192 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeBuiltinFn == clang::BuiltinType::BuiltinFn, ""); | |
| 1193 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeARCUnbridgedCast == clang::BuiltinType::ARCUnbridgedCast, ""); | |
| 1194 | static_assert((clang::BuiltinType::Kind)ZigClangBuiltinTypeOMPArraySection == clang::BuiltinType::OMPArraySection, ""); | |
| 1195 | ||
| 1196 | void 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 | ||
| 1220 | static_assert((clang::CallingConv)ZigClangCallingConv_C == clang::CC_C, ""); | |
| 1221 | static_assert((clang::CallingConv)ZigClangCallingConv_X86StdCall == clang::CC_X86StdCall, ""); | |
| 1222 | static_assert((clang::CallingConv)ZigClangCallingConv_X86FastCall == clang::CC_X86FastCall, ""); | |
| 1223 | static_assert((clang::CallingConv)ZigClangCallingConv_X86ThisCall == clang::CC_X86ThisCall, ""); | |
| 1224 | static_assert((clang::CallingConv)ZigClangCallingConv_X86VectorCall == clang::CC_X86VectorCall, ""); | |
| 1225 | static_assert((clang::CallingConv)ZigClangCallingConv_X86Pascal == clang::CC_X86Pascal, ""); | |
| 1226 | static_assert((clang::CallingConv)ZigClangCallingConv_Win64 == clang::CC_Win64, ""); | |
| 1227 | static_assert((clang::CallingConv)ZigClangCallingConv_X86_64SysV == clang::CC_X86_64SysV, ""); | |
| 1228 | static_assert((clang::CallingConv)ZigClangCallingConv_X86RegCall == clang::CC_X86RegCall, ""); | |
| 1229 | static_assert((clang::CallingConv)ZigClangCallingConv_AAPCS == clang::CC_AAPCS, ""); | |
| 1230 | static_assert((clang::CallingConv)ZigClangCallingConv_AAPCS_VFP == clang::CC_AAPCS_VFP, ""); | |
| 1231 | static_assert((clang::CallingConv)ZigClangCallingConv_IntelOclBicc == clang::CC_IntelOclBicc, ""); | |
| 1232 | static_assert((clang::CallingConv)ZigClangCallingConv_SpirFunction == clang::CC_SpirFunction, ""); | |
| 1233 | static_assert((clang::CallingConv)ZigClangCallingConv_OpenCLKernel == clang::CC_OpenCLKernel, ""); | |
| 1234 | static_assert((clang::CallingConv)ZigClangCallingConv_Swift == clang::CC_Swift, ""); | |
| 1235 | static_assert((clang::CallingConv)ZigClangCallingConv_PreserveMost == clang::CC_PreserveMost, ""); | |
| 1236 | static_assert((clang::CallingConv)ZigClangCallingConv_PreserveAll == clang::CC_PreserveAll, ""); | |
| 1237 | static_assert((clang::CallingConv)ZigClangCallingConv_AArch64VectorCall == clang::CC_AArch64VectorCall, ""); | |
| 1238 | ||
| 1239 | void 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 | ||
| 1251 | static_assert((clang::StorageClass)ZigClangStorageClass_None == clang::SC_None, ""); | |
| 1252 | static_assert((clang::StorageClass)ZigClangStorageClass_Extern == clang::SC_Extern, ""); | |
| 1253 | static_assert((clang::StorageClass)ZigClangStorageClass_Static == clang::SC_Static, ""); | |
| 1254 | static_assert((clang::StorageClass)ZigClangStorageClass_PrivateExtern == clang::SC_PrivateExtern, ""); | |
| 1255 | static_assert((clang::StorageClass)ZigClangStorageClass_Auto == clang::SC_Auto, ""); | |
| 1256 | static_assert((clang::StorageClass)ZigClangStorageClass_Register == clang::SC_Register, ""); | |
| 1257 | ||
| 1258 | ||
| 140 | 1259 | static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), ""); |
| 141 | 1260 | static ZigClangSourceLocation bitcast(clang::SourceLocation src) { |
| 142 | 1261 | ZigClangSourceLocation dest; |
| ... | ... | @@ -161,6 +1280,26 @@ static clang::QualType bitcast(ZigClangQualType src) { |
| 161 | 1280 | return dest; |
| 162 | 1281 | } |
| 163 | 1282 | |
| 1283 | static_assert(sizeof(ZigClangAPValueLValueBase) == sizeof(clang::APValue::LValueBase), ""); | |
| 1284 | static ZigClangAPValueLValueBase bitcast(clang::APValue::LValueBase src) { | |
| 1285 | ZigClangAPValueLValueBase dest; | |
| 1286 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangAPValueLValueBase)); | |
| 1287 | return dest; | |
| 1288 | } | |
| 1289 | static 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 | ||
| 1295 | static_assert(sizeof(ZigClangCompoundStmt_const_body_iterator) == sizeof(clang::CompoundStmt::const_body_iterator), ""); | |
| 1296 | static 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 | ||
| 164 | 1303 | ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self, |
| 165 | 1304 | ZigClangSourceLocation Loc) |
| 166 | 1305 | { |
| ... | ... | @@ -196,6 +1335,10 @@ ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* sel |
| 196 | 1335 | return bitcast(reinterpret_cast<const clang::ASTContext *>(self)->getPointerType(bitcast(T))); |
| 197 | 1336 | } |
| 198 | 1337 | |
| 1338 | unsigned ZigClangASTContext_getTypeAlign(const ZigClangASTContext* self, ZigClangQualType T) { | |
| 1339 | return reinterpret_cast<const clang::ASTContext *>(self)->getTypeAlign(bitcast(T)); | |
| 1340 | } | |
| 1341 | ||
| 199 | 1342 | ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) { |
| 200 | 1343 | clang::ASTContext *result = &reinterpret_cast<clang::ASTUnit *>(self)->getASTContext(); |
| 201 | 1344 | return reinterpret_cast<ZigClangASTContext *>(result); |
| ... | ... | @@ -212,3 +1355,477 @@ bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *contex |
| 212 | 1355 | return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context, |
| 213 | 1356 | reinterpret_cast<bool (*)(void *, const clang::Decl *)>(Fn)); |
| 214 | 1357 | } |
| 1358 | ||
| 1359 | const 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 | ||
| 1364 | const 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 | ||
| 1369 | const 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 | ||
| 1374 | const 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 | ||
| 1379 | const 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 | ||
| 1384 | const 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 | ||
| 1390 | const 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 | ||
| 1396 | bool ZigClangRecordDecl_isUnion(const ZigClangRecordDecl *record_decl) { | |
| 1397 | return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isUnion(); | |
| 1398 | } | |
| 1399 | ||
| 1400 | bool ZigClangRecordDecl_isStruct(const ZigClangRecordDecl *record_decl) { | |
| 1401 | return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isStruct(); | |
| 1402 | } | |
| 1403 | ||
| 1404 | bool ZigClangRecordDecl_isAnonymousStructOrUnion(const ZigClangRecordDecl *record_decl) { | |
| 1405 | return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isAnonymousStructOrUnion(); | |
| 1406 | } | |
| 1407 | ||
| 1408 | const 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 | ||
| 1414 | ZigClangDeclKind ZigClangDecl_getKind(const struct ZigClangDecl *self) { | |
| 1415 | auto casted = reinterpret_cast<const clang::Decl *>(self); | |
| 1416 | return (ZigClangDeclKind)casted->getKind(); | |
| 1417 | } | |
| 1418 | ||
| 1419 | const char *ZigClangDecl_getDeclKindName(const struct ZigClangDecl *self) { | |
| 1420 | auto casted = reinterpret_cast<const clang::Decl *>(self); | |
| 1421 | return casted->getDeclKindName(); | |
| 1422 | } | |
| 1423 | ||
| 1424 | ZigClangSourceLocation 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 | ||
| 1429 | ZigClangSourceLocation ZigClangEnumDecl_getLocation(const ZigClangEnumDecl *self) { | |
| 1430 | auto casted = reinterpret_cast<const clang::EnumDecl *>(self); | |
| 1431 | return bitcast(casted->getLocation()); | |
| 1432 | } | |
| 1433 | ||
| 1434 | ZigClangSourceLocation ZigClangTypedefNameDecl_getLocation(const ZigClangTypedefNameDecl *self) { | |
| 1435 | auto casted = reinterpret_cast<const clang::TypedefNameDecl *>(self); | |
| 1436 | return bitcast(casted->getLocation()); | |
| 1437 | } | |
| 1438 | ||
| 1439 | ZigClangSourceLocation ZigClangDecl_getLocation(const ZigClangDecl *self) { | |
| 1440 | auto casted = reinterpret_cast<const clang::Decl *>(self); | |
| 1441 | return bitcast(casted->getLocation()); | |
| 1442 | } | |
| 1443 | ||
| 1444 | bool 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 | ||
| 1450 | ZigClangQualType ZigClangEnumDecl_getIntegerType(const ZigClangEnumDecl *self) { | |
| 1451 | return bitcast(reinterpret_cast<const clang::EnumDecl *>(self)->getIntegerType()); | |
| 1452 | } | |
| 1453 | ||
| 1454 | struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *self) { | |
| 1455 | auto casted = reinterpret_cast<const clang::FunctionDecl *>(self); | |
| 1456 | return bitcast(casted->getType()); | |
| 1457 | } | |
| 1458 | ||
| 1459 | struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *self) { | |
| 1460 | auto casted = reinterpret_cast<const clang::FunctionDecl *>(self); | |
| 1461 | return bitcast(casted->getLocation()); | |
| 1462 | } | |
| 1463 | ||
| 1464 | bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *self) { | |
| 1465 | auto casted = reinterpret_cast<const clang::FunctionDecl *>(self); | |
| 1466 | return casted->hasBody(); | |
| 1467 | } | |
| 1468 | ||
| 1469 | enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *self) { | |
| 1470 | auto casted = reinterpret_cast<const clang::FunctionDecl *>(self); | |
| 1471 | return (ZigClangStorageClass)casted->getStorageClass(); | |
| 1472 | } | |
| 1473 | ||
| 1474 | const 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 | ||
| 1482 | const 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 | ||
| 1488 | const 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 | ||
| 1494 | ZigClangQualType 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 | ||
| 1500 | ZigClangQualType ZigClangQualType_getCanonicalType(ZigClangQualType self) { | |
| 1501 | clang::QualType qt = bitcast(self); | |
| 1502 | return bitcast(qt.getCanonicalType()); | |
| 1503 | } | |
| 1504 | ||
| 1505 | const 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 | ||
| 1511 | void ZigClangQualType_addConst(ZigClangQualType *self) { | |
| 1512 | reinterpret_cast<clang::QualType *>(self)->addConst(); | |
| 1513 | } | |
| 1514 | ||
| 1515 | bool 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 | ||
| 1530 | bool ZigClangQualType_isConstQualified(ZigClangQualType self) { | |
| 1531 | clang::QualType qt = bitcast(self); | |
| 1532 | return qt.isConstQualified(); | |
| 1533 | } | |
| 1534 | ||
| 1535 | bool ZigClangQualType_isVolatileQualified(ZigClangQualType self) { | |
| 1536 | clang::QualType qt = bitcast(self); | |
| 1537 | return qt.isVolatileQualified(); | |
| 1538 | } | |
| 1539 | ||
| 1540 | bool ZigClangQualType_isRestrictQualified(ZigClangQualType self) { | |
| 1541 | clang::QualType qt = bitcast(self); | |
| 1542 | return qt.isRestrictQualified(); | |
| 1543 | } | |
| 1544 | ||
| 1545 | ZigClangTypeClass 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 | ||
| 1551 | ZigClangQualType ZigClangType_getPointeeType(const ZigClangType *self) { | |
| 1552 | auto casted = reinterpret_cast<const clang::Type *>(self); | |
| 1553 | return bitcast(casted->getPointeeType()); | |
| 1554 | } | |
| 1555 | ||
| 1556 | bool ZigClangType_isVoidType(const ZigClangType *self) { | |
| 1557 | auto casted = reinterpret_cast<const clang::Type *>(self); | |
| 1558 | return casted->isVoidType(); | |
| 1559 | } | |
| 1560 | ||
| 1561 | const char *ZigClangType_getTypeClassName(const ZigClangType *self) { | |
| 1562 | auto casted = reinterpret_cast<const clang::Type *>(self); | |
| 1563 | return casted->getTypeClassName(); | |
| 1564 | } | |
| 1565 | ||
| 1566 | ZigClangSourceLocation ZigClangStmt_getBeginLoc(const ZigClangStmt *self) { | |
| 1567 | auto casted = reinterpret_cast<const clang::Stmt *>(self); | |
| 1568 | return bitcast(casted->getBeginLoc()); | |
| 1569 | } | |
| 1570 | ||
| 1571 | bool ZigClangStmt_classof_Expr(const ZigClangStmt *self) { | |
| 1572 | auto casted = reinterpret_cast<const clang::Stmt *>(self); | |
| 1573 | return clang::Expr::classof(casted); | |
| 1574 | } | |
| 1575 | ||
| 1576 | ZigClangStmtClass ZigClangStmt_getStmtClass(const ZigClangStmt *self) { | |
| 1577 | auto casted = reinterpret_cast<const clang::Stmt *>(self); | |
| 1578 | return (ZigClangStmtClass)casted->getStmtClass(); | |
| 1579 | } | |
| 1580 | ||
| 1581 | ZigClangStmtClass ZigClangExpr_getStmtClass(const ZigClangExpr *self) { | |
| 1582 | auto casted = reinterpret_cast<const clang::Expr *>(self); | |
| 1583 | return (ZigClangStmtClass)casted->getStmtClass(); | |
| 1584 | } | |
| 1585 | ||
| 1586 | ZigClangQualType ZigClangExpr_getType(const ZigClangExpr *self) { | |
| 1587 | auto casted = reinterpret_cast<const clang::Expr *>(self); | |
| 1588 | return bitcast(casted->getType()); | |
| 1589 | } | |
| 1590 | ||
| 1591 | ZigClangSourceLocation ZigClangExpr_getBeginLoc(const ZigClangExpr *self) { | |
| 1592 | auto casted = reinterpret_cast<const clang::Expr *>(self); | |
| 1593 | return bitcast(casted->getBeginLoc()); | |
| 1594 | } | |
| 1595 | ||
| 1596 | ZigClangAPValueKind ZigClangAPValue_getKind(const ZigClangAPValue *self) { | |
| 1597 | auto casted = reinterpret_cast<const clang::APValue *>(self); | |
| 1598 | return (ZigClangAPValueKind)casted->getKind(); | |
| 1599 | } | |
| 1600 | ||
| 1601 | const 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 | ||
| 1607 | unsigned ZigClangAPValue_getArrayInitializedElts(const ZigClangAPValue *self) { | |
| 1608 | auto casted = reinterpret_cast<const clang::APValue *>(self); | |
| 1609 | return casted->getArrayInitializedElts(); | |
| 1610 | } | |
| 1611 | ||
| 1612 | const 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 | ||
| 1618 | const 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 | ||
| 1624 | unsigned ZigClangAPValue_getArraySize(const ZigClangAPValue *self) { | |
| 1625 | auto casted = reinterpret_cast<const clang::APValue *>(self); | |
| 1626 | return casted->getArraySize(); | |
| 1627 | } | |
| 1628 | ||
| 1629 | const 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 | ||
| 1637 | void ZigClangAPSInt_free(const ZigClangAPSInt *self) { | |
| 1638 | auto casted = reinterpret_cast<const llvm::APSInt *>(self); | |
| 1639 | delete casted; | |
| 1640 | } | |
| 1641 | ||
| 1642 | bool ZigClangAPSInt_isSigned(const ZigClangAPSInt *self) { | |
| 1643 | auto casted = reinterpret_cast<const llvm::APSInt *>(self); | |
| 1644 | return casted->isSigned(); | |
| 1645 | } | |
| 1646 | ||
| 1647 | bool ZigClangAPSInt_isNegative(const ZigClangAPSInt *self) { | |
| 1648 | auto casted = reinterpret_cast<const llvm::APSInt *>(self); | |
| 1649 | return casted->isNegative(); | |
| 1650 | } | |
| 1651 | ||
| 1652 | const uint64_t *ZigClangAPSInt_getRawData(const ZigClangAPSInt *self) { | |
| 1653 | auto casted = reinterpret_cast<const llvm::APSInt *>(self); | |
| 1654 | return casted->getRawData(); | |
| 1655 | } | |
| 1656 | ||
| 1657 | unsigned ZigClangAPSInt_getNumWords(const ZigClangAPSInt *self) { | |
| 1658 | auto casted = reinterpret_cast<const llvm::APSInt *>(self); | |
| 1659 | return casted->getNumWords(); | |
| 1660 | } | |
| 1661 | ||
| 1662 | const 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 | ||
| 1668 | ZigClangAPValueLValueBase 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 | ||
| 1674 | ZigClangASTUnit *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 | ||
| 1778 | void ZigClangErrorMsg_delete(Stage2ErrorMsg *ptr, size_t len) { | |
| 1779 | free(ptr); | |
| 1780 | } | |
| 1781 | ||
| 1782 | void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) { | |
| 1783 | delete reinterpret_cast<clang::ASTUnit *>(self); | |
| 1784 | } | |
| 1785 | ||
| 1786 | enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self) { | |
| 1787 | auto casted = reinterpret_cast<const clang::BuiltinType *>(self); | |
| 1788 | return (ZigClangBuiltinTypeKind)casted->getKind(); | |
| 1789 | } | |
| 1790 | ||
| 1791 | bool ZigClangFunctionType_getNoReturnAttr(const struct ZigClangFunctionType *self) { | |
| 1792 | auto casted = reinterpret_cast<const clang::FunctionType *>(self); | |
| 1793 | return casted->getNoReturnAttr(); | |
| 1794 | } | |
| 1795 | ||
| 1796 | enum ZigClangCallingConv ZigClangFunctionType_getCallConv(const struct ZigClangFunctionType *self) { | |
| 1797 | auto casted = reinterpret_cast<const clang::FunctionType *>(self); | |
| 1798 | return (ZigClangCallingConv)casted->getCallConv(); | |
| 1799 | } | |
| 1800 | ||
| 1801 | struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClangFunctionType *self) { | |
| 1802 | auto casted = reinterpret_cast<const clang::FunctionType *>(self); | |
| 1803 | return bitcast(casted->getReturnType()); | |
| 1804 | } | |
| 1805 | ||
| 1806 | bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self) { | |
| 1807 | auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self); | |
| 1808 | return casted->isVariadic(); | |
| 1809 | } | |
| 1810 | ||
| 1811 | unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self) { | |
| 1812 | auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self); | |
| 1813 | return casted->getNumParams(); | |
| 1814 | } | |
| 1815 | ||
| 1816 | struct 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 | ||
| 1823 | ZigClangCompoundStmt_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 | ||
| 1828 | ZigClangCompoundStmt_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 | 8 | #ifndef ZIG_ZIG_CLANG_H |
| 9 | 9 | #define ZIG_ZIG_CLANG_H |
| 10 | 10 | |
| 11 | #ifdef __cplusplus | |
| 12 | #define ZIG_EXTERN_C extern "C" | |
| 13 | #else | |
| 14 | #define ZIG_EXTERN_C | |
| 15 | #endif | |
| 11 | #include "userland.h" | |
| 12 | #include <inttypes.h> | |
| 13 | #include <stdbool.h> | |
| 16 | 14 | |
| 17 | 15 | // 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. | |
| 19 | 18 | |
| 20 | 19 | struct ZigClangSourceLocation { |
| 21 | 20 | unsigned ID; |
| ... | ... | @@ -25,7 +24,14 @@ struct ZigClangQualType { |
| 25 | 24 | void *ptr; |
| 26 | 25 | }; |
| 27 | 26 | |
| 27 | struct ZigClangAPValueLValueBase { | |
| 28 | void *Ptr; | |
| 29 | unsigned CallIndex; | |
| 30 | unsigned Version; | |
| 31 | }; | |
| 32 | ||
| 28 | 33 | struct ZigClangAPValue; |
| 34 | struct ZigClangAPSInt; | |
| 29 | 35 | struct ZigClangASTContext; |
| 30 | 36 | struct ZigClangASTUnit; |
| 31 | 37 | struct ZigClangArraySubscriptExpr; |
| ... | ... | @@ -82,10 +88,10 @@ struct ZigClangSkipFunctionBodiesScope; |
| 82 | 88 | struct ZigClangSourceManager; |
| 83 | 89 | struct ZigClangSourceRange; |
| 84 | 90 | struct ZigClangStmt; |
| 85 | struct ZigClangStorageClass; | |
| 86 | 91 | struct ZigClangStringLiteral; |
| 87 | 92 | struct ZigClangStringRef; |
| 88 | 93 | struct ZigClangSwitchStmt; |
| 94 | struct ZigClangTagDecl; | |
| 89 | 95 | struct ZigClangType; |
| 90 | 96 | struct ZigClangTypedefNameDecl; |
| 91 | 97 | struct ZigClangTypedefType; |
| ... | ... | @@ -94,6 +100,9 @@ struct ZigClangUnaryOperator; |
| 94 | 100 | struct ZigClangValueDecl; |
| 95 | 101 | struct ZigClangVarDecl; |
| 96 | 102 | struct ZigClangWhileStmt; |
| 103 | struct ZigClangFunctionType; | |
| 104 | ||
| 105 | typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator; | |
| 97 | 106 | |
| 98 | 107 | enum ZigClangBO { |
| 99 | 108 | ZigClangBO_PtrMemD, |
| ... | ... | @@ -148,112 +157,674 @@ enum ZigClangUO { |
| 148 | 157 | ZigClangUO_Coawait, |
| 149 | 158 | }; |
| 150 | 159 | |
| 151 | //struct ZigClangCC_AAPCS; | |
| 152 | //struct ZigClangCC_AAPCS_VFP; | |
| 153 | //struct ZigClangCC_C; | |
| 154 | //struct ZigClangCC_IntelOclBicc; | |
| 155 | //struct ZigClangCC_OpenCLKernel; | |
| 156 | //struct ZigClangCC_PreserveAll; | |
| 157 | //struct ZigClangCC_PreserveMost; | |
| 158 | //struct ZigClangCC_SpirFunction; | |
| 159 | //struct ZigClangCC_Swift; | |
| 160 | //struct ZigClangCC_Win64; | |
| 161 | //struct ZigClangCC_X86FastCall; | |
| 162 | //struct ZigClangCC_X86Pascal; | |
| 163 | //struct ZigClangCC_X86RegCall; | |
| 164 | //struct ZigClangCC_X86StdCall; | |
| 165 | //struct ZigClangCC_X86ThisCall; | |
| 166 | //struct ZigClangCC_X86VectorCall; | |
| 167 | //struct ZigClangCC_X86_64SysV; | |
| 168 | ||
| 169 | //struct ZigClangCK_ARCConsumeObject; | |
| 170 | //struct ZigClangCK_ARCExtendBlockObject; | |
| 171 | //struct ZigClangCK_ARCProduceObject; | |
| 172 | //struct ZigClangCK_ARCReclaimReturnedObject; | |
| 173 | //struct ZigClangCK_AddressSpaceConversion; | |
| 174 | //struct ZigClangCK_AnyPointerToBlockPointerCast; | |
| 175 | //struct ZigClangCK_ArrayToPointerDecay; | |
| 176 | //struct ZigClangCK_AtomicToNonAtomic; | |
| 177 | //struct ZigClangCK_BaseToDerived; | |
| 178 | //struct ZigClangCK_BaseToDerivedMemberPointer; | |
| 179 | //struct ZigClangCK_BitCast; | |
| 180 | //struct ZigClangCK_BlockPointerToObjCPointerCast; | |
| 181 | //struct ZigClangCK_BooleanToSignedIntegral; | |
| 182 | //struct ZigClangCK_BuiltinFnToFnPtr; | |
| 183 | //struct ZigClangCK_CPointerToObjCPointerCast; | |
| 184 | //struct ZigClangCK_ConstructorConversion; | |
| 185 | //struct ZigClangCK_CopyAndAutoreleaseBlockObject; | |
| 186 | //struct ZigClangCK_Dependent; | |
| 187 | //struct ZigClangCK_DerivedToBase; | |
| 188 | //struct ZigClangCK_DerivedToBaseMemberPointer; | |
| 189 | //struct ZigClangCK_Dynamic; | |
| 190 | //struct ZigClangCK_FloatingCast; | |
| 191 | //struct ZigClangCK_FloatingComplexCast; | |
| 192 | //struct ZigClangCK_FloatingComplexToBoolean; | |
| 193 | //struct ZigClangCK_FloatingComplexToIntegralComplex; | |
| 194 | //struct ZigClangCK_FloatingComplexToReal; | |
| 195 | //struct ZigClangCK_FloatingRealToComplex; | |
| 196 | //struct ZigClangCK_FloatingToBoolean; | |
| 197 | //struct ZigClangCK_FloatingToIntegral; | |
| 198 | //struct ZigClangCK_FunctionToPointerDecay; | |
| 199 | //struct ZigClangCK_IntToOCLSampler; | |
| 200 | //struct ZigClangCK_IntegralCast; | |
| 201 | //struct ZigClangCK_IntegralComplexCast; | |
| 202 | //struct ZigClangCK_IntegralComplexToBoolean; | |
| 203 | //struct ZigClangCK_IntegralComplexToFloatingComplex; | |
| 204 | //struct ZigClangCK_IntegralComplexToReal; | |
| 205 | //struct ZigClangCK_IntegralRealToComplex; | |
| 206 | //struct ZigClangCK_IntegralToBoolean; | |
| 207 | //struct ZigClangCK_IntegralToFloating; | |
| 208 | //struct ZigClangCK_IntegralToPointer; | |
| 209 | //struct ZigClangCK_LValueBitCast; | |
| 210 | //struct ZigClangCK_LValueToRValue; | |
| 211 | //struct ZigClangCK_MemberPointerToBoolean; | |
| 212 | //struct ZigClangCK_NoOp; | |
| 213 | //struct ZigClangCK_NonAtomicToAtomic; | |
| 214 | //struct ZigClangCK_NullToMemberPointer; | |
| 215 | //struct ZigClangCK_NullToPointer; | |
| 216 | //struct ZigClangCK_ObjCObjectLValueCast; | |
| 217 | //struct ZigClangCK_PointerToBoolean; | |
| 218 | //struct ZigClangCK_PointerToIntegral; | |
| 219 | //struct ZigClangCK_ReinterpretMemberPointer; | |
| 220 | //struct ZigClangCK_ToUnion; | |
| 221 | //struct ZigClangCK_ToVoid; | |
| 222 | //struct ZigClangCK_UncheckedDerivedToBase; | |
| 223 | //struct ZigClangCK_UserDefinedConversion; | |
| 224 | //struct ZigClangCK_VectorSplat; | |
| 225 | //struct ZigClangCK_ZeroToOCLEvent; | |
| 226 | //struct ZigClangCK_ZeroToOCLQueue; | |
| 227 | ||
| 228 | //struct ZigClangETK_Class; | |
| 229 | //struct ZigClangETK_Enum; | |
| 230 | //struct ZigClangETK_Interface; | |
| 231 | //struct ZigClangETK_None; | |
| 232 | //struct ZigClangETK_Struct; | |
| 233 | //struct ZigClangETK_Typename; | |
| 234 | //struct ZigClangETK_Union; | |
| 235 | ||
| 236 | //struct ZigClangSC_None; | |
| 237 | //struct ZigClangSC_PrivateExtern; | |
| 238 | //struct ZigClangSC_Static; | |
| 239 | ||
| 240 | //struct ZigClangTU_Complete; | |
| 241 | ||
| 242 | ZIG_EXTERN_C ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *, | |
| 243 | ZigClangSourceLocation Loc); | |
| 244 | ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *, | |
| 245 | ZigClangSourceLocation SpellingLoc); | |
| 246 | ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *, | |
| 247 | ZigClangSourceLocation Loc); | |
| 248 | ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *, | |
| 249 | ZigClangSourceLocation Loc); | |
| 250 | ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *, | |
| 251 | ZigClangSourceLocation SL); | |
| 252 | ||
| 253 | ZIG_EXTERN_C ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext*, ZigClangQualType T); | |
| 254 | ||
| 255 | ZIG_EXTERN_C ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *); | |
| 256 | ZIG_EXTERN_C ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *); | |
| 257 | ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *, void *context, | |
| 258 | bool (*Fn)(void *context, const ZigClangDecl *decl)); | |
| 160 | enum ZigClangTypeClass { | |
| 161 | ZigClangType_Builtin, | |
| 162 | ZigClangType_Complex, | |
| 163 | ZigClangType_Pointer, | |
| 164 | ZigClangType_BlockPointer, | |
| 165 | ZigClangType_LValueReference, | |
| 166 | ZigClangType_RValueReference, | |
| 167 | ZigClangType_MemberPointer, | |
| 168 | ZigClangType_ConstantArray, | |
| 169 | ZigClangType_IncompleteArray, | |
| 170 | ZigClangType_VariableArray, | |
| 171 | ZigClangType_DependentSizedArray, | |
| 172 | ZigClangType_DependentSizedExtVector, | |
| 173 | ZigClangType_DependentAddressSpace, | |
| 174 | ZigClangType_Vector, | |
| 175 | ZigClangType_DependentVector, | |
| 176 | ZigClangType_ExtVector, | |
| 177 | ZigClangType_FunctionProto, | |
| 178 | ZigClangType_FunctionNoProto, | |
| 179 | ZigClangType_UnresolvedUsing, | |
| 180 | ZigClangType_Paren, | |
| 181 | ZigClangType_Typedef, | |
| 182 | ZigClangType_Adjusted, | |
| 183 | ZigClangType_Decayed, | |
| 184 | ZigClangType_TypeOfExpr, | |
| 185 | ZigClangType_TypeOf, | |
| 186 | ZigClangType_Decltype, | |
| 187 | ZigClangType_UnaryTransform, | |
| 188 | ZigClangType_Record, | |
| 189 | ZigClangType_Enum, | |
| 190 | ZigClangType_Elaborated, | |
| 191 | ZigClangType_Attributed, | |
| 192 | ZigClangType_TemplateTypeParm, | |
| 193 | ZigClangType_SubstTemplateTypeParm, | |
| 194 | ZigClangType_SubstTemplateTypeParmPack, | |
| 195 | ZigClangType_TemplateSpecialization, | |
| 196 | ZigClangType_Auto, | |
| 197 | ZigClangType_DeducedTemplateSpecialization, | |
| 198 | ZigClangType_InjectedClassName, | |
| 199 | ZigClangType_DependentName, | |
| 200 | ZigClangType_DependentTemplateSpecialization, | |
| 201 | ZigClangType_PackExpansion, | |
| 202 | ZigClangType_ObjCTypeParam, | |
| 203 | ZigClangType_ObjCObject, | |
| 204 | ZigClangType_ObjCInterface, | |
| 205 | ZigClangType_ObjCObjectPointer, | |
| 206 | ZigClangType_Pipe, | |
| 207 | ZigClangType_Atomic, | |
| 208 | }; | |
| 209 | ||
| 210 | enum ZigClangStmtClass { | |
| 211 | ZigClangStmt_NoStmtClass = 0, | |
| 212 | ZigClangStmt_GCCAsmStmtClass, | |
| 213 | ZigClangStmt_MSAsmStmtClass, | |
| 214 | ZigClangStmt_AttributedStmtClass, | |
| 215 | ZigClangStmt_BreakStmtClass, | |
| 216 | ZigClangStmt_CXXCatchStmtClass, | |
| 217 | ZigClangStmt_CXXForRangeStmtClass, | |
| 218 | ZigClangStmt_CXXTryStmtClass, | |
| 219 | ZigClangStmt_CapturedStmtClass, | |
| 220 | ZigClangStmt_CompoundStmtClass, | |
| 221 | ZigClangStmt_ContinueStmtClass, | |
| 222 | ZigClangStmt_CoreturnStmtClass, | |
| 223 | ZigClangStmt_CoroutineBodyStmtClass, | |
| 224 | ZigClangStmt_DeclStmtClass, | |
| 225 | ZigClangStmt_DoStmtClass, | |
| 226 | ZigClangStmt_BinaryConditionalOperatorClass, | |
| 227 | ZigClangStmt_ConditionalOperatorClass, | |
| 228 | ZigClangStmt_AddrLabelExprClass, | |
| 229 | ZigClangStmt_ArrayInitIndexExprClass, | |
| 230 | ZigClangStmt_ArrayInitLoopExprClass, | |
| 231 | ZigClangStmt_ArraySubscriptExprClass, | |
| 232 | ZigClangStmt_ArrayTypeTraitExprClass, | |
| 233 | ZigClangStmt_AsTypeExprClass, | |
| 234 | ZigClangStmt_AtomicExprClass, | |
| 235 | ZigClangStmt_BinaryOperatorClass, | |
| 236 | ZigClangStmt_CompoundAssignOperatorClass, | |
| 237 | ZigClangStmt_BlockExprClass, | |
| 238 | ZigClangStmt_CXXBindTemporaryExprClass, | |
| 239 | ZigClangStmt_CXXBoolLiteralExprClass, | |
| 240 | ZigClangStmt_CXXConstructExprClass, | |
| 241 | ZigClangStmt_CXXTemporaryObjectExprClass, | |
| 242 | ZigClangStmt_CXXDefaultArgExprClass, | |
| 243 | ZigClangStmt_CXXDefaultInitExprClass, | |
| 244 | ZigClangStmt_CXXDeleteExprClass, | |
| 245 | ZigClangStmt_CXXDependentScopeMemberExprClass, | |
| 246 | ZigClangStmt_CXXFoldExprClass, | |
| 247 | ZigClangStmt_CXXInheritedCtorInitExprClass, | |
| 248 | ZigClangStmt_CXXNewExprClass, | |
| 249 | ZigClangStmt_CXXNoexceptExprClass, | |
| 250 | ZigClangStmt_CXXNullPtrLiteralExprClass, | |
| 251 | ZigClangStmt_CXXPseudoDestructorExprClass, | |
| 252 | ZigClangStmt_CXXScalarValueInitExprClass, | |
| 253 | ZigClangStmt_CXXStdInitializerListExprClass, | |
| 254 | ZigClangStmt_CXXThisExprClass, | |
| 255 | ZigClangStmt_CXXThrowExprClass, | |
| 256 | ZigClangStmt_CXXTypeidExprClass, | |
| 257 | ZigClangStmt_CXXUnresolvedConstructExprClass, | |
| 258 | ZigClangStmt_CXXUuidofExprClass, | |
| 259 | ZigClangStmt_CallExprClass, | |
| 260 | ZigClangStmt_CUDAKernelCallExprClass, | |
| 261 | ZigClangStmt_CXXMemberCallExprClass, | |
| 262 | ZigClangStmt_CXXOperatorCallExprClass, | |
| 263 | ZigClangStmt_UserDefinedLiteralClass, | |
| 264 | ZigClangStmt_CStyleCastExprClass, | |
| 265 | ZigClangStmt_CXXFunctionalCastExprClass, | |
| 266 | ZigClangStmt_CXXConstCastExprClass, | |
| 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 | ||
| 410 | enum 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 | ||
| 472 | enum 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 | ||
| 487 | enum 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 | ||
| 564 | enum 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 | ||
| 683 | enum 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 | ||
| 704 | enum 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 | ||
| 716 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *, | |
| 717 | struct ZigClangSourceLocation Loc); | |
| 718 | ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *, | |
| 719 | struct ZigClangSourceLocation SpellingLoc); | |
| 720 | ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const struct ZigClangSourceManager *, | |
| 721 | struct ZigClangSourceLocation Loc); | |
| 722 | ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const struct ZigClangSourceManager *, | |
| 723 | struct ZigClangSourceLocation Loc); | |
| 724 | ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const struct ZigClangSourceManager *, | |
| 725 | struct ZigClangSourceLocation SL); | |
| 726 | ||
| 727 | ZIG_EXTERN_C struct ZigClangQualType ZigClangASTContext_getPointerType(const struct ZigClangASTContext*, struct ZigClangQualType T); | |
| 728 | ||
| 729 | ||
| 730 | // Can return null. | |
| 731 | ZIG_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); | |
| 733 | ZIG_EXTERN_C void ZigClangASTUnit_delete(struct ZigClangASTUnit *); | |
| 734 | ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len); | |
| 735 | ||
| 736 | ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *); | |
| 737 | ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *); | |
| 738 | ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context, | |
| 739 | bool (*Fn)(void *context, const struct ZigClangDecl *decl)); | |
| 740 | ||
| 741 | ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordType_getDecl(const struct ZigClangRecordType *record_ty); | |
| 742 | ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumType_getDecl(const struct ZigClangEnumType *record_ty); | |
| 743 | ||
| 744 | ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const struct ZigClangRecordDecl *record_decl); | |
| 745 | ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const struct ZigClangEnumDecl *); | |
| 746 | ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCanonicalDecl(const struct ZigClangTypedefNameDecl *); | |
| 747 | ||
| 748 | ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *); | |
| 749 | ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *); | |
| 750 | ||
| 751 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangRecordDecl_getLocation(const struct ZigClangRecordDecl *); | |
| 752 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangEnumDecl_getLocation(const struct ZigClangEnumDecl *); | |
| 753 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangTypedefNameDecl_getLocation(const struct ZigClangTypedefNameDecl *); | |
| 754 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDecl_getLocation(const struct ZigClangDecl *); | |
| 755 | ||
| 756 | ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *); | |
| 757 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *); | |
| 758 | ZIG_EXTERN_C bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *); | |
| 759 | ZIG_EXTERN_C enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *); | |
| 760 | ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *, unsigned i); | |
| 761 | ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *); | |
| 762 | ||
| 763 | ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl); | |
| 764 | ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const struct ZigClangRecordDecl *record_decl); | |
| 765 | ZIG_EXTERN_C bool ZigClangRecordDecl_isAnonymousStructOrUnion(const struct ZigClangRecordDecl *record_decl); | |
| 766 | ||
| 767 | ZIG_EXTERN_C struct ZigClangQualType ZigClangEnumDecl_getIntegerType(const struct ZigClangEnumDecl *); | |
| 768 | ||
| 769 | ZIG_EXTERN_C const char *ZigClangDecl_getName_bytes_begin(const struct ZigClangDecl *decl); | |
| 770 | ZIG_EXTERN_C enum ZigClangDeclKind ZigClangDecl_getKind(const struct ZigClangDecl *decl); | |
| 771 | ZIG_EXTERN_C const char *ZigClangDecl_getDeclKindName(const struct ZigClangDecl *decl); | |
| 772 | ||
| 773 | ZIG_EXTERN_C bool ZigClangSourceLocation_eq(struct ZigClangSourceLocation a, struct ZigClangSourceLocation b); | |
| 774 | ||
| 775 | ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const struct ZigClangTypedefType *); | |
| 776 | ZIG_EXTERN_C struct ZigClangQualType ZigClangTypedefNameDecl_getUnderlyingType(const struct ZigClangTypedefNameDecl *); | |
| 777 | ||
| 778 | ZIG_EXTERN_C struct ZigClangQualType ZigClangQualType_getCanonicalType(struct ZigClangQualType); | |
| 779 | ZIG_EXTERN_C const struct ZigClangType *ZigClangQualType_getTypePtr(struct ZigClangQualType); | |
| 780 | ZIG_EXTERN_C void ZigClangQualType_addConst(struct ZigClangQualType *); | |
| 781 | ZIG_EXTERN_C bool ZigClangQualType_eq(struct ZigClangQualType, struct ZigClangQualType); | |
| 782 | ZIG_EXTERN_C bool ZigClangQualType_isConstQualified(struct ZigClangQualType); | |
| 783 | ZIG_EXTERN_C bool ZigClangQualType_isVolatileQualified(struct ZigClangQualType); | |
| 784 | ZIG_EXTERN_C bool ZigClangQualType_isRestrictQualified(struct ZigClangQualType); | |
| 785 | ||
| 786 | ZIG_EXTERN_C enum ZigClangTypeClass ZigClangType_getTypeClass(const struct ZigClangType *self); | |
| 787 | ZIG_EXTERN_C struct ZigClangQualType ZigClangType_getPointeeType(const struct ZigClangType *self); | |
| 788 | ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self); | |
| 789 | ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self); | |
| 790 | ||
| 791 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangStmt_getBeginLoc(const struct ZigClangStmt *self); | |
| 792 | ZIG_EXTERN_C enum ZigClangStmtClass ZigClangStmt_getStmtClass(const struct ZigClangStmt *self); | |
| 793 | ZIG_EXTERN_C bool ZigClangStmt_classof_Expr(const struct ZigClangStmt *self); | |
| 794 | ||
| 795 | ZIG_EXTERN_C enum ZigClangStmtClass ZigClangExpr_getStmtClass(const struct ZigClangExpr *self); | |
| 796 | ZIG_EXTERN_C struct ZigClangQualType ZigClangExpr_getType(const struct ZigClangExpr *self); | |
| 797 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangExpr_getBeginLoc(const struct ZigClangExpr *self); | |
| 798 | ||
| 799 | ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self); | |
| 800 | ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPValue_getInt(const struct ZigClangAPValue *self); | |
| 801 | ZIG_EXTERN_C unsigned ZigClangAPValue_getArrayInitializedElts(const struct ZigClangAPValue *self); | |
| 802 | ZIG_EXTERN_C const struct ZigClangAPValue *ZigClangAPValue_getArrayInitializedElt(const struct ZigClangAPValue *self, unsigned i); | |
| 803 | ZIG_EXTERN_C const struct ZigClangAPValue *ZigClangAPValue_getArrayFiller(const struct ZigClangAPValue *self); | |
| 804 | ZIG_EXTERN_C unsigned ZigClangAPValue_getArraySize(const struct ZigClangAPValue *self); | |
| 805 | ZIG_EXTERN_C struct ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const struct ZigClangAPValue *self); | |
| 806 | ||
| 807 | ZIG_EXTERN_C bool ZigClangAPSInt_isSigned(const struct ZigClangAPSInt *self); | |
| 808 | ZIG_EXTERN_C bool ZigClangAPSInt_isNegative(const struct ZigClangAPSInt *self); | |
| 809 | ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPSInt_negate(const struct ZigClangAPSInt *self); | |
| 810 | ZIG_EXTERN_C void ZigClangAPSInt_free(const struct ZigClangAPSInt *self); | |
| 811 | ZIG_EXTERN_C const uint64_t *ZigClangAPSInt_getRawData(const struct ZigClangAPSInt *self); | |
| 812 | ZIG_EXTERN_C unsigned ZigClangAPSInt_getNumWords(const struct ZigClangAPSInt *self); | |
| 813 | ||
| 814 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangAPValueLValueBase_dyn_cast_Expr(struct ZigClangAPValueLValueBase self); | |
| 815 | ||
| 816 | ZIG_EXTERN_C enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self); | |
| 817 | ||
| 818 | ZIG_EXTERN_C bool ZigClangFunctionType_getNoReturnAttr(const struct ZigClangFunctionType *self); | |
| 819 | ZIG_EXTERN_C enum ZigClangCallingConv ZigClangFunctionType_getCallConv(const struct ZigClangFunctionType *self); | |
| 820 | ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClangFunctionType *self); | |
| 821 | ||
| 822 | ZIG_EXTERN_C bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self); | |
| 823 | ZIG_EXTERN_C unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self); | |
| 824 | ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self, unsigned i); | |
| 825 | ||
| 826 | ||
| 827 | ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self); | |
| 828 | ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self); | |
| 829 | ||
| 259 | 830 | #endif |
std/array_list.zig+38| ... | ... | @@ -111,6 +111,17 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type { |
| 111 | 111 | new_item_ptr.* = item; |
| 112 | 112 | } |
| 113 | 113 | |
| 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 | 125 | /// Removes the element at the specified index and returns it. |
| 115 | 126 | /// The empty slot is filled from the end of the list. |
| 116 | 127 | pub fn swapRemove(self: *Self, i: usize) T { |
| ... | ... | @@ -279,6 +290,33 @@ test "std.ArrayList.basic" { |
| 279 | 290 | testing.expect(list.pop() == 33); |
| 280 | 291 | } |
| 281 | 292 | |
| 293 | test "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 | ||
| 282 | 320 | test "std.ArrayList.swapRemove" { |
| 283 | 321 | var list = ArrayList(i32).init(debug.global_allocator); |
| 284 | 322 | defer list.deinit(); |
std/build.zig+27| ... | ... | @@ -50,6 +50,8 @@ pub const Builder = struct { |
| 50 | 50 | build_root: []const u8, |
| 51 | 51 | cache_root: []const u8, |
| 52 | 52 | release_mode: ?builtin.Mode, |
| 53 | override_std_dir: ?[]const u8, | |
| 54 | override_lib_dir: ?[]const u8, | |
| 53 | 55 | |
| 54 | 56 | pub const CStd = enum { |
| 55 | 57 | C89, |
| ... | ... | @@ -133,6 +135,8 @@ pub const Builder = struct { |
| 133 | 135 | }, |
| 134 | 136 | .have_install_step = false, |
| 135 | 137 | .release_mode = null, |
| 138 | .override_std_dir = null, | |
| 139 | .override_lib_dir = null, | |
| 136 | 140 | }; |
| 137 | 141 | self.detectNativeSystemPaths(); |
| 138 | 142 | self.default_step = self.step("default", "Build the project"); |
| ... | ... | @@ -937,8 +941,11 @@ pub const LibExeObjStep = struct { |
| 937 | 941 | verbose_link: bool, |
| 938 | 942 | verbose_cc: bool, |
| 939 | 943 | disable_gen_h: bool, |
| 944 | bundle_compiler_rt: bool, | |
| 945 | disable_stack_probing: bool, | |
| 940 | 946 | c_std: Builder.CStd, |
| 941 | 947 | override_std_dir: ?[]const u8, |
| 948 | override_lib_dir: ?[]const u8, | |
| 942 | 949 | main_pkg_path: ?[]const u8, |
| 943 | 950 | exec_cmd_args: ?[]const ?[]const u8, |
| 944 | 951 | name_prefix: []const u8, |
| ... | ... | @@ -1039,11 +1046,14 @@ pub const LibExeObjStep = struct { |
| 1039 | 1046 | .c_std = Builder.CStd.C99, |
| 1040 | 1047 | .system_linker_hack = false, |
| 1041 | 1048 | .override_std_dir = null, |
| 1049 | .override_lib_dir = null, | |
| 1042 | 1050 | .main_pkg_path = null, |
| 1043 | 1051 | .exec_cmd_args = null, |
| 1044 | 1052 | .name_prefix = "", |
| 1045 | 1053 | .filter = null, |
| 1046 | 1054 | .disable_gen_h = false, |
| 1055 | .bundle_compiler_rt = false, | |
| 1056 | .disable_stack_probing = false, | |
| 1047 | 1057 | .output_dir = null, |
| 1048 | 1058 | .need_system_paths = false, |
| 1049 | 1059 | .single_threaded = false, |
| ... | ... | @@ -1446,6 +1456,12 @@ pub const LibExeObjStep = struct { |
| 1446 | 1456 | if (self.disable_gen_h) { |
| 1447 | 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 | } | |
| 1449 | 1465 | |
| 1450 | 1466 | switch (self.target) { |
| 1451 | 1467 | Target.Native => {}, |
| ... | ... | @@ -1528,6 +1544,17 @@ pub const LibExeObjStep = struct { |
| 1528 | 1544 | if (self.override_std_dir) |dir| { |
| 1529 | 1545 | try zig_args.append("--override-std-dir"); |
| 1530 | 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 | } |
| 1532 | 1559 | |
| 1533 | 1560 | if (self.main_pkg_path) |dir| { |
std/c.zig+6| ... | ... | @@ -12,6 +12,12 @@ pub use switch (builtin.os) { |
| 12 | 12 | |
| 13 | 13 | // TODO https://github.com/ziglang/zig/issues/265 on this whole file |
| 14 | 14 | |
| 15 | pub const FILE = @OpaqueType(); | |
| 16 | pub extern "c" fn fopen(filename: [*]const u8, modes: [*]const u8) ?*FILE; | |
| 17 | pub extern "c" fn fclose(stream: *FILE) c_int; | |
| 18 | pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; | |
| 19 | pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; | |
| 20 | ||
| 15 | 21 | pub extern "c" fn abort() noreturn; |
| 16 | 22 | pub extern "c" fn exit(code: c_int) noreturn; |
| 17 | 23 | pub 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 | 42 | }; |
| 43 | 43 | |
| 44 | 44 | pub const msghdr = extern struct { |
| 45 | msg_name: *u8, | |
| 45 | /// optional address | |
| 46 | msg_name: ?*sockaddr, | |
| 47 | /// size of address | |
| 46 | 48 | msg_namelen: socklen_t, |
| 47 | msg_iov: *iovec, | |
| 49 | /// scatter/gather array | |
| 50 | msg_iov: [*]iovec, | |
| 51 | /// # elements in msg_iov | |
| 48 | 52 | msg_iovlen: i32, |
| 49 | __pad1: i32, | |
| 50 | msg_control: *u8, | |
| 53 | /// ancillary data | |
| 54 | msg_control: ?*c_void, | |
| 55 | /// ancillary data buffer len | |
| 51 | 56 | msg_controllen: socklen_t, |
| 52 | __pad2: socklen_t, | |
| 57 | /// flags on received message | |
| 58 | msg_flags: i32, | |
| 59 | }; | |
| 60 | ||
| 61 | pub 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 | 75 | msg_flags: i32, |
| 54 | 76 | }; |
| 55 | 77 |
std/c/linux.zig+4| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | const linux = @import("../os/linux.zig"); | |
| 1 | 2 | pub use @import("../os/linux/errno.zig"); |
| 2 | 3 | |
| 3 | 4 | pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int; |
| ... | ... | @@ -11,3 +12,6 @@ pub const pthread_attr_t = extern struct { |
| 11 | 12 | |
| 12 | 13 | /// See std.elf for constants for this |
| 13 | 14 | pub extern fn getauxval(__type: c_ulong) c_ulong; |
| 15 | ||
| 16 | pub const dl_iterate_phdr_callback = extern fn (info: *linux.dl_phdr_info, size: usize, data: ?*c_void) c_int; | |
| 17 | pub 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 | 42 | }; |
| 43 | 43 | |
| 44 | 44 | pub const msghdr = extern struct { |
| 45 | msg_name: *u8, | |
| 45 | /// optional address | |
| 46 | msg_name: ?*sockaddr, | |
| 47 | /// size of address | |
| 46 | 48 | msg_namelen: socklen_t, |
| 47 | msg_iov: *iovec, | |
| 49 | /// scatter/gather array | |
| 50 | msg_iov: [*]iovec, | |
| 51 | /// # elements in msg_iov | |
| 48 | 52 | msg_iovlen: i32, |
| 49 | __pad1: i32, | |
| 50 | msg_control: *u8, | |
| 53 | /// ancillary data | |
| 54 | msg_control: ?*c_void, | |
| 55 | /// ancillary data buffer len | |
| 51 | 56 | msg_controllen: socklen_t, |
| 52 | __pad2: socklen_t, | |
| 57 | /// flags on received message | |
| 58 | msg_flags: i32, | |
| 59 | }; | |
| 60 | ||
| 61 | pub 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 | 75 | msg_flags: i32, |
| 54 | 76 | }; |
| 55 | 77 |
std/crypto/chacha20.zig+3-2| ... | ... | @@ -142,7 +142,7 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32] |
| 142 | 142 | assert(in.len >= out.len); |
| 143 | 143 | assert(counter +% (in.len >> 6) >= counter); |
| 144 | 144 | |
| 145 | var cursor: u64 = 0; | |
| 145 | var cursor: usize = 0; | |
| 146 | 146 | var k: [8]u32 = undefined; |
| 147 | 147 | var c: [4]u32 = undefined; |
| 148 | 148 | |
| ... | ... | @@ -161,7 +161,8 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32] |
| 161 | 161 | c[3] = mem.readIntSliceLittle(u32, nonce[4..8]); |
| 162 | 162 | |
| 163 | 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); | |
| 165 | 166 | |
| 166 | 167 | // first partial big block |
| 167 | 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 | 13 | const builtin = @import("builtin"); |
| 14 | 14 | const maxInt = std.math.maxInt; |
| 15 | 15 | |
| 16 | const leb = @import("debug/leb128.zig"); | |
| 17 | ||
| 16 | 18 | pub const FailingAllocator = @import("debug/failing_allocator.zig").FailingAllocator; |
| 17 | 19 | pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator; |
| 18 | 20 | |
| ... | ... | @@ -214,14 +216,14 @@ pub fn writeStackTrace( |
| 214 | 216 | tty_color: bool, |
| 215 | 217 | ) !void { |
| 216 | 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); | |
| 218 | 220 | |
| 219 | 221 | while (frames_left != 0) : ({ |
| 220 | 222 | frames_left -= 1; |
| 221 | 223 | frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len; |
| 222 | 224 | }) { |
| 223 | 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 | } |
| 227 | 229 | |
| ... | ... | @@ -263,7 +265,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color |
| 263 | 265 | } |
| 264 | 266 | var it = StackIterator.init(start_addr); |
| 265 | 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 | } |
| 269 | 271 | |
| ... | ... | @@ -376,7 +378,6 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 376 | 378 | // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records) |
| 377 | 379 | // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in, |
| 378 | 380 | // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection. |
| 379 | ||
| 380 | 381 | const subsection_end_index = sect_offset + subsect_hdr.Length; |
| 381 | 382 | |
| 382 | 383 | while (line_index < subsection_end_index) { |
| ... | ... | @@ -690,9 +691,9 @@ pub fn printSourceAtAddressDwarf( |
| 690 | 691 | return; |
| 691 | 692 | }; |
| 692 | 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 | 695 | defer line_info.deinit(); |
| 695 | const symbol_name = "???"; | |
| 696 | const symbol_name = getSymbolNameDwarf(debug_info, address) orelse "???"; | |
| 696 | 697 | try printLineInfo( |
| 697 | 698 | out_stream, |
| 698 | 699 | line_info, |
| ... | ... | @@ -969,6 +970,8 @@ fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Sec |
| 969 | 970 | pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void { |
| 970 | 971 | di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator); |
| 971 | 972 | di.compile_unit_list = ArrayList(CompileUnit).init(allocator); |
| 973 | di.func_list = ArrayList(Func).init(allocator); | |
| 974 | try scanAllFunctions(di); | |
| 972 | 975 | try scanAllCompileUnits(di); |
| 973 | 976 | } |
| 974 | 977 | |
| ... | ... | @@ -992,6 +995,7 @@ pub fn openElfDebugInfo( |
| 992 | 995 | .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")), |
| 993 | 996 | .abbrev_table_list = undefined, |
| 994 | 997 | .compile_unit_list = undefined, |
| 998 | .func_list = undefined, | |
| 995 | 999 | }; |
| 996 | 1000 | try openDwarfDebugInfo(&di, allocator); |
| 997 | 1001 | return di; |
| ... | ... | @@ -1162,6 +1166,7 @@ pub const DwarfInfo = struct { |
| 1162 | 1166 | debug_ranges: ?Section, |
| 1163 | 1167 | abbrev_table_list: ArrayList(AbbrevTableHeader), |
| 1164 | 1168 | compile_unit_list: ArrayList(CompileUnit), |
| 1169 | func_list: ArrayList(Func), | |
| 1165 | 1170 | |
| 1166 | 1171 | pub const Section = struct { |
| 1167 | 1172 | offset: usize, |
| ... | ... | @@ -1178,7 +1183,7 @@ pub const DwarfInfo = struct { |
| 1178 | 1183 | }; |
| 1179 | 1184 | |
| 1180 | 1185 | pub const DebugInfo = switch (builtin.os) { |
| 1181 | builtin.Os.macosx => struct { | |
| 1186 | builtin.Os.macosx, builtin.Os.ios => struct { | |
| 1182 | 1187 | symbols: []const MachoSymbol, |
| 1183 | 1188 | strings: []const u8, |
| 1184 | 1189 | ofiles: OFileTable, |
| ... | ... | @@ -1213,7 +1218,6 @@ const CompileUnit = struct { |
| 1213 | 1218 | version: u16, |
| 1214 | 1219 | is_64: bool, |
| 1215 | 1220 | die: *Die, |
| 1216 | index: usize, | |
| 1217 | 1221 | pc_range: ?PcRange, |
| 1218 | 1222 | }; |
| 1219 | 1223 | |
| ... | ... | @@ -1244,21 +1248,19 @@ const FormValue = union(enum) { |
| 1244 | 1248 | ExprLoc: []u8, |
| 1245 | 1249 | Flag: bool, |
| 1246 | 1250 | SecOffset: u64, |
| 1247 | Ref: []u8, | |
| 1251 | Ref: u64, | |
| 1248 | 1252 | RefAddr: u64, |
| 1249 | RefSig8: u64, | |
| 1250 | 1253 | String: []u8, |
| 1251 | 1254 | StrPtr: u64, |
| 1252 | 1255 | }; |
| 1253 | 1256 | |
| 1254 | 1257 | const Constant = struct { |
| 1255 | payload: []u8, | |
| 1258 | payload: u64, | |
| 1256 | 1259 | signed: bool, |
| 1257 | 1260 | |
| 1258 | 1261 | fn asUnsignedLe(self: *const Constant) !u64 { |
| 1259 | if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; | |
| 1260 | 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 | }; |
| 1264 | 1266 | |
| ... | ... | @@ -1304,6 +1306,14 @@ const Die = struct { |
| 1304 | 1306 | }; |
| 1305 | 1307 | } |
| 1306 | 1308 | |
| 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 | 1317 | fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 { |
| 1308 | 1318 | const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; |
| 1309 | 1319 | return switch (form_value.*) { |
| ... | ... | @@ -1443,11 +1453,18 @@ fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) ! |
| 1443 | 1453 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 1444 | 1454 | } |
| 1445 | 1455 | |
| 1446 | fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue { | |
| 1456 | fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, comptime size: i32) !FormValue { | |
| 1447 | 1457 | return FormValue{ |
| 1448 | 1458 | .Const = Constant{ |
| 1449 | 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 | 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 | } |
| 1462 | 1479 | |
| 1463 | fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { | |
| 1464 | const buf = try readAllocBytes(allocator, in_stream, size); | |
| 1465 | return FormValue{ .Ref = buf }; | |
| 1466 | } | |
| 1467 | ||
| 1468 | fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue { | |
| 1469 | const block_len = try in_stream.readIntLittle(T); | |
| 1470 | return parseFormValueRefLen(allocator, in_stream, block_len); | |
| 1480 | fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue { | |
| 1481 | return FormValue{ | |
| 1482 | .Ref = switch (size) { | |
| 1483 | 1 => try in_stream.readIntLittle(u8), | |
| 1484 | 2 => try in_stream.readIntLittle(u16), | |
| 1485 | 4 => try in_stream.readIntLittle(u32), | |
| 1486 | 8 => try in_stream.readIntLittle(u64), | |
| 1487 | -1 => try leb.readULEB128(u64, in_stream), | |
| 1488 | else => unreachable, | |
| 1489 | }, | |
| 1490 | }; | |
| 1471 | 1491 | } |
| 1472 | 1492 | |
| 1473 | 1493 | fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue { |
| ... | ... | @@ -1477,7 +1497,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1477 | 1497 | DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), |
| 1478 | 1498 | DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4), |
| 1479 | 1499 | DW.FORM_block => x: { |
| 1480 | const block_len = try readULeb128(in_stream); | |
| 1500 | const block_len = try leb.readULEB128(usize, in_stream); | |
| 1481 | 1501 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 1482 | 1502 | }, |
| 1483 | 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 | 1505 | DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4), |
| 1486 | 1506 | DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8), |
| 1487 | 1507 | DW.FORM_udata, DW.FORM_sdata => { |
| 1488 | const block_len = try readULeb128(in_stream); | |
| 1489 | 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 | 1511 | DW.FORM_exprloc => { |
| 1493 | const size = try readULeb128(in_stream); | |
| 1512 | const size = try leb.readULEB128(usize, in_stream); | |
| 1494 | 1513 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 1495 | 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 | 1517 | DW.FORM_flag_present => FormValue{ .Flag = true }, |
| 1499 | 1518 | DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 1500 | 1519 | |
| 1501 | DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8), | |
| 1502 | DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16), | |
| 1503 | DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, u32), | |
| 1504 | DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, u64), | |
| 1505 | DW.FORM_ref_udata => { | |
| 1506 | const ref_len = try readULeb128(in_stream); | |
| 1507 | return parseFormValueRefLen(allocator, in_stream, ref_len); | |
| 1508 | }, | |
| 1520 | DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, 1), | |
| 1521 | DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, 2), | |
| 1522 | DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, 4), | |
| 1523 | DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, 8), | |
| 1524 | DW.FORM_ref_udata => parseFormValueRef(allocator, in_stream, -1), | |
| 1509 | 1525 | |
| 1510 | 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) }, | |
| 1512 | 1528 | |
| 1513 | 1529 | DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, |
| 1514 | 1530 | DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 1515 | 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 | 1533 | return parseFormValue(allocator, in_stream, child_form_id, is_64); |
| 1518 | 1534 | }, |
| 1519 | 1535 | else => error.InvalidDebugInfo, |
| ... | ... | @@ -1523,19 +1539,19 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1523 | 1539 | fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable { |
| 1524 | 1540 | var result = AbbrevTable.init(di.allocator()); |
| 1525 | 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 | 1543 | if (abbrev_code == 0) return result; |
| 1528 | 1544 | try result.append(AbbrevTableEntry{ |
| 1529 | 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 | 1547 | .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes, |
| 1532 | 1548 | .attrs = ArrayList(AbbrevAttr).init(di.allocator()), |
| 1533 | 1549 | }); |
| 1534 | 1550 | const attrs = &result.items[result.len - 1].attrs; |
| 1535 | 1551 | |
| 1536 | 1552 | while (true) { |
| 1537 | const attr_id = try readULeb128(di.dwarf_in_stream); | |
| 1538 | const form_id = try readULeb128(di.dwarf_in_stream); | |
| 1553 | const attr_id = try leb.readULEB128(u64, di.dwarf_in_stream); | |
| 1554 | const form_id = try leb.readULEB128(u64, di.dwarf_in_stream); | |
| 1539 | 1555 | if (attr_id == 0 and form_id == 0) break; |
| 1540 | 1556 | try attrs.append(AbbrevAttr{ |
| 1541 | 1557 | .attr_id = attr_id, |
| ... | ... | @@ -1568,8 +1584,28 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con |
| 1568 | 1584 | return null; |
| 1569 | 1585 | } |
| 1570 | 1586 | |
| 1587 | fn 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 | ||
| 1571 | 1607 | fn 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 | 1609 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; |
| 1574 | 1610 | |
| 1575 | 1611 | var result = Die{ |
| ... | ... | @@ -1682,9 +1718,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1682 | 1718 | while (true) { |
| 1683 | 1719 | const file_name = readStringMem(&ptr); |
| 1684 | 1720 | if (file_name.len == 0) break; |
| 1685 | const dir_index = try readULeb128Mem(&ptr); | |
| 1686 | const mtime = try readULeb128Mem(&ptr); | |
| 1687 | const len_bytes = try readULeb128Mem(&ptr); | |
| 1721 | const dir_index = try leb.readULEB128Mem(usize, &ptr); | |
| 1722 | const mtime = try leb.readULEB128Mem(usize, &ptr); | |
| 1723 | const len_bytes = try leb.readULEB128Mem(usize, &ptr); | |
| 1688 | 1724 | try file_entries.append(FileEntry{ |
| 1689 | 1725 | .file_name = file_name, |
| 1690 | 1726 | .dir_index = dir_index, |
| ... | ... | @@ -1698,7 +1734,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1698 | 1734 | const opcode = readByteMem(&ptr); |
| 1699 | 1735 | |
| 1700 | 1736 | if (opcode == DW.LNS_extended_op) { |
| 1701 | const op_size = try readULeb128Mem(&ptr); | |
| 1737 | const op_size = try leb.readULEB128Mem(u64, &ptr); | |
| 1702 | 1738 | if (op_size < 1) return error.InvalidDebugInfo; |
| 1703 | 1739 | var sub_op = readByteMem(&ptr); |
| 1704 | 1740 | switch (sub_op) { |
| ... | ... | @@ -1713,9 +1749,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1713 | 1749 | }, |
| 1714 | 1750 | DW.LNE_define_file => { |
| 1715 | 1751 | const file_name = readStringMem(&ptr); |
| 1716 | const dir_index = try readULeb128Mem(&ptr); | |
| 1717 | const mtime = try readULeb128Mem(&ptr); | |
| 1718 | const len_bytes = try readULeb128Mem(&ptr); | |
| 1752 | const dir_index = try leb.readULEB128Mem(usize, &ptr); | |
| 1753 | const mtime = try leb.readULEB128Mem(usize, &ptr); | |
| 1754 | const len_bytes = try leb.readULEB128Mem(usize, &ptr); | |
| 1719 | 1755 | try file_entries.append(FileEntry{ |
| 1720 | 1756 | .file_name = file_name, |
| 1721 | 1757 | .dir_index = dir_index, |
| ... | ... | @@ -1743,19 +1779,19 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1743 | 1779 | prog.basic_block = false; |
| 1744 | 1780 | }, |
| 1745 | 1781 | DW.LNS_advance_pc => { |
| 1746 | const arg = try readULeb128Mem(&ptr); | |
| 1782 | const arg = try leb.readULEB128Mem(u64, &ptr); | |
| 1747 | 1783 | prog.address += arg * minimum_instruction_length; |
| 1748 | 1784 | }, |
| 1749 | 1785 | DW.LNS_advance_line => { |
| 1750 | const arg = try readILeb128Mem(&ptr); | |
| 1786 | const arg = try leb.readILEB128Mem(i64, &ptr); | |
| 1751 | 1787 | prog.line += arg; |
| 1752 | 1788 | }, |
| 1753 | 1789 | DW.LNS_set_file => { |
| 1754 | const arg = try readULeb128Mem(&ptr); | |
| 1790 | const arg = try leb.readULEB128Mem(u64, &ptr); | |
| 1755 | 1791 | prog.file = arg; |
| 1756 | 1792 | }, |
| 1757 | 1793 | DW.LNS_set_column => { |
| 1758 | const arg = try readULeb128Mem(&ptr); | |
| 1794 | const arg = try leb.readULEB128Mem(u64, &ptr); | |
| 1759 | 1795 | prog.column = arg; |
| 1760 | 1796 | }, |
| 1761 | 1797 | DW.LNS_negate_stmt => { |
| ... | ... | @@ -1787,182 +1823,292 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1787 | 1823 | |
| 1788 | 1824 | fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo { |
| 1789 | 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); | |
| 1790 | 1827 | |
| 1791 | const debug_line_end = di.debug_line.offset + di.debug_line.size; | |
| 1792 | var this_offset = di.debug_line.offset; | |
| 1793 | var this_index: usize = 0; | |
| 1828 | assert(line_info_offset < di.debug_line.size); | |
| 1794 | 1829 | |
| 1795 | while (this_offset < debug_line_end) : (this_index += 1) { | |
| 1796 | try di.dwarf_seekable_stream.seekTo(this_offset); | |
| 1830 | try di.dwarf_seekable_stream.seekTo(di.debug_line.offset + line_info_offset); | |
| 1797 | 1831 | |
| 1798 | 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); | |
| 1800 | if (unit_length == 0) return error.MissingDebugInfo; | |
| 1801 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | |
| 1832 | var is_64: bool = undefined; | |
| 1833 | const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); | |
| 1834 | if (unit_length == 0) { | |
| 1835 | return error.MissingDebugInfo; | |
| 1836 | } | |
| 1837 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | |
| 1802 | 1838 | |
| 1803 | if (compile_unit.index != this_index) { | |
| 1804 | this_offset += next_offset; | |
| 1805 | continue; | |
| 1806 | } | |
| 1839 | const version = try di.dwarf_in_stream.readInt(u16, di.endian); | |
| 1840 | // TODO support 3 and 5 | |
| 1841 | if (version != 2 and version != 4) return error.InvalidDebugInfo; | |
| 1807 | 1842 | |
| 1808 | const version = try di.dwarf_in_stream.readInt(u16, di.endian); | |
| 1809 | // TODO support 3 and 5 | |
| 1810 | if (version != 2 and version != 4) return error.InvalidDebugInfo; | |
| 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); | |
| 1844 | const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; | |
| 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; | |
| 1811 | 1859 | |
| 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); | |
| 1813 | const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; | |
| 1860 | const opcode_base = try di.dwarf_in_stream.readByte(); | |
| 1814 | 1861 | |
| 1815 | const minimum_instruction_length = try di.dwarf_in_stream.readByte(); | |
| 1816 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; | |
| 1862 | const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); | |
| 1817 | 1863 | |
| 1818 | if (version >= 4) { | |
| 1819 | // maximum_operations_per_instruction | |
| 1820 | _ = try di.dwarf_in_stream.readByte(); | |
| 1864 | { | |
| 1865 | var i: usize = 0; | |
| 1866 | while (i < opcode_base - 1) : (i += 1) { | |
| 1867 | standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); | |
| 1821 | 1868 | } |
| 1869 | } | |
| 1822 | 1870 | |
| 1823 | const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; | |
| 1824 | const line_base = try di.dwarf_in_stream.readByteSigned(); | |
| 1871 | var include_directories = ArrayList([]u8).init(di.allocator()); | |
| 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); | |
| 1825 | 1881 | |
| 1826 | const line_range = try di.dwarf_in_stream.readByte(); | |
| 1827 | if (line_range == 0) return error.InvalidDebugInfo; | |
| 1882 | while (true) { | |
| 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 | } | |
| 1828 | 1895 | |
| 1829 | const opcode_base = try di.dwarf_in_stream.readByte(); | |
| 1896 | try di.dwarf_seekable_stream.seekTo(prog_start_offset); | |
| 1830 | 1897 | |
| 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(); | |
| 1832 | 1900 | |
| 1833 | { | |
| 1834 | var i: usize = 0; | |
| 1835 | while (i < opcode_base - 1) : (i += 1) { | |
| 1836 | standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); | |
| 1901 | if (opcode == DW.LNS_extended_op) { | |
| 1902 | const op_size = try leb.readULEB128(u64, di.dwarf_in_stream); | |
| 1903 | if (op_size < 1) return error.InvalidDebugInfo; | |
| 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 | } | |
| 1839 | 1986 | |
| 1840 | var include_directories = ArrayList([]u8).init(di.allocator()); | |
| 1841 | try include_directories.append(compile_unit_cwd); | |
| 1842 | while (true) { | |
| 1843 | const dir = try di.readString(); | |
| 1844 | if (dir.len == 0) break; | |
| 1845 | try include_directories.append(dir); | |
| 1846 | } | |
| 1987 | return error.MissingDebugInfo; | |
| 1988 | } | |
| 1847 | 1989 | |
| 1848 | var file_entries = ArrayList(FileEntry).init(di.allocator()); | |
| 1849 | var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address); | |
| 1990 | const Func = struct { | |
| 1991 | pc_range: ?PcRange, | |
| 1992 | name: ?[]u8, | |
| 1993 | }; | |
| 1850 | 1994 | |
| 1851 | while (true) { | |
| 1852 | const file_name = try di.readString(); | |
| 1853 | if (file_name.len == 0) break; | |
| 1854 | const dir_index = try readULeb128(di.dwarf_in_stream); | |
| 1855 | const mtime = try readULeb128(di.dwarf_in_stream); | |
| 1856 | const len_bytes = try readULeb128(di.dwarf_in_stream); | |
| 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 | }); | |
| 1995 | fn getSymbolNameDwarf(di: *DwarfInfo, address: u64) ?[]const u8 { | |
| 1996 | for (di.func_list.toSliceConst()) |*func| { | |
| 1997 | if (func.pc_range) |range| { | |
| 1998 | if (address >= range.start and address < range.end) { | |
| 1999 | return func.name; | |
| 2000 | } | |
| 1863 | 2001 | } |
| 2002 | } | |
| 2003 | ||
| 2004 | return null; | |
| 2005 | } | |
| 1864 | 2006 | |
| 1865 | try di.dwarf_seekable_stream.seekTo(prog_start_offset); | |
| 2007 | fn 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; | |
| 1866 | 2010 | |
| 1867 | while (true) { | |
| 1868 | const opcode = try di.dwarf_in_stream.readByte(); | |
| 1869 | ||
| 1870 | if (opcode == DW.LNS_extended_op) { | |
| 1871 | const op_size = try readULeb128(di.dwarf_in_stream); | |
| 1872 | if (op_size < 1) return error.InvalidDebugInfo; | |
| 1873 | var sub_op = try di.dwarf_in_stream.readByte(); | |
| 1874 | switch (sub_op) { | |
| 1875 | DW.LNE_end_sequence => { | |
| 1876 | prog.end_sequence = true; | |
| 1877 | if (try prog.checkLineMatch()) |info| return info; | |
| 1878 | return error.MissingDebugInfo; | |
| 1879 | }, | |
| 1880 | DW.LNE_set_address => { | |
| 1881 | const addr = try di.dwarf_in_stream.readInt(usize, di.endian); | |
| 1882 | prog.address = addr; | |
| 1883 | }, | |
| 1884 | DW.LNE_define_file => { | |
| 1885 | const file_name = try di.readString(); | |
| 1886 | const dir_index = try readULeb128(di.dwarf_in_stream); | |
| 1887 | const mtime = try readULeb128(di.dwarf_in_stream); | |
| 1888 | const len_bytes = try readULeb128(di.dwarf_in_stream); | |
| 1889 | try file_entries.append(FileEntry{ | |
| 1890 | .file_name = file_name, | |
| 1891 | .dir_index = dir_index, | |
| 1892 | .mtime = mtime, | |
| 1893 | .len_bytes = len_bytes, | |
| 1894 | }); | |
| 1895 | }, | |
| 1896 | else => { | |
| 1897 | const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; | |
| 1898 | try di.dwarf_seekable_stream.seekForward(fwd_amt); | |
| 1899 | }, | |
| 1900 | } | |
| 1901 | } else if (opcode >= opcode_base) { | |
| 1902 | // special opcodes | |
| 1903 | const adjusted_opcode = opcode - opcode_base; | |
| 1904 | const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); | |
| 1905 | const inc_line = i32(line_base) + i32(adjusted_opcode % line_range); | |
| 1906 | prog.line += inc_line; | |
| 1907 | prog.address += inc_addr; | |
| 1908 | if (try prog.checkLineMatch()) |info| return info; | |
| 1909 | prog.basic_block = false; | |
| 1910 | } else { | |
| 1911 | switch (opcode) { | |
| 1912 | DW.LNS_copy => { | |
| 1913 | if (try prog.checkLineMatch()) |info| return info; | |
| 1914 | prog.basic_block = false; | |
| 1915 | }, | |
| 1916 | DW.LNS_advance_pc => { | |
| 1917 | const arg = try readULeb128(di.dwarf_in_stream); | |
| 1918 | prog.address += arg * minimum_instruction_length; | |
| 1919 | }, | |
| 1920 | DW.LNS_advance_line => { | |
| 1921 | const arg = try readILeb128(di.dwarf_in_stream); | |
| 1922 | prog.line += arg; | |
| 1923 | }, | |
| 1924 | DW.LNS_set_file => { | |
| 1925 | const arg = try readULeb128(di.dwarf_in_stream); | |
| 1926 | prog.file = arg; | |
| 1927 | }, | |
| 1928 | DW.LNS_set_column => { | |
| 1929 | const arg = try readULeb128(di.dwarf_in_stream); | |
| 1930 | prog.column = arg; | |
| 1931 | }, | |
| 1932 | DW.LNS_negate_stmt => { | |
| 1933 | prog.is_stmt = !prog.is_stmt; | |
| 1934 | }, | |
| 1935 | DW.LNS_set_basic_block => { | |
| 1936 | prog.basic_block = true; | |
| 1937 | }, | |
| 1938 | DW.LNS_const_add_pc => { | |
| 1939 | const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range); | |
| 1940 | prog.address += inc_addr; | |
| 1941 | }, | |
| 1942 | DW.LNS_fixed_advance_pc => { | |
| 1943 | const arg = try di.dwarf_in_stream.readInt(u16, di.endian); | |
| 1944 | prog.address += arg; | |
| 1945 | }, | |
| 1946 | DW.LNS_set_prologue_end => {}, | |
| 1947 | else => { | |
| 1948 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; | |
| 1949 | const len_bytes = standard_opcode_lengths[opcode - 1]; | |
| 1950 | try di.dwarf_seekable_stream.seekForward(len_bytes); | |
| 1951 | }, | |
| 1952 | } | |
| 2011 | while (this_unit_offset < debug_info_end) { | |
| 2012 | try di.dwarf_seekable_stream.seekTo(this_unit_offset); | |
| 2013 | ||
| 2014 | var is_64: bool = undefined; | |
| 2015 | const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); | |
| 2016 | if (unit_length == 0) return; | |
| 2017 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | |
| 2018 | ||
| 2019 | const version = try di.dwarf_in_stream.readInt(u16, di.endian); | |
| 2020 | if (version < 2 or version > 5) return error.InvalidDebugInfo; | |
| 2021 | ||
| 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); | |
| 2023 | ||
| 2024 | const address_size = try di.dwarf_in_stream.readByte(); | |
| 2025 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; | |
| 2026 | ||
| 2027 | const compile_unit_pos = try di.dwarf_seekable_stream.getPos(); | |
| 2028 | const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset); | |
| 2029 | ||
| 2030 | try di.dwarf_seekable_stream.seekTo(compile_unit_pos); | |
| 2031 | ||
| 2032 | const next_unit_pos = this_unit_offset + next_offset; | |
| 2033 | ||
| 2034 | while ((try di.dwarf_seekable_stream.getPos()) < next_unit_pos) { | |
| 2035 | const die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse continue; | |
| 2036 | const after_die_offset = try di.dwarf_seekable_stream.getPos(); | |
| 2037 | ||
| 2038 | switch (die_obj.tag_id) { | |
| 2039 | DW.TAG_subprogram, DW.TAG_inlined_subroutine, DW.TAG_subroutine, DW.TAG_entry_point => { | |
| 2040 | const fn_name = x: { | |
| 2041 | var depth: i32 = 3; | |
| 2042 | var this_die_obj = die_obj; | |
| 2043 | // Prenvent endless loops | |
| 2044 | while (depth > 0) : (depth -= 1) { | |
| 2045 | if (this_die_obj.getAttr(DW.AT_name)) |_| { | |
| 2046 | const name = try this_die_obj.getAttrString(di, DW.AT_name); | |
| 2047 | break :x name; | |
| 2048 | } else if (this_die_obj.getAttr(DW.AT_abstract_origin)) |ref| { | |
| 2049 | // Follow the DIE it points to and repeat | |
| 2050 | const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin); | |
| 2051 | if (ref_offset > next_offset) return error.InvalidDebugInfo; | |
| 2052 | try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset); | |
| 2053 | this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; | |
| 2054 | } else if (this_die_obj.getAttr(DW.AT_specification)) |ref| { | |
| 2055 | // Follow the DIE it points to and repeat | |
| 2056 | const ref_offset = try this_die_obj.getAttrRef(DW.AT_specification); | |
| 2057 | if (ref_offset > next_offset) return error.InvalidDebugInfo; | |
| 2058 | try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset); | |
| 2059 | this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; | |
| 2060 | } else { | |
| 2061 | break :x null; | |
| 2062 | } | |
| 2063 | } | |
| 2064 | ||
| 2065 | break :x null; | |
| 2066 | }; | |
| 2067 | ||
| 2068 | const pc_range = x: { | |
| 2069 | if (die_obj.getAttrAddr(DW.AT_low_pc)) |low_pc| { | |
| 2070 | if (die_obj.getAttr(DW.AT_high_pc)) |high_pc_value| { | |
| 2071 | const pc_end = switch (high_pc_value.*) { | |
| 2072 | FormValue.Address => |value| value, | |
| 2073 | FormValue.Const => |value| b: { | |
| 2074 | const offset = try value.asUnsignedLe(); | |
| 2075 | break :b (low_pc + offset); | |
| 2076 | }, | |
| 2077 | else => return error.InvalidDebugInfo, | |
| 2078 | }; | |
| 2079 | break :x PcRange{ | |
| 2080 | .start = low_pc, | |
| 2081 | .end = pc_end, | |
| 2082 | }; | |
| 2083 | } else { | |
| 2084 | break :x null; | |
| 2085 | } | |
| 2086 | } else |err| { | |
| 2087 | if (err != error.MissingDebugInfo) return err; | |
| 2088 | break :x null; | |
| 2089 | } | |
| 2090 | }; | |
| 2091 | ||
| 2092 | try di.func_list.append(Func{ | |
| 2093 | .name = fn_name, | |
| 2094 | .pc_range = pc_range, | |
| 2095 | }); | |
| 2096 | }, | |
| 2097 | else => { | |
| 2098 | continue; | |
| 2099 | }, | |
| 1953 | 2100 | } |
| 2101 | ||
| 2102 | try di.dwarf_seekable_stream.seekTo(after_die_offset); | |
| 1954 | 2103 | } |
| 1955 | 2104 | |
| 1956 | this_offset += next_offset; | |
| 2105 | this_unit_offset += next_offset; | |
| 1957 | 2106 | } |
| 1958 | ||
| 1959 | return error.MissingDebugInfo; | |
| 1960 | 2107 | } |
| 1961 | 2108 | |
| 1962 | 2109 | fn scanAllCompileUnits(di: *DwarfInfo) !void { |
| 1963 | 2110 | const debug_info_end = di.debug_info.offset + di.debug_info.size; |
| 1964 | 2111 | var this_unit_offset = di.debug_info.offset; |
| 1965 | var cu_index: usize = 0; | |
| 1966 | 2112 | |
| 1967 | 2113 | while (this_unit_offset < debug_info_end) { |
| 1968 | 2114 | try di.dwarf_seekable_stream.seekTo(this_unit_offset); |
| ... | ... | @@ -2019,11 +2165,9 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { |
| 2019 | 2165 | .is_64 = is_64, |
| 2020 | 2166 | .pc_range = pc_range, |
| 2021 | 2167 | .die = compile_unit_die, |
| 2022 | .index = cu_index, | |
| 2023 | 2168 | }); |
| 2024 | 2169 | |
| 2025 | 2170 | this_unit_offset += next_offset; |
| 2026 | cu_index += 1; | |
| 2027 | 2171 | } |
| 2028 | 2172 | } |
| 2029 | 2173 | |
| ... | ... | @@ -2098,52 +2242,6 @@ fn readStringMem(ptr: *[*]const u8) []const u8 { |
| 2098 | 2242 | return result; |
| 2099 | 2243 | } |
| 2100 | 2244 | |
| 2101 | fn 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 | } | |
| 2124 | fn 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 | ||
| 2147 | 2245 | fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 { |
| 2148 | 2246 | const first_32_bits = try in_stream.readIntLittle(u32); |
| 2149 | 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 | 2253 | } |
| 2156 | 2254 | } |
| 2157 | 2255 | |
| 2158 | fn 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 | ||
| 2177 | fn 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 | 2256 | /// This should only be used in temporary test programs. |
| 2199 | 2257 | pub const global_allocator = &global_fixed_allocator.allocator; |
| 2200 | 2258 | var 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 | 10 | internal_allocator: *mem.Allocator, |
| 11 | 11 | allocated_bytes: usize, |
| 12 | 12 | freed_bytes: usize, |
| 13 | allocations: usize, | |
| 13 | 14 | deallocations: usize, |
| 14 | 15 | |
| 15 | 16 | pub fn init(allocator: *mem.Allocator, fail_index: usize) FailingAllocator { |
| ... | ... | @@ -19,6 +20,7 @@ pub const FailingAllocator = struct { |
| 19 | 20 | .index = 0, |
| 20 | 21 | .allocated_bytes = 0, |
| 21 | 22 | .freed_bytes = 0, |
| 23 | .allocations = 0, | |
| 22 | 24 | .deallocations = 0, |
| 23 | 25 | .allocator = mem.Allocator{ |
| 24 | 26 | .reallocFn = realloc, |
| ... | ... | @@ -39,19 +41,25 @@ pub const FailingAllocator = struct { |
| 39 | 41 | new_size, |
| 40 | 42 | new_align, |
| 41 | 43 | ); |
| 42 | if (new_size <= old_mem.len) { | |
| 44 | if (new_size < old_mem.len) { | |
| 43 | 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 | 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 | 53 | self.index += 1; |
| 49 | 54 | return result; |
| 50 | 55 | } |
| 51 | 56 | |
| 52 | 57 | fn shrink(allocator: *mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { |
| 53 | 58 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); |
| 54 | self.freed_bytes += old_mem.len - new_size; | |
| 55 | return self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align); | |
| 59 | const r = 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const testing = std.testing; | |
| 3 | ||
| 4 | pub 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 | ||
| 29 | pub 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 | ||
| 57 | pub 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 | ||
| 89 | pub 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 | ||
| 123 | fn 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 | ||
| 128 | fn 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 | ||
| 133 | fn 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 | ||
| 142 | fn 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 | ||
| 151 | test "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 | ||
| 193 | test "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 | 13 | pub const TAG_compile_unit = 0x11; |
| 14 | 14 | pub const TAG_string_type = 0x12; |
| 15 | 15 | pub const TAG_structure_type = 0x13; |
| 16 | pub const TAG_subroutine = 0x14; | |
| 16 | 17 | pub const TAG_subroutine_type = 0x15; |
| 17 | 18 | pub const TAG_typedef = 0x16; |
| 18 | 19 | pub const TAG_union_type = 0x17; |
| ... | ... | @@ -241,6 +242,9 @@ pub const AT_const_expr = 0x6c; |
| 241 | 242 | pub const AT_enum_class = 0x6d; |
| 242 | 243 | pub const AT_linkage_name = 0x6e; |
| 243 | 244 | |
| 245 | // DWARF 5 | |
| 246 | pub const AT_alignment = 0x88; | |
| 247 | ||
| 244 | 248 | pub const AT_lo_user = 0x2000; // Implementation-defined range start. |
| 245 | 249 | pub const AT_hi_user = 0x3fff; // Implementation-defined range end. |
| 246 | 250 |
std/dynamic_library.zig+83| ... | ... | @@ -19,6 +19,89 @@ pub const DynLib = switch (builtin.os) { |
| 19 | 19 | else => void, |
| 20 | 20 | }; |
| 21 | 21 | |
| 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. | |
| 27 | const 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 | ||
| 51 | const RDebug = extern struct { | |
| 52 | r_version: i32, | |
| 53 | r_map: ?*LinkMap, | |
| 54 | r_brk: usize, | |
| 55 | r_ldbase: usize, | |
| 56 | }; | |
| 57 | ||
| 58 | fn 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 | ||
| 67 | pub 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 | ||
| 22 | 105 | pub const LinuxDynLib = struct { |
| 23 | 106 | elf_lib: ElfLib, |
| 24 | 107 | fd: i32, |
std/elf.zig+5| ... | ... | @@ -877,6 +877,11 @@ pub const Phdr = switch (@sizeOf(usize)) { |
| 877 | 877 | 8 => Elf64_Phdr, |
| 878 | 878 | else => @compileError("expected pointer size of 32 or 64"), |
| 879 | 879 | }; |
| 880 | pub const Dyn = switch (@sizeOf(usize)) { | |
| 881 | 4 => Elf32_Dyn, | |
| 882 | 8 => Elf64_Dyn, | |
| 883 | else => @compileError("expected pointer size of 32 or 64"), | |
| 884 | }; | |
| 880 | 885 | pub const Shdr = switch (@sizeOf(usize)) { |
| 881 | 886 | 4 => Elf32_Shdr, |
| 882 | 887 | 8 => Elf64_Shdr, |
std/fmt.zig+96-12| ... | ... | @@ -8,6 +8,8 @@ const builtin = @import("builtin"); |
| 8 | 8 | const errol = @import("fmt/errol.zig"); |
| 9 | 9 | const lossyCast = std.math.lossyCast; |
| 10 | 10 | |
| 11 | pub const default_max_depth = 3; | |
| 12 | ||
| 11 | 13 | /// Renders fmt string with args, calling output with slices of bytes. |
| 12 | 14 | /// If `output` returns an error, the error is returned from `format` and |
| 13 | 15 | /// `output` is not called again. |
| ... | ... | @@ -49,7 +51,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context), |
| 49 | 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 | 55 | next_arg += 1; |
| 54 | 56 | state = State.Start; |
| 55 | 57 | start_index = i + 1; |
| ... | ... | @@ -69,7 +71,7 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context), |
| 69 | 71 | State.FormatString => switch (c) { |
| 70 | 72 | '}' => { |
| 71 | 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 | 75 | next_arg += 1; |
| 74 | 76 | state = State.Start; |
| 75 | 77 | start_index = i + 1; |
| ... | ... | @@ -108,6 +110,7 @@ pub fn formatType( |
| 108 | 110 | context: var, |
| 109 | 111 | comptime Errors: type, |
| 110 | 112 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 113 | max_depth: usize, | |
| 111 | 114 | ) Errors!void { |
| 112 | 115 | const T = @typeOf(value); |
| 113 | 116 | switch (@typeInfo(T)) { |
| ... | ... | @@ -122,16 +125,16 @@ pub fn formatType( |
| 122 | 125 | }, |
| 123 | 126 | builtin.TypeId.Optional => { |
| 124 | 127 | if (value) |payload| { |
| 125 | return formatType(payload, fmt, context, Errors, output); | |
| 128 | return formatType(payload, fmt, context, Errors, output, max_depth); | |
| 126 | 129 | } else { |
| 127 | 130 | return output(context, "null"); |
| 128 | 131 | } |
| 129 | 132 | }, |
| 130 | 133 | builtin.TypeId.ErrorUnion => { |
| 131 | 134 | if (value) |payload| { |
| 132 | return formatType(payload, fmt, context, Errors, output); | |
| 135 | return formatType(payload, fmt, context, Errors, output, max_depth); | |
| 133 | 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 | 140 | builtin.TypeId.ErrorSet => { |
| ... | ... | @@ -164,10 +167,13 @@ pub fn formatType( |
| 164 | 167 | switch (comptime @typeId(T)) { |
| 165 | 168 | builtin.TypeId.Enum => { |
| 166 | 169 | try output(context, "."); |
| 167 | try formatType(@tagName(value), "", context, Errors, output); | |
| 170 | try formatType(@tagName(value), "", context, Errors, output, max_depth); | |
| 168 | 171 | return; |
| 169 | 172 | }, |
| 170 | 173 | builtin.TypeId.Struct => { |
| 174 | if (max_depth == 0) { | |
| 175 | return output(context, "{ ... }"); | |
| 176 | } | |
| 171 | 177 | comptime var field_i = 0; |
| 172 | 178 | inline while (field_i < @memberCount(T)) : (field_i += 1) { |
| 173 | 179 | if (field_i == 0) { |
| ... | ... | @@ -177,11 +183,14 @@ pub fn formatType( |
| 177 | 183 | } |
| 178 | 184 | try output(context, @memberName(T, field_i)); |
| 179 | 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 | 188 | try output(context, " }"); |
| 183 | 189 | }, |
| 184 | 190 | builtin.TypeId.Union => { |
| 191 | if (max_depth == 0) { | |
| 192 | return output(context, "{ ... }"); | |
| 193 | } | |
| 185 | 194 | const info = @typeInfo(T).Union; |
| 186 | 195 | if (info.tag_type) |UnionTagType| { |
| 187 | 196 | try output(context, "{ ."); |
| ... | ... | @@ -189,7 +198,7 @@ pub fn formatType( |
| 189 | 198 | try output(context, " = "); |
| 190 | 199 | inline for (info.fields) |u_field| { |
| 191 | 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 | 204 | try output(context, " }"); |
| ... | ... | @@ -210,7 +219,7 @@ pub fn formatType( |
| 210 | 219 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); |
| 211 | 220 | }, |
| 212 | 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 | 224 | else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)), |
| 216 | 225 | }, |
| ... | ... | @@ -986,17 +995,17 @@ test "fmt.format" { |
| 986 | 995 | { |
| 987 | 996 | var buf1: [32]u8 = undefined; |
| 988 | 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 | 999 | var res = buf1[0 .. buf1.len - context.remaining.len]; |
| 991 | 1000 | testing.expect(mem.eql(u8, res, "1234")); |
| 992 | 1001 | |
| 993 | 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 | 1004 | res = buf1[0 .. buf1.len - context.remaining.len]; |
| 996 | 1005 | testing.expect(mem.eql(u8, res, "a")); |
| 997 | 1006 | |
| 998 | 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 | 1009 | res = buf1[0 .. buf1.len - context.remaining.len]; |
| 1001 | 1010 | testing.expect(mem.eql(u8, res, "1100")); |
| 1002 | 1011 | } |
| ... | ... | @@ -1364,6 +1373,20 @@ test "fmt.format" { |
| 1364 | 1373 | |
| 1365 | 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 | 1390 | //print bytes as hex |
| 1368 | 1391 | { |
| 1369 | 1392 | const some_bytes = "\xCA\xFE\xBA\xBE"; |
| ... | ... | @@ -1449,3 +1472,64 @@ test "fmt.formatIntValue with comptime_int" { |
| 1449 | 1472 | try formatIntValue(value, "", &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append); |
| 1450 | 1473 | assert(mem.eql(u8, buf.toSlice(), "123456789123456789")); |
| 1451 | 1474 | } |
| 1475 | ||
| 1476 | test "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 | 118 | }; |
| 119 | 119 | } |
| 120 | 120 | self.incrementModificationCount(); |
| 121 | try self.ensureCapacity(); | |
| 121 | try self.autoCapacity(); | |
| 122 | 122 | const put_result = self.internalPut(key); |
| 123 | 123 | assert(put_result.old_kv == null); |
| 124 | 124 | return GetOrPutResult{ |
| ... | ... | @@ -135,15 +135,37 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 135 | 135 | return res.kv; |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | fn ensureCapacity(self: *Self) !void { | |
| 139 | if (self.entries.len == 0) { | |
| 140 | return self.initCapacity(16); | |
| 138 | fn optimizedCapacity(expected_count: usize) usize { | |
| 139 | // ensure that the hash map will be at most 60% full if | |
| 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 | } |
| 142 | 164 | |
| 143 | // if we get too full (60%), double the capacity | |
| 144 | if (self.size * 5 >= self.entries.len * 3) { | |
| 145 | const old_entries = self.entries; | |
| 146 | try self.initCapacity(self.entries.len * 2); | |
| 165 | const old_entries = self.entries; | |
| 166 | try self.initCapacity(new_capacity); | |
| 167 | self.incrementModificationCount(); | |
| 168 | if (old_entries.len > 0) { | |
| 147 | 169 | // dump all of the old elements into the new table |
| 148 | 170 | for (old_entries) |*old_entry| { |
| 149 | 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 | 178 | |
| 157 | 179 | /// Returns the kv pair that was already there. |
| 158 | 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 | 187 | self.incrementModificationCount(); |
| 160 | try self.ensureCapacity(); | |
| 161 | 188 | |
| 162 | 189 | const put_result = self.internalPut(key); |
| 163 | 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 | 202 | return hm.get(key) != null; |
| 176 | 203 | } |
| 177 | 204 | |
| 178 | pub fn remove(hm: *Self, key: K) ?*KV { | |
| 205 | pub fn remove(hm: *Self, key: K) ?KV { | |
| 179 | 206 | if (hm.entries.len == 0) return null; |
| 180 | 207 | hm.incrementModificationCount(); |
| 181 | 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 | 216 | |
| 190 | 217 | if (!eql(entry.kv.key, key)) continue; |
| 191 | 218 | |
| 219 | const removed_kv = entry.kv; | |
| 192 | 220 | while (roll_over < hm.entries.len) : (roll_over += 1) { |
| 193 | 221 | const next_index = (start_index + roll_over + 1) % hm.entries.len; |
| 194 | 222 | const next_entry = &hm.entries[next_index]; |
| 195 | 223 | if (!next_entry.used or next_entry.distance_from_start_index == 0) { |
| 196 | 224 | entry.used = false; |
| 197 | 225 | hm.size -= 1; |
| 198 | return &entry.kv; | |
| 226 | return removed_kv; | |
| 199 | 227 | } |
| 200 | 228 | entry.* = next_entry.*; |
| 201 | 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 | 254 | return other; |
| 227 | 255 | } |
| 228 | 256 | |
| 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 | 267 | fn initCapacity(hm: *Self, capacity: usize) !void { |
| 230 | 268 | hm.entries = try hm.allocator.alloc(Entry, capacity); |
| 231 | 269 | hm.size = 0; |
| ... | ... | @@ -371,7 +409,10 @@ test "basic hash map usage" { |
| 371 | 409 | |
| 372 | 410 | testing.expect(map.contains(2)); |
| 373 | 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 | 416 | testing.expect(map.remove(2) == null); |
| 376 | 417 | testing.expect(map.get(2) == null); |
| 377 | 418 | } |
| ... | ... | @@ -423,6 +464,24 @@ test "iterator hash map" { |
| 423 | 464 | testing.expect(entry.value == values[0]); |
| 424 | 465 | } |
| 425 | 466 | |
| 467 | test "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 | ||
| 426 | 485 | pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) { |
| 427 | 486 | return struct { |
| 428 | 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 | 34 | /// Thread-safe and lock-free. |
| 35 | 35 | pub const DirectAllocator = struct { |
| 36 | 36 | allocator: Allocator, |
| 37 | heap_handle: ?HeapHandle, | |
| 38 | ||
| 39 | const HeapHandle = if (builtin.os == Os.windows) os.windows.HANDLE else void; | |
| 40 | 37 | |
| 41 | 38 | pub fn init() DirectAllocator { |
| 42 | 39 | return DirectAllocator{ |
| ... | ... | @@ -44,21 +41,15 @@ pub const DirectAllocator = struct { |
| 44 | 41 | .reallocFn = realloc, |
| 45 | 42 | .shrinkFn = shrink, |
| 46 | 43 | }, |
| 47 | .heap_handle = if (builtin.os == Os.windows) null else {}, | |
| 48 | 44 | }; |
| 49 | 45 | } |
| 50 | 46 | |
| 51 | 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 | } | |
| 47 | pub fn deinit(self: *DirectAllocator) void {} | |
| 59 | 48 | |
| 60 | 49 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 { |
| 61 | 50 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 51 | if (n == 0) | |
| 52 | return (([*]u8)(undefined))[0..0]; | |
| 62 | 53 | |
| 63 | 54 | switch (builtin.os) { |
| 64 | 55 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { |
| ... | ... | @@ -68,39 +59,76 @@ pub const DirectAllocator = struct { |
| 68 | 59 | if (addr == p.MAP_FAILED) return error.OutOfMemory; |
| 69 | 60 | if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n]; |
| 70 | 61 | |
| 71 | const aligned_addr = (addr & ~usize(alignment - 1)) + 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); | |
| 62 | const aligned_addr = mem.alignForward(addr, alignment); | |
| 83 | 63 | |
| 84 | // It is impossible that there is an unoccupied page at the top of our | |
| 85 | // mmap. | |
| 64 | // Unmap the extra bytes that were only requested in order to guarantee | |
| 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 | } | |
| 86 | 78 | |
| 87 | 79 | return @intToPtr([*]u8, aligned_addr)[0..n]; |
| 88 | 80 | }, |
| 89 | Os.windows => { | |
| 90 | const amt = n + alignment + @sizeOf(usize); | |
| 91 | const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, builtin.AtomicOrder.SeqCst); | |
| 92 | const heap_handle = optional_heap_handle orelse blk: { | |
| 93 | const hh = os.windows.HeapCreate(0, amt, 0) orelse return error.OutOfMemory; | |
| 94 | const other_hh = @cmpxchgStrong(?HeapHandle, &self.heap_handle, null, hh, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse break :blk hh; | |
| 95 | _ = os.windows.HeapDestroy(hh); | |
| 96 | break :blk other_hh.?; // can't be null because of the cmpxchg | |
| 97 | }; | |
| 98 | const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory; | |
| 99 | const root_addr = @ptrToInt(ptr); | |
| 100 | const adjusted_addr = mem.alignForward(root_addr, alignment); | |
| 101 | const record_addr = adjusted_addr + n; | |
| 102 | @intToPtr(*align(1) usize, record_addr).* = root_addr; | |
| 103 | return @intToPtr([*]u8, adjusted_addr)[0..n]; | |
| 81 | .windows => { | |
| 82 | const w = os.windows; | |
| 83 | ||
| 84 | // Although officially it's at least aligned to page boundary, | |
| 85 | // Windows is known to reserve pages on a 64K boundary. It's | |
| 86 | // even more likely that the requested alignment is <= 64K than | |
| 87 | // 4K, so we're just allocating blindly and hoping for the best. | |
| 88 | // see https://devblogs.microsoft.com/oldnewthing/?p=42223 | |
| 89 | const addr = w.VirtualAlloc( | |
| 90 | null, | |
| 91 | n, | |
| 92 | w.MEM_COMMIT | w.MEM_RESERVE, | |
| 93 | w.PAGE_READWRITE, | |
| 94 | ) orelse return error.OutOfMemory; | |
| 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 | 133 | else => @compileError("Unsupported OS"), |
| 106 | 134 | } |
| ... | ... | @@ -118,13 +146,31 @@ pub const DirectAllocator = struct { |
| 118 | 146 | } |
| 119 | 147 | return old_mem[0..new_size]; |
| 120 | 148 | }, |
| 121 | Os.windows => return realloc(allocator, old_mem, old_align, new_size, new_align) catch { | |
| 122 | const old_adjusted_addr = @ptrToInt(old_mem.ptr); | |
| 123 | const old_record_addr = old_adjusted_addr + old_mem.len; | |
| 124 | const root_addr = @intToPtr(*align(1) usize, old_record_addr).*; | |
| 125 | const old_ptr = @intToPtr(*c_void, root_addr); | |
| 126 | const new_record_addr = old_record_addr - new_size + old_mem.len; | |
| 127 | @intToPtr(*align(1) usize, new_record_addr).* = root_addr; | |
| 149 | .windows => { | |
| 150 | const w = os.windows; | |
| 151 | if (new_size == 0) { | |
| 152 | // From the docs: | |
| 153 | // "If the dwFreeType parameter is MEM_RELEASE, this parameter | |
| 154 | // must be 0 (zero). The function frees the entire region that | |
| 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 | 174 | return old_mem[0..new_size]; |
| 129 | 175 | }, |
| 130 | 176 | else => @compileError("Unsupported OS"), |
| ... | ... | @@ -138,36 +184,168 @@ pub const DirectAllocator = struct { |
| 138 | 184 | return shrink(allocator, old_mem, old_align, new_size, new_align); |
| 139 | 185 | } |
| 140 | 186 | const result = try alloc(allocator, new_size, new_align); |
| 141 | mem.copy(u8, result, old_mem); | |
| 142 | _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len); | |
| 187 | if (old_mem.len != 0) { | |
| 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 | 191 | return result; |
| 144 | 192 | }, |
| 145 | Os.windows => { | |
| 146 | if (old_mem.len == 0) return alloc(allocator, new_size, new_align); | |
| 193 | .windows => { | |
| 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; | |
| 147 | 213 | |
| 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 | ||
| 252 | pub 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 | 299 | const old_adjusted_addr = @ptrToInt(old_mem.ptr); |
| 150 | 300 | const old_record_addr = old_adjusted_addr + old_mem.len; |
| 151 | 301 | const root_addr = @intToPtr(*align(1) usize, old_record_addr).*; |
| 152 | 302 | const old_ptr = @intToPtr(*c_void, root_addr); |
| 153 | const amt = new_size + new_align + @sizeOf(usize); | |
| 154 | const new_ptr = os.windows.HeapReAlloc( | |
| 155 | self.heap_handle.?, | |
| 156 | 0, | |
| 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"), | |
| 303 | const new_record_addr = old_record_addr - new_size + old_mem.len; | |
| 304 | @intToPtr(*align(1) usize, new_record_addr).* = root_addr; | |
| 305 | return old_mem[0..new_size]; | |
| 306 | }; | |
| 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 | }; |
| 172 | 350 | |
| 173 | 351 | /// This allocator takes an existing allocator, wraps it, and provides an interface |
| ... | ... | @@ -250,7 +428,7 @@ pub const ArenaAllocator = struct { |
| 250 | 428 | return error.OutOfMemory; |
| 251 | 429 | } else { |
| 252 | 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 | 432 | return result; |
| 255 | 433 | } |
| 256 | 434 | } |
| ... | ... | @@ -306,6 +484,103 @@ pub const FixedBufferAllocator = struct { |
| 306 | 484 | } else if (new_size <= old_mem.len and new_align <= old_align) { |
| 307 | 485 | // We can't do anything with the memory, so tell the client to keep it. |
| 308 | 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 | |
| 501 | extern fn @"llvm.wasm.memory.size.i32"(u32) u32; | |
| 502 | extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32; | |
| 503 | ||
| 504 | pub const wasm_allocator = &wasm_allocator_state.allocator; | |
| 505 | var 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 | ||
| 515 | const 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 | 584 | } else { |
| 310 | 585 | const result = try alloc(allocator, new_size, new_align); |
| 311 | 586 | mem.copy(u8, result, old_mem); |
| ... | ... | @@ -360,7 +635,7 @@ pub const ThreadSafeFixedBufferAllocator = blk: { |
| 360 | 635 | return error.OutOfMemory; |
| 361 | 636 | } else { |
| 362 | 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 | 639 | return result; |
| 365 | 640 | } |
| 366 | 641 | } |
| ... | ... | @@ -470,6 +745,31 @@ test "DirectAllocator" { |
| 470 | 745 | try testAllocator(allocator); |
| 471 | 746 | try testAllocatorAligned(allocator, 16); |
| 472 | 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 | ||
| 762 | test "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 | } |
| 474 | 774 | |
| 475 | 775 | test "ArenaAllocator" { |
| ... | ... | @@ -482,15 +782,17 @@ test "ArenaAllocator" { |
| 482 | 782 | try testAllocator(&arena_allocator.allocator); |
| 483 | 783 | try testAllocatorAligned(&arena_allocator.allocator, 16); |
| 484 | 784 | try testAllocatorLargeAlignment(&arena_allocator.allocator); |
| 785 | try testAllocatorAlignedShrink(&arena_allocator.allocator); | |
| 485 | 786 | } |
| 486 | 787 | |
| 487 | var test_fixed_buffer_allocator_memory: [30000 * @sizeOf(usize)]u8 = undefined; | |
| 788 | var test_fixed_buffer_allocator_memory: [80000 * @sizeOf(u64)]u8 = undefined; | |
| 488 | 789 | test "FixedBufferAllocator" { |
| 489 | 790 | var fixed_buffer_allocator = FixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]); |
| 490 | 791 | |
| 491 | 792 | try testAllocator(&fixed_buffer_allocator.allocator); |
| 492 | 793 | try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16); |
| 493 | 794 | try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator); |
| 795 | try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator); | |
| 494 | 796 | } |
| 495 | 797 | |
| 496 | 798 | test "FixedBufferAllocator Reuse memory on realloc" { |
| ... | ... | @@ -528,6 +830,7 @@ test "ThreadSafeFixedBufferAllocator" { |
| 528 | 830 | try testAllocator(&fixed_buffer_allocator.allocator); |
| 529 | 831 | try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16); |
| 530 | 832 | try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator); |
| 833 | try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator); | |
| 531 | 834 | } |
| 532 | 835 | |
| 533 | 836 | fn testAllocator(allocator: *mem.Allocator) !void { |
| ... | ... | @@ -610,3 +913,32 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo |
| 610 | 913 | |
| 611 | 914 | allocator.free(slice); |
| 612 | 915 | } |
| 916 | ||
| 917 | fn 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 | 36 | } |
| 37 | 37 | |
| 38 | 38 | pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream; |
| 39 | pub const COutStream = @import("io/c_out_stream.zig").COutStream; | |
| 39 | 40 | |
| 40 | 41 | pub fn InStream(comptime ReadError: type) type { |
| 41 | 42 | return struct { |
| ... | ... | @@ -194,8 +195,8 @@ pub fn InStream(comptime ReadError: type) type { |
| 194 | 195 | return mem.readVarInt(ReturnType, bytes, endian); |
| 195 | 196 | } |
| 196 | 197 | |
| 197 | pub fn skipBytes(self: *Self, num_bytes: usize) !void { | |
| 198 | var i: usize = 0; | |
| 198 | pub fn skipBytes(self: *Self, num_bytes: u64) !void { | |
| 199 | var i: u64 = 0; | |
| 199 | 200 | while (i < num_bytes) : (i += 1) { |
| 200 | 201 | _ = try self.readByte(); |
| 201 | 202 | } |
| ... | ... | @@ -289,7 +290,7 @@ pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptim |
| 289 | 290 | var file = try File.openRead(path); |
| 290 | 291 | defer file.close(); |
| 291 | 292 | |
| 292 | const size = try file.getEndPos(); | |
| 293 | const size = try math.cast(usize, try file.getEndPos()); | |
| 293 | 294 | const buf = try allocator.alignedAlloc(u8, A, size); |
| 294 | 295 | errdefer allocator.free(buf); |
| 295 | 296 | |
| ... | ... | @@ -742,7 +743,7 @@ pub fn CountingOutStream(comptime OutStreamError: type) type { |
| 742 | 743 | pub const Error = OutStreamError; |
| 743 | 744 | |
| 744 | 745 | pub stream: Stream, |
| 745 | pub bytes_written: usize, | |
| 746 | pub bytes_written: u64, | |
| 746 | 747 | child_stream: *Stream, |
| 747 | 748 | |
| 748 | 749 | pub fn init(child_stream: *Stream) Self { |
| ... | ... | @@ -1089,8 +1090,11 @@ test "io.readLineSliceFrom" { |
| 1089 | 1090 | } |
| 1090 | 1091 | |
| 1091 | 1092 | pub const Packing = enum { |
| 1092 | Byte, /// Pack data to byte alignment | |
| 1093 | Bit, /// Pack data to bit alignment | |
| 1093 | /// Pack data to byte alignment | |
| 1094 | Byte, | |
| 1095 | ||
| 1096 | /// Pack data to bit alignment | |
| 1097 | Bit, | |
| 1094 | 1098 | }; |
| 1095 | 1099 | |
| 1096 | 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 | 1115 | pub const Stream = InStream(Error); |
| 1112 | 1116 | |
| 1113 | 1117 | pub fn init(in_stream: *Stream) Self { |
| 1114 | return Self{ .in_stream = switch (packing) { | |
| 1115 | .Bit => BitInStream(endian, Stream.Error).init(in_stream), | |
| 1116 | .Byte => in_stream, | |
| 1117 | } }; | |
| 1118 | return Self{ | |
| 1119 | .in_stream = switch (packing) { | |
| 1120 | .Bit => BitInStream(endian, Stream.Error).init(in_stream), | |
| 1121 | .Byte => in_stream, | |
| 1122 | }, | |
| 1123 | }; | |
| 1118 | 1124 | } |
| 1119 | 1125 | |
| 1120 | 1126 | pub fn alignToByte(self: *Self) void { |
| ... | ... | @@ -1281,7 +1287,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, |
| 1281 | 1287 | ptr.* = null; |
| 1282 | 1288 | return; |
| 1283 | 1289 | } |
| 1284 | ||
| 1290 | ||
| 1285 | 1291 | ptr.* = OC(undefined); //make it non-null so the following .? is guaranteed safe |
| 1286 | 1292 | const val_ptr = &ptr.*.?; |
| 1287 | 1293 | try self.deserializeInto(val_ptr); |
| ... | ... | @@ -1320,10 +1326,12 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co |
| 1320 | 1326 | pub const Stream = OutStream(Error); |
| 1321 | 1327 | |
| 1322 | 1328 | pub fn init(out_stream: *Stream) Self { |
| 1323 | return Self{ .out_stream = switch (packing) { | |
| 1324 | .Bit => BitOutStream(endian, Stream.Error).init(out_stream), | |
| 1325 | .Byte => out_stream, | |
| 1326 | } }; | |
| 1329 | return Self{ | |
| 1330 | .out_stream = switch (packing) { | |
| 1331 | .Bit => BitOutStream(endian, Stream.Error).init(out_stream), | |
| 1332 | .Byte => out_stream, | |
| 1333 | }, | |
| 1334 | }; | |
| 1327 | 1335 | } |
| 1328 | 1336 | |
| 1329 | 1337 | /// Flushes any unwritten bits to the stream |
| ... | ... | @@ -1447,7 +1455,6 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co |
| 1447 | 1455 | |
| 1448 | 1456 | test "import io tests" { |
| 1449 | 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 @@ |
| 1 | const std = @import("../std.zig"); | |
| 2 | const OutStream = std.io.OutStream; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const 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. | |
| 9 | pub 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 | 7 | pub const SeekError = SeekErrorType; |
| 8 | 8 | pub const GetSeekPosError = GetSeekPosErrorType; |
| 9 | 9 | |
| 10 | seekToFn: fn (self: *Self, pos: usize) SeekError!void, | |
| 11 | seekForwardFn: fn (self: *Self, pos: isize) SeekError!void, | |
| 10 | seekToFn: fn (self: *Self, pos: u64) SeekError!void, | |
| 11 | seekForwardFn: fn (self: *Self, pos: i64) SeekError!void, | |
| 12 | 12 | |
| 13 | getPosFn: fn (self: *Self) GetSeekPosError!usize, | |
| 14 | getEndPosFn: fn (self: *Self) GetSeekPosError!usize, | |
| 13 | getPosFn: fn (self: *Self) GetSeekPosError!u64, | |
| 14 | getEndPosFn: fn (self: *Self) GetSeekPosError!u64, | |
| 15 | 15 | |
| 16 | pub fn seekTo(self: *Self, pos: usize) SeekError!void { | |
| 16 | pub fn seekTo(self: *Self, pos: u64) SeekError!void { | |
| 17 | 17 | return self.seekToFn(self, pos); |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | pub fn seekForward(self: *Self, amt: isize) SeekError!void { | |
| 20 | pub fn seekForward(self: *Self, amt: i64) SeekError!void { | |
| 21 | 21 | return self.seekForwardFn(self, amt); |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | pub fn getEndPos(self: *Self) GetSeekPosError!usize { | |
| 24 | pub fn getEndPos(self: *Self) GetSeekPosError!u64 { | |
| 25 | 25 | return self.getEndPosFn(self); |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | pub fn getPos(self: *Self) GetSeekPosError!usize { | |
| 28 | pub fn getPos(self: *Self) GetSeekPosError!u64 { | |
| 29 | 29 | return self.getPosFn(self); |
| 30 | 30 | } |
| 31 | 31 | }; |
std/io/test.zig created+602| ... | ... | @@ -0,0 +1,602 @@ |
| 1 | const std = @import("../std.zig"); | |
| 2 | const io = std.io; | |
| 3 | const meta = std.meta; | |
| 4 | const trait = std.trait; | |
| 5 | const DefaultPrng = std.rand.DefaultPrng; | |
| 6 | const expect = std.testing.expect; | |
| 7 | const expectError = std.testing.expectError; | |
| 8 | const mem = std.mem; | |
| 9 | const os = std.os; | |
| 10 | const builtin = @import("builtin"); | |
| 11 | ||
| 12 | test "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 | ||
| 63 | test "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 | ||
| 77 | test "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 | ||
| 95 | test "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 | ||
| 128 | test "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 | ||
| 148 | test "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 | ||
| 220 | test "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 | ||
| 273 | test "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 | ||
| 321 | fn 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 | ||
| 381 | test "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 | ||
| 390 | fn 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 | ||
| 434 | test "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 | ||
| 441 | fn testAlternateSerializer(self: var, serializer: var) !void { | |
| 442 | try serializer.serialize(self.f_f16); | |
| 443 | } | |
| 444 | ||
| 445 | fn 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 | ||
| 545 | test "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 | ||
| 552 | fn 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 | ||
| 586 | test "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 | ||
| 593 | test "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 @@ |
| 1 | const std = @import("std.zig"); | |
| 2 | const io = std.io; | |
| 3 | const meta = std.meta; | |
| 4 | const trait = std.trait; | |
| 5 | const DefaultPrng = std.rand.DefaultPrng; | |
| 6 | const expect = std.testing.expect; | |
| 7 | const expectError = std.testing.expectError; | |
| 8 | const mem = std.mem; | |
| 9 | const os = std.os; | |
| 10 | const builtin = @import("builtin"); | |
| 11 | ||
| 12 | test "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 | ||
| 63 | test "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 | ||
| 77 | test "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 | ||
| 95 | test "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 | ||
| 128 | test "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 | ||
| 148 | test "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 | ||
| 220 | test "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 | ||
| 273 | test "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 | ||
| 321 | fn 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 | ||
| 381 | test "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 | ||
| 390 | fn 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 | ||
| 434 | test "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 | ||
| 441 | fn testAlternateSerializer(self: var, serializer: var) !void { | |
| 442 | try serializer.serialize(self.f_f16); | |
| 443 | } | |
| 444 | ||
| 445 | fn 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 | ||
| 545 | test "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 | ||
| 552 | fn 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 | ||
| 586 | test "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 | 1400 | const double = image.Object.get("double").?.value; |
| 1401 | 1401 | testing.expect(double.Float == 1.3412); |
| 1402 | 1402 | } |
| 1403 | ||
| 1404 | test "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 | ||
| 6 | const std = @import("../std.zig"); | |
| 7 | ||
| 8 | fn ok(comptime s: []const u8) void { | |
| 9 | std.testing.expect(std.json.validate(s)); | |
| 10 | } | |
| 11 | ||
| 12 | fn err(comptime s: []const u8) void { | |
| 13 | std.testing.expect(!std.json.validate(s)); | |
| 14 | } | |
| 15 | ||
| 16 | fn any(comptime s: []const u8) void { | |
| 17 | std.testing.expect(true); | |
| 18 | } | |
| 19 | ||
| 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 21 | // | |
| 22 | // Additional tests not part of test JSONTestSuite. | |
| 23 | ||
| 24 | test "y_trailing_comma_after_empty" { | |
| 25 | ok( | |
| 26 | \\{"1":[],"2":{},"3":"4"} | |
| 27 | ); | |
| 28 | } | |
| 29 | ||
| 30 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 31 | ||
| 32 | test "y_array_arraysWithSpaces" { | |
| 33 | ok( | |
| 34 | \\[[] ] | |
| 35 | ); | |
| 36 | } | |
| 37 | ||
| 38 | test "y_array_empty" { | |
| 39 | ok( | |
| 40 | \\[] | |
| 41 | ); | |
| 42 | } | |
| 43 | ||
| 44 | test "y_array_empty-string" { | |
| 45 | ok( | |
| 46 | \\[""] | |
| 47 | ); | |
| 48 | } | |
| 49 | ||
| 50 | test "y_array_ending_with_newline" { | |
| 51 | ok( | |
| 52 | \\["a"] | |
| 53 | ); | |
| 54 | } | |
| 55 | ||
| 56 | test "y_array_false" { | |
| 57 | ok( | |
| 58 | \\[false] | |
| 59 | ); | |
| 60 | } | |
| 61 | ||
| 62 | test "y_array_heterogeneous" { | |
| 63 | ok( | |
| 64 | \\[null, 1, "1", {}] | |
| 65 | ); | |
| 66 | } | |
| 67 | ||
| 68 | test "y_array_null" { | |
| 69 | ok( | |
| 70 | \\[null] | |
| 71 | ); | |
| 72 | } | |
| 73 | ||
| 74 | test "y_array_with_1_and_newline" { | |
| 75 | ok( | |
| 76 | \\[1 | |
| 77 | \\] | |
| 78 | ); | |
| 79 | } | |
| 80 | ||
| 81 | test "y_array_with_leading_space" { | |
| 82 | ok( | |
| 83 | \\ [1] | |
| 84 | ); | |
| 85 | } | |
| 86 | ||
| 87 | test "y_array_with_several_null" { | |
| 88 | ok( | |
| 89 | \\[1,null,null,null,2] | |
| 90 | ); | |
| 91 | } | |
| 92 | ||
| 93 | test "y_array_with_trailing_space" { | |
| 94 | ok("[2] "); | |
| 95 | } | |
| 96 | ||
| 97 | test "y_number_0e+1" { | |
| 98 | ok( | |
| 99 | \\[0e+1] | |
| 100 | ); | |
| 101 | } | |
| 102 | ||
| 103 | test "y_number_0e1" { | |
| 104 | ok( | |
| 105 | \\[0e1] | |
| 106 | ); | |
| 107 | } | |
| 108 | ||
| 109 | test "y_number_after_space" { | |
| 110 | ok( | |
| 111 | \\[ 4] | |
| 112 | ); | |
| 113 | } | |
| 114 | ||
| 115 | test "y_number_double_close_to_zero" { | |
| 116 | ok( | |
| 117 | \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001] | |
| 118 | ); | |
| 119 | } | |
| 120 | ||
| 121 | test "y_number_int_with_exp" { | |
| 122 | ok( | |
| 123 | \\[20e1] | |
| 124 | ); | |
| 125 | } | |
| 126 | ||
| 127 | test "y_number" { | |
| 128 | ok( | |
| 129 | \\[123e65] | |
| 130 | ); | |
| 131 | } | |
| 132 | ||
| 133 | test "y_number_minus_zero" { | |
| 134 | ok( | |
| 135 | \\[-0] | |
| 136 | ); | |
| 137 | } | |
| 138 | ||
| 139 | test "y_number_negative_int" { | |
| 140 | ok( | |
| 141 | \\[-123] | |
| 142 | ); | |
| 143 | } | |
| 144 | ||
| 145 | test "y_number_negative_one" { | |
| 146 | ok( | |
| 147 | \\[-1] | |
| 148 | ); | |
| 149 | } | |
| 150 | ||
| 151 | test "y_number_negative_zero" { | |
| 152 | ok( | |
| 153 | \\[-0] | |
| 154 | ); | |
| 155 | } | |
| 156 | ||
| 157 | test "y_number_real_capital_e" { | |
| 158 | ok( | |
| 159 | \\[1E22] | |
| 160 | ); | |
| 161 | } | |
| 162 | ||
| 163 | test "y_number_real_capital_e_neg_exp" { | |
| 164 | ok( | |
| 165 | \\[1E-2] | |
| 166 | ); | |
| 167 | } | |
| 168 | ||
| 169 | test "y_number_real_capital_e_pos_exp" { | |
| 170 | ok( | |
| 171 | \\[1E+2] | |
| 172 | ); | |
| 173 | } | |
| 174 | ||
| 175 | test "y_number_real_exponent" { | |
| 176 | ok( | |
| 177 | \\[123e45] | |
| 178 | ); | |
| 179 | } | |
| 180 | ||
| 181 | test "y_number_real_fraction_exponent" { | |
| 182 | ok( | |
| 183 | \\[123.456e78] | |
| 184 | ); | |
| 185 | } | |
| 186 | ||
| 187 | test "y_number_real_neg_exp" { | |
| 188 | ok( | |
| 189 | \\[1e-2] | |
| 190 | ); | |
| 191 | } | |
| 192 | ||
| 193 | test "y_number_real_pos_exponent" { | |
| 194 | ok( | |
| 195 | \\[1e+2] | |
| 196 | ); | |
| 197 | } | |
| 198 | ||
| 199 | test "y_number_simple_int" { | |
| 200 | ok( | |
| 201 | \\[123] | |
| 202 | ); | |
| 203 | } | |
| 204 | ||
| 205 | test "y_number_simple_real" { | |
| 206 | ok( | |
| 207 | \\[123.456789] | |
| 208 | ); | |
| 209 | } | |
| 210 | ||
| 211 | test "y_object_basic" { | |
| 212 | ok( | |
| 213 | \\{"asd":"sdf"} | |
| 214 | ); | |
| 215 | } | |
| 216 | ||
| 217 | test "y_object_duplicated_key_and_value" { | |
| 218 | ok( | |
| 219 | \\{"a":"b","a":"b"} | |
| 220 | ); | |
| 221 | } | |
| 222 | ||
| 223 | test "y_object_duplicated_key" { | |
| 224 | ok( | |
| 225 | \\{"a":"b","a":"c"} | |
| 226 | ); | |
| 227 | } | |
| 228 | ||
| 229 | test "y_object_empty" { | |
| 230 | ok( | |
| 231 | \\{} | |
| 232 | ); | |
| 233 | } | |
| 234 | ||
| 235 | test "y_object_empty_key" { | |
| 236 | ok( | |
| 237 | \\{"":0} | |
| 238 | ); | |
| 239 | } | |
| 240 | ||
| 241 | test "y_object_escaped_null_in_key" { | |
| 242 | ok( | |
| 243 | \\{"foo\u0000bar": 42} | |
| 244 | ); | |
| 245 | } | |
| 246 | ||
| 247 | test "y_object_extreme_numbers" { | |
| 248 | ok( | |
| 249 | \\{ "min": -1.0e+28, "max": 1.0e+28 } | |
| 250 | ); | |
| 251 | } | |
| 252 | ||
| 253 | test "y_object" { | |
| 254 | ok( | |
| 255 | \\{"asd":"sdf", "dfg":"fgh"} | |
| 256 | ); | |
| 257 | } | |
| 258 | ||
| 259 | test "y_object_long_strings" { | |
| 260 | ok( | |
| 261 | \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} | |
| 262 | ); | |
| 263 | } | |
| 264 | ||
| 265 | test "y_object_simple" { | |
| 266 | ok( | |
| 267 | \\{"a":[]} | |
| 268 | ); | |
| 269 | } | |
| 270 | ||
| 271 | 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 | ||
| 277 | test "y_object_with_newlines" { | |
| 278 | ok( | |
| 279 | \\{ | |
| 280 | \\"a": "b" | |
| 281 | \\} | |
| 282 | ); | |
| 283 | } | |
| 284 | ||
| 285 | test "y_string_1_2_3_bytes_UTF-8_sequences" { | |
| 286 | ok( | |
| 287 | \\["\u0060\u012a\u12AB"] | |
| 288 | ); | |
| 289 | } | |
| 290 | ||
| 291 | test "y_string_accepted_surrogate_pair" { | |
| 292 | ok( | |
| 293 | \\["\uD801\udc37"] | |
| 294 | ); | |
| 295 | } | |
| 296 | ||
| 297 | test "y_string_accepted_surrogate_pairs" { | |
| 298 | ok( | |
| 299 | \\["\ud83d\ude39\ud83d\udc8d"] | |
| 300 | ); | |
| 301 | } | |
| 302 | ||
| 303 | test "y_string_allowed_escapes" { | |
| 304 | ok( | |
| 305 | \\["\"\\\/\b\f\n\r\t"] | |
| 306 | ); | |
| 307 | } | |
| 308 | ||
| 309 | test "y_string_backslash_and_u_escaped_zero" { | |
| 310 | ok( | |
| 311 | \\["\\u0000"] | |
| 312 | ); | |
| 313 | } | |
| 314 | ||
| 315 | test "y_string_backslash_doublequotes" { | |
| 316 | ok( | |
| 317 | \\["\""] | |
| 318 | ); | |
| 319 | } | |
| 320 | ||
| 321 | test "y_string_comments" { | |
| 322 | ok( | |
| 323 | \\["a/*b*/c/*d//e"] | |
| 324 | ); | |
| 325 | } | |
| 326 | ||
| 327 | test "y_string_double_escape_a" { | |
| 328 | ok( | |
| 329 | \\["\\a"] | |
| 330 | ); | |
| 331 | } | |
| 332 | ||
| 333 | test "y_string_double_escape_n" { | |
| 334 | ok( | |
| 335 | \\["\\n"] | |
| 336 | ); | |
| 337 | } | |
| 338 | ||
| 339 | test "y_string_escaped_control_character" { | |
| 340 | ok( | |
| 341 | \\["\u0012"] | |
| 342 | ); | |
| 343 | } | |
| 344 | ||
| 345 | test "y_string_escaped_noncharacter" { | |
| 346 | ok( | |
| 347 | \\["\uFFFF"] | |
| 348 | ); | |
| 349 | } | |
| 350 | ||
| 351 | test "y_string_in_array" { | |
| 352 | ok( | |
| 353 | \\["asd"] | |
| 354 | ); | |
| 355 | } | |
| 356 | ||
| 357 | test "y_string_in_array_with_leading_space" { | |
| 358 | ok( | |
| 359 | \\[ "asd"] | |
| 360 | ); | |
| 361 | } | |
| 362 | ||
| 363 | test "y_string_last_surrogates_1_and_2" { | |
| 364 | ok( | |
| 365 | \\["\uDBFF\uDFFF"] | |
| 366 | ); | |
| 367 | } | |
| 368 | ||
| 369 | test "y_string_nbsp_uescaped" { | |
| 370 | ok( | |
| 371 | \\["new\u00A0line"] | |
| 372 | ); | |
| 373 | } | |
| 374 | ||
| 375 | test "y_string_nonCharacterInUTF-8_U+10FFFF" { | |
| 376 | ok( | |
| 377 | \\[""] | |
| 378 | ); | |
| 379 | } | |
| 380 | ||
| 381 | test "y_string_nonCharacterInUTF-8_U+FFFF" { | |
| 382 | ok( | |
| 383 | \\[""] | |
| 384 | ); | |
| 385 | } | |
| 386 | ||
| 387 | test "y_string_null_escape" { | |
| 388 | ok( | |
| 389 | \\["\u0000"] | |
| 390 | ); | |
| 391 | } | |
| 392 | ||
| 393 | test "y_string_one-byte-utf-8" { | |
| 394 | ok( | |
| 395 | \\["\u002c"] | |
| 396 | ); | |
| 397 | } | |
| 398 | ||
| 399 | test "y_string_pi" { | |
| 400 | ok( | |
| 401 | \\["π"] | |
| 402 | ); | |
| 403 | } | |
| 404 | ||
| 405 | test "y_string_reservedCharacterInUTF-8_U+1BFFF" { | |
| 406 | ok( | |
| 407 | \\[""] | |
| 408 | ); | |
| 409 | } | |
| 410 | ||
| 411 | test "y_string_simple_ascii" { | |
| 412 | ok( | |
| 413 | \\["asd "] | |
| 414 | ); | |
| 415 | } | |
| 416 | ||
| 417 | test "y_string_space" { | |
| 418 | ok( | |
| 419 | \\" " | |
| 420 | ); | |
| 421 | } | |
| 422 | ||
| 423 | test "y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" { | |
| 424 | ok( | |
| 425 | \\["\uD834\uDd1e"] | |
| 426 | ); | |
| 427 | } | |
| 428 | ||
| 429 | test "y_string_three-byte-utf-8" { | |
| 430 | ok( | |
| 431 | \\["\u0821"] | |
| 432 | ); | |
| 433 | } | |
| 434 | ||
| 435 | test "y_string_two-byte-utf-8" { | |
| 436 | ok( | |
| 437 | \\["\u0123"] | |
| 438 | ); | |
| 439 | } | |
| 440 | ||
| 441 | test "y_string_u+2028_line_sep" { | |
| 442 | ok("[\"\xe2\x80\xa8\"]"); | |
| 443 | } | |
| 444 | ||
| 445 | test "y_string_u+2029_par_sep" { | |
| 446 | ok("[\"\xe2\x80\xa9\"]"); | |
| 447 | } | |
| 448 | ||
| 449 | test "y_string_uescaped_newline" { | |
| 450 | ok( | |
| 451 | \\["new\u000Aline"] | |
| 452 | ); | |
| 453 | } | |
| 454 | ||
| 455 | test "y_string_uEscape" { | |
| 456 | ok( | |
| 457 | \\["\u0061\u30af\u30EA\u30b9"] | |
| 458 | ); | |
| 459 | } | |
| 460 | ||
| 461 | test "y_string_unescaped_char_delete" { | |
| 462 | ok("[\"\x7f\"]"); | |
| 463 | } | |
| 464 | ||
| 465 | test "y_string_unicode_2" { | |
| 466 | ok( | |
| 467 | \\["⍂㈴⍂"] | |
| 468 | ); | |
| 469 | } | |
| 470 | ||
| 471 | test "y_string_unicodeEscapedBackslash" { | |
| 472 | ok( | |
| 473 | \\["\u005C"] | |
| 474 | ); | |
| 475 | } | |
| 476 | ||
| 477 | test "y_string_unicode_escaped_double_quote" { | |
| 478 | ok( | |
| 479 | \\["\u0022"] | |
| 480 | ); | |
| 481 | } | |
| 482 | ||
| 483 | test "y_string_unicode" { | |
| 484 | ok( | |
| 485 | \\["\uA66D"] | |
| 486 | ); | |
| 487 | } | |
| 488 | ||
| 489 | test "y_string_unicode_U+10FFFE_nonchar" { | |
| 490 | ok( | |
| 491 | \\["\uDBFF\uDFFE"] | |
| 492 | ); | |
| 493 | } | |
| 494 | ||
| 495 | test "y_string_unicode_U+1FFFE_nonchar" { | |
| 496 | ok( | |
| 497 | \\["\uD83F\uDFFE"] | |
| 498 | ); | |
| 499 | } | |
| 500 | ||
| 501 | test "y_string_unicode_U+200B_ZERO_WIDTH_SPACE" { | |
| 502 | ok( | |
| 503 | \\["\u200B"] | |
| 504 | ); | |
| 505 | } | |
| 506 | ||
| 507 | test "y_string_unicode_U+2064_invisible_plus" { | |
| 508 | ok( | |
| 509 | \\["\u2064"] | |
| 510 | ); | |
| 511 | } | |
| 512 | ||
| 513 | test "y_string_unicode_U+FDD0_nonchar" { | |
| 514 | ok( | |
| 515 | \\["\uFDD0"] | |
| 516 | ); | |
| 517 | } | |
| 518 | ||
| 519 | test "y_string_unicode_U+FFFE_nonchar" { | |
| 520 | ok( | |
| 521 | \\["\uFFFE"] | |
| 522 | ); | |
| 523 | } | |
| 524 | ||
| 525 | test "y_string_utf8" { | |
| 526 | ok( | |
| 527 | \\["€𝄞"] | |
| 528 | ); | |
| 529 | } | |
| 530 | ||
| 531 | test "y_string_with_del_character" { | |
| 532 | ok("[\"a\x7fa\"]"); | |
| 533 | } | |
| 534 | ||
| 535 | test "y_structure_lonely_false" { | |
| 536 | ok( | |
| 537 | \\false | |
| 538 | ); | |
| 539 | } | |
| 540 | ||
| 541 | test "y_structure_lonely_int" { | |
| 542 | ok( | |
| 543 | \\42 | |
| 544 | ); | |
| 545 | } | |
| 546 | ||
| 547 | test "y_structure_lonely_negative_real" { | |
| 548 | ok( | |
| 549 | \\-0.1 | |
| 550 | ); | |
| 551 | } | |
| 552 | ||
| 553 | test "y_structure_lonely_null" { | |
| 554 | ok( | |
| 555 | \\null | |
| 556 | ); | |
| 557 | } | |
| 558 | ||
| 559 | test "y_structure_lonely_string" { | |
| 560 | ok( | |
| 561 | \\"asd" | |
| 562 | ); | |
| 563 | } | |
| 564 | ||
| 565 | test "y_structure_lonely_true" { | |
| 566 | ok( | |
| 567 | \\true | |
| 568 | ); | |
| 569 | } | |
| 570 | ||
| 571 | test "y_structure_string_empty" { | |
| 572 | ok( | |
| 573 | \\"" | |
| 574 | ); | |
| 575 | } | |
| 576 | ||
| 577 | test "y_structure_trailing_newline" { | |
| 578 | ok( | |
| 579 | \\["a"] | |
| 580 | ); | |
| 581 | } | |
| 582 | ||
| 583 | test "y_structure_true_in_array" { | |
| 584 | ok( | |
| 585 | \\[true] | |
| 586 | ); | |
| 587 | } | |
| 588 | ||
| 589 | test "y_structure_whitespace_array" { | |
| 590 | ok(" [] "); | |
| 591 | } | |
| 592 | ||
| 593 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 594 | ||
| 595 | test "n_array_1_true_without_comma" { | |
| 596 | err( | |
| 597 | \\[1 true] | |
| 598 | ); | |
| 599 | } | |
| 600 | ||
| 601 | test "n_array_a_invalid_utf8" { | |
| 602 | err( | |
| 603 | \\[aå] | |
| 604 | ); | |
| 605 | } | |
| 606 | ||
| 607 | test "n_array_colon_instead_of_comma" { | |
| 608 | err( | |
| 609 | \\["": 1] | |
| 610 | ); | |
| 611 | } | |
| 612 | ||
| 613 | test "n_array_comma_after_close" { | |
| 614 | //err( | |
| 615 | // \\[""], | |
| 616 | //); | |
| 617 | } | |
| 618 | ||
| 619 | test "n_array_comma_and_number" { | |
| 620 | err( | |
| 621 | \\[,1] | |
| 622 | ); | |
| 623 | } | |
| 624 | ||
| 625 | test "n_array_double_comma" { | |
| 626 | err( | |
| 627 | \\[1,,2] | |
| 628 | ); | |
| 629 | } | |
| 630 | ||
| 631 | test "n_array_double_extra_comma" { | |
| 632 | err( | |
| 633 | \\["x",,] | |
| 634 | ); | |
| 635 | } | |
| 636 | ||
| 637 | test "n_array_extra_close" { | |
| 638 | err( | |
| 639 | \\["x"]] | |
| 640 | ); | |
| 641 | } | |
| 642 | ||
| 643 | test "n_array_extra_comma" { | |
| 644 | //err( | |
| 645 | // \\["",] | |
| 646 | //); | |
| 647 | } | |
| 648 | ||
| 649 | test "n_array_incomplete_invalid_value" { | |
| 650 | err( | |
| 651 | \\[x | |
| 652 | ); | |
| 653 | } | |
| 654 | ||
| 655 | test "n_array_incomplete" { | |
| 656 | err( | |
| 657 | \\["x" | |
| 658 | ); | |
| 659 | } | |
| 660 | ||
| 661 | test "n_array_inner_array_no_comma" { | |
| 662 | err( | |
| 663 | \\[3[4]] | |
| 664 | ); | |
| 665 | } | |
| 666 | ||
| 667 | test "n_array_invalid_utf8" { | |
| 668 | err( | |
| 669 | \\[ÿ] | |
| 670 | ); | |
| 671 | } | |
| 672 | ||
| 673 | test "n_array_items_separated_by_semicolon" { | |
| 674 | err( | |
| 675 | \\[1:2] | |
| 676 | ); | |
| 677 | } | |
| 678 | ||
| 679 | test "n_array_just_comma" { | |
| 680 | err( | |
| 681 | \\[,] | |
| 682 | ); | |
| 683 | } | |
| 684 | ||
| 685 | test "n_array_just_minus" { | |
| 686 | err( | |
| 687 | \\[-] | |
| 688 | ); | |
| 689 | } | |
| 690 | ||
| 691 | test "n_array_missing_value" { | |
| 692 | err( | |
| 693 | \\[ , ""] | |
| 694 | ); | |
| 695 | } | |
| 696 | ||
| 697 | test "n_array_newlines_unclosed" { | |
| 698 | err( | |
| 699 | \\["a", | |
| 700 | \\4 | |
| 701 | \\,1, | |
| 702 | ); | |
| 703 | } | |
| 704 | ||
| 705 | test "n_array_number_and_comma" { | |
| 706 | err( | |
| 707 | \\[1,] | |
| 708 | ); | |
| 709 | } | |
| 710 | ||
| 711 | test "n_array_number_and_several_commas" { | |
| 712 | err( | |
| 713 | \\[1,,] | |
| 714 | ); | |
| 715 | } | |
| 716 | ||
| 717 | test "n_array_spaces_vertical_tab_formfeed" { | |
| 718 | err("[\"\x0aa\"\\f]"); | |
| 719 | } | |
| 720 | ||
| 721 | test "n_array_star_inside" { | |
| 722 | err( | |
| 723 | \\[*] | |
| 724 | ); | |
| 725 | } | |
| 726 | ||
| 727 | test "n_array_unclosed" { | |
| 728 | err( | |
| 729 | \\["" | |
| 730 | ); | |
| 731 | } | |
| 732 | ||
| 733 | test "n_array_unclosed_trailing_comma" { | |
| 734 | err( | |
| 735 | \\[1, | |
| 736 | ); | |
| 737 | } | |
| 738 | ||
| 739 | test "n_array_unclosed_with_new_lines" { | |
| 740 | err( | |
| 741 | \\[1, | |
| 742 | \\1 | |
| 743 | \\,1 | |
| 744 | ); | |
| 745 | } | |
| 746 | ||
| 747 | test "n_array_unclosed_with_object_inside" { | |
| 748 | err( | |
| 749 | \\[{} | |
| 750 | ); | |
| 751 | } | |
| 752 | ||
| 753 | test "n_incomplete_false" { | |
| 754 | err( | |
| 755 | \\[fals] | |
| 756 | ); | |
| 757 | } | |
| 758 | ||
| 759 | test "n_incomplete_null" { | |
| 760 | err( | |
| 761 | \\[nul] | |
| 762 | ); | |
| 763 | } | |
| 764 | ||
| 765 | test "n_incomplete_true" { | |
| 766 | err( | |
| 767 | \\[tru] | |
| 768 | ); | |
| 769 | } | |
| 770 | ||
| 771 | test "n_multidigit_number_then_00" { | |
| 772 | err("123\x00"); | |
| 773 | } | |
| 774 | ||
| 775 | test "n_number_0.1.2" { | |
| 776 | err( | |
| 777 | \\[0.1.2] | |
| 778 | ); | |
| 779 | } | |
| 780 | ||
| 781 | test "n_number_-01" { | |
| 782 | err( | |
| 783 | \\[-01] | |
| 784 | ); | |
| 785 | } | |
| 786 | ||
| 787 | test "n_number_0.3e" { | |
| 788 | err( | |
| 789 | \\[0.3e] | |
| 790 | ); | |
| 791 | } | |
| 792 | ||
| 793 | test "n_number_0.3e+" { | |
| 794 | err( | |
| 795 | \\[0.3e+] | |
| 796 | ); | |
| 797 | } | |
| 798 | ||
| 799 | test "n_number_0_capital_E" { | |
| 800 | err( | |
| 801 | \\[0E] | |
| 802 | ); | |
| 803 | } | |
| 804 | ||
| 805 | test "n_number_0_capital_E+" { | |
| 806 | err( | |
| 807 | \\[0E+] | |
| 808 | ); | |
| 809 | } | |
| 810 | ||
| 811 | test "n_number_0.e1" { | |
| 812 | err( | |
| 813 | \\[0.e1] | |
| 814 | ); | |
| 815 | } | |
| 816 | ||
| 817 | test "n_number_0e" { | |
| 818 | err( | |
| 819 | \\[0e] | |
| 820 | ); | |
| 821 | } | |
| 822 | ||
| 823 | test "n_number_0e+" { | |
| 824 | err( | |
| 825 | \\[0e+] | |
| 826 | ); | |
| 827 | } | |
| 828 | ||
| 829 | test "n_number_1_000" { | |
| 830 | err( | |
| 831 | \\[1 000.0] | |
| 832 | ); | |
| 833 | } | |
| 834 | ||
| 835 | test "n_number_1.0e-" { | |
| 836 | err( | |
| 837 | \\[1.0e-] | |
| 838 | ); | |
| 839 | } | |
| 840 | ||
| 841 | test "n_number_1.0e" { | |
| 842 | err( | |
| 843 | \\[1.0e] | |
| 844 | ); | |
| 845 | } | |
| 846 | ||
| 847 | test "n_number_1.0e+" { | |
| 848 | err( | |
| 849 | \\[1.0e+] | |
| 850 | ); | |
| 851 | } | |
| 852 | ||
| 853 | test "n_number_-1.0." { | |
| 854 | err( | |
| 855 | \\[-1.0.] | |
| 856 | ); | |
| 857 | } | |
| 858 | ||
| 859 | test "n_number_1eE2" { | |
| 860 | err( | |
| 861 | \\[1eE2] | |
| 862 | ); | |
| 863 | } | |
| 864 | ||
| 865 | test "n_number_.-1" { | |
| 866 | err( | |
| 867 | \\[.-1] | |
| 868 | ); | |
| 869 | } | |
| 870 | ||
| 871 | test "n_number_+1" { | |
| 872 | err( | |
| 873 | \\[+1] | |
| 874 | ); | |
| 875 | } | |
| 876 | ||
| 877 | test "n_number_.2e-3" { | |
| 878 | err( | |
| 879 | \\[.2e-3] | |
| 880 | ); | |
| 881 | } | |
| 882 | ||
| 883 | test "n_number_2.e-3" { | |
| 884 | err( | |
| 885 | \\[2.e-3] | |
| 886 | ); | |
| 887 | } | |
| 888 | ||
| 889 | test "n_number_2.e+3" { | |
| 890 | err( | |
| 891 | \\[2.e+3] | |
| 892 | ); | |
| 893 | } | |
| 894 | ||
| 895 | test "n_number_2.e3" { | |
| 896 | err( | |
| 897 | \\[2.e3] | |
| 898 | ); | |
| 899 | } | |
| 900 | ||
| 901 | test "n_number_-2." { | |
| 902 | err( | |
| 903 | \\[-2.] | |
| 904 | ); | |
| 905 | } | |
| 906 | ||
| 907 | test "n_number_9.e+" { | |
| 908 | err( | |
| 909 | \\[9.e+] | |
| 910 | ); | |
| 911 | } | |
| 912 | ||
| 913 | test "n_number_expression" { | |
| 914 | err( | |
| 915 | \\[1+2] | |
| 916 | ); | |
| 917 | } | |
| 918 | ||
| 919 | test "n_number_hex_1_digit" { | |
| 920 | err( | |
| 921 | \\[0x1] | |
| 922 | ); | |
| 923 | } | |
| 924 | ||
| 925 | test "n_number_hex_2_digits" { | |
| 926 | err( | |
| 927 | \\[0x42] | |
| 928 | ); | |
| 929 | } | |
| 930 | ||
| 931 | test "n_number_infinity" { | |
| 932 | err( | |
| 933 | \\[Infinity] | |
| 934 | ); | |
| 935 | } | |
| 936 | ||
| 937 | test "n_number_+Inf" { | |
| 938 | err( | |
| 939 | \\[+Inf] | |
| 940 | ); | |
| 941 | } | |
| 942 | ||
| 943 | test "n_number_Inf" { | |
| 944 | err( | |
| 945 | \\[Inf] | |
| 946 | ); | |
| 947 | } | |
| 948 | ||
| 949 | test "n_number_invalid+-" { | |
| 950 | err( | |
| 951 | \\[0e+-1] | |
| 952 | ); | |
| 953 | } | |
| 954 | ||
| 955 | test "n_number_invalid-negative-real" { | |
| 956 | err( | |
| 957 | \\[-123.123foo] | |
| 958 | ); | |
| 959 | } | |
| 960 | ||
| 961 | test "n_number_invalid-utf-8-in-bigger-int" { | |
| 962 | err( | |
| 963 | \\[123å] | |
| 964 | ); | |
| 965 | } | |
| 966 | ||
| 967 | test "n_number_invalid-utf-8-in-exponent" { | |
| 968 | err( | |
| 969 | \\[1e1å] | |
| 970 | ); | |
| 971 | } | |
| 972 | ||
| 973 | test "n_number_invalid-utf-8-in-int" { | |
| 974 | err( | |
| 975 | \\[0å] | |
| 976 | ); | |
| 977 | } | |
| 978 | ||
| 979 | test "n_number_++" { | |
| 980 | err( | |
| 981 | \\[++1234] | |
| 982 | ); | |
| 983 | } | |
| 984 | ||
| 985 | test "n_number_minus_infinity" { | |
| 986 | err( | |
| 987 | \\[-Infinity] | |
| 988 | ); | |
| 989 | } | |
| 990 | ||
| 991 | test "n_number_minus_sign_with_trailing_garbage" { | |
| 992 | err( | |
| 993 | \\[-foo] | |
| 994 | ); | |
| 995 | } | |
| 996 | ||
| 997 | test "n_number_minus_space_1" { | |
| 998 | err( | |
| 999 | \\[- 1] | |
| 1000 | ); | |
| 1001 | } | |
| 1002 | ||
| 1003 | test "n_number_-NaN" { | |
| 1004 | err( | |
| 1005 | \\[-NaN] | |
| 1006 | ); | |
| 1007 | } | |
| 1008 | ||
| 1009 | test "n_number_NaN" { | |
| 1010 | err( | |
| 1011 | \\[NaN] | |
| 1012 | ); | |
| 1013 | } | |
| 1014 | ||
| 1015 | test "n_number_neg_int_starting_with_zero" { | |
| 1016 | err( | |
| 1017 | \\[-012] | |
| 1018 | ); | |
| 1019 | } | |
| 1020 | ||
| 1021 | test "n_number_neg_real_without_int_part" { | |
| 1022 | err( | |
| 1023 | \\[-.123] | |
| 1024 | ); | |
| 1025 | } | |
| 1026 | ||
| 1027 | test "n_number_neg_with_garbage_at_end" { | |
| 1028 | err( | |
| 1029 | \\[-1x] | |
| 1030 | ); | |
| 1031 | } | |
| 1032 | ||
| 1033 | test "n_number_real_garbage_after_e" { | |
| 1034 | err( | |
| 1035 | \\[1ea] | |
| 1036 | ); | |
| 1037 | } | |
| 1038 | ||
| 1039 | test "n_number_real_with_invalid_utf8_after_e" { | |
| 1040 | err( | |
| 1041 | \\[1eå] | |
| 1042 | ); | |
| 1043 | } | |
| 1044 | ||
| 1045 | test "n_number_real_without_fractional_part" { | |
| 1046 | err( | |
| 1047 | \\[1.] | |
| 1048 | ); | |
| 1049 | } | |
| 1050 | ||
| 1051 | test "n_number_starting_with_dot" { | |
| 1052 | err( | |
| 1053 | \\[.123] | |
| 1054 | ); | |
| 1055 | } | |
| 1056 | ||
| 1057 | test "n_number_U+FF11_fullwidth_digit_one" { | |
| 1058 | err( | |
| 1059 | \\[ï¼] | |
| 1060 | ); | |
| 1061 | } | |
| 1062 | ||
| 1063 | test "n_number_with_alpha_char" { | |
| 1064 | err( | |
| 1065 | \\[1.8011670033376514H-308] | |
| 1066 | ); | |
| 1067 | } | |
| 1068 | ||
| 1069 | test "n_number_with_alpha" { | |
| 1070 | err( | |
| 1071 | \\[1.2a-3] | |
| 1072 | ); | |
| 1073 | } | |
| 1074 | ||
| 1075 | test "n_number_with_leading_zero" { | |
| 1076 | err( | |
| 1077 | \\[012] | |
| 1078 | ); | |
| 1079 | } | |
| 1080 | ||
| 1081 | test "n_object_bad_value" { | |
| 1082 | err( | |
| 1083 | \\["x", truth] | |
| 1084 | ); | |
| 1085 | } | |
| 1086 | ||
| 1087 | test "n_object_bracket_key" { | |
| 1088 | err( | |
| 1089 | \\{[: "x"} | |
| 1090 | ); | |
| 1091 | } | |
| 1092 | ||
| 1093 | test "n_object_comma_instead_of_colon" { | |
| 1094 | err( | |
| 1095 | \\{"x", null} | |
| 1096 | ); | |
| 1097 | } | |
| 1098 | ||
| 1099 | test "n_object_double_colon" { | |
| 1100 | err( | |
| 1101 | \\{"x"::"b"} | |
| 1102 | ); | |
| 1103 | } | |
| 1104 | ||
| 1105 | test "n_object_emoji" { | |
| 1106 | err( | |
| 1107 | \\{ð¨ð} | |
| 1108 | ); | |
| 1109 | } | |
| 1110 | ||
| 1111 | test "n_object_garbage_at_end" { | |
| 1112 | err( | |
| 1113 | \\{"a":"a" 123} | |
| 1114 | ); | |
| 1115 | } | |
| 1116 | ||
| 1117 | test "n_object_key_with_single_quotes" { | |
| 1118 | err( | |
| 1119 | \\{key: 'value'} | |
| 1120 | ); | |
| 1121 | } | |
| 1122 | ||
| 1123 | test "n_object_lone_continuation_byte_in_key_and_trailing_comma" { | |
| 1124 | err( | |
| 1125 | \\{"¹":"0",} | |
| 1126 | ); | |
| 1127 | } | |
| 1128 | ||
| 1129 | test "n_object_missing_colon" { | |
| 1130 | err( | |
| 1131 | \\{"a" b} | |
| 1132 | ); | |
| 1133 | } | |
| 1134 | ||
| 1135 | test "n_object_missing_key" { | |
| 1136 | err( | |
| 1137 | \\{:"b"} | |
| 1138 | ); | |
| 1139 | } | |
| 1140 | ||
| 1141 | test "n_object_missing_semicolon" { | |
| 1142 | err( | |
| 1143 | \\{"a" "b"} | |
| 1144 | ); | |
| 1145 | } | |
| 1146 | ||
| 1147 | test "n_object_missing_value" { | |
| 1148 | err( | |
| 1149 | \\{"a": | |
| 1150 | ); | |
| 1151 | } | |
| 1152 | ||
| 1153 | test "n_object_no-colon" { | |
| 1154 | err( | |
| 1155 | \\{"a" | |
| 1156 | ); | |
| 1157 | } | |
| 1158 | ||
| 1159 | test "n_object_non_string_key_but_huge_number_instead" { | |
| 1160 | err( | |
| 1161 | \\{9999E9999:1} | |
| 1162 | ); | |
| 1163 | } | |
| 1164 | ||
| 1165 | test "n_object_non_string_key" { | |
| 1166 | err( | |
| 1167 | \\{1:1} | |
| 1168 | ); | |
| 1169 | } | |
| 1170 | ||
| 1171 | test "n_object_repeated_null_null" { | |
| 1172 | err( | |
| 1173 | \\{null:null,null:null} | |
| 1174 | ); | |
| 1175 | } | |
| 1176 | ||
| 1177 | test "n_object_several_trailing_commas" { | |
| 1178 | err( | |
| 1179 | \\{"id":0,,,,,} | |
| 1180 | ); | |
| 1181 | } | |
| 1182 | ||
| 1183 | test "n_object_single_quote" { | |
| 1184 | err( | |
| 1185 | \\{'a':0} | |
| 1186 | ); | |
| 1187 | } | |
| 1188 | ||
| 1189 | test "n_object_trailing_comma" { | |
| 1190 | err( | |
| 1191 | \\{"id":0,} | |
| 1192 | ); | |
| 1193 | } | |
| 1194 | ||
| 1195 | test "n_object_trailing_comment" { | |
| 1196 | err( | |
| 1197 | \\{"a":"b"}/**/ | |
| 1198 | ); | |
| 1199 | } | |
| 1200 | ||
| 1201 | test "n_object_trailing_comment_open" { | |
| 1202 | err( | |
| 1203 | \\{"a":"b"}/**// | |
| 1204 | ); | |
| 1205 | } | |
| 1206 | ||
| 1207 | test "n_object_trailing_comment_slash_open_incomplete" { | |
| 1208 | err( | |
| 1209 | \\{"a":"b"}/ | |
| 1210 | ); | |
| 1211 | } | |
| 1212 | ||
| 1213 | test "n_object_trailing_comment_slash_open" { | |
| 1214 | err( | |
| 1215 | \\{"a":"b"}// | |
| 1216 | ); | |
| 1217 | } | |
| 1218 | ||
| 1219 | test "n_object_two_commas_in_a_row" { | |
| 1220 | err( | |
| 1221 | \\{"a":"b",,"c":"d"} | |
| 1222 | ); | |
| 1223 | } | |
| 1224 | ||
| 1225 | test "n_object_unquoted_key" { | |
| 1226 | err( | |
| 1227 | \\{a: "b"} | |
| 1228 | ); | |
| 1229 | } | |
| 1230 | ||
| 1231 | test "n_object_unterminated-value" { | |
| 1232 | err( | |
| 1233 | \\{"a":"a | |
| 1234 | ); | |
| 1235 | } | |
| 1236 | ||
| 1237 | test "n_object_with_single_string" { | |
| 1238 | err( | |
| 1239 | \\{ "foo" : "bar", "a" } | |
| 1240 | ); | |
| 1241 | } | |
| 1242 | ||
| 1243 | test "n_object_with_trailing_garbage" { | |
| 1244 | err( | |
| 1245 | \\{"a":"b"}# | |
| 1246 | ); | |
| 1247 | } | |
| 1248 | ||
| 1249 | test "n_single_space" { | |
| 1250 | err(" "); | |
| 1251 | } | |
| 1252 | ||
| 1253 | test "n_string_1_surrogate_then_escape" { | |
| 1254 | err( | |
| 1255 | \\["\uD800\"] | |
| 1256 | ); | |
| 1257 | } | |
| 1258 | ||
| 1259 | test "n_string_1_surrogate_then_escape_u1" { | |
| 1260 | err( | |
| 1261 | \\["\uD800\u1"] | |
| 1262 | ); | |
| 1263 | } | |
| 1264 | ||
| 1265 | test "n_string_1_surrogate_then_escape_u1x" { | |
| 1266 | err( | |
| 1267 | \\["\uD800\u1x"] | |
| 1268 | ); | |
| 1269 | } | |
| 1270 | ||
| 1271 | test "n_string_1_surrogate_then_escape_u" { | |
| 1272 | err( | |
| 1273 | \\["\uD800\u"] | |
| 1274 | ); | |
| 1275 | } | |
| 1276 | ||
| 1277 | test "n_string_accentuated_char_no_quotes" { | |
| 1278 | err( | |
| 1279 | \\[é] | |
| 1280 | ); | |
| 1281 | } | |
| 1282 | ||
| 1283 | test "n_string_backslash_00" { | |
| 1284 | err("[\"\x00\"]"); | |
| 1285 | } | |
| 1286 | ||
| 1287 | test "n_string_escaped_backslash_bad" { | |
| 1288 | err( | |
| 1289 | \\["\\\"] | |
| 1290 | ); | |
| 1291 | } | |
| 1292 | ||
| 1293 | test "n_string_escaped_ctrl_char_tab" { | |
| 1294 | err("\x5b\x22\x5c\x09\x22\x5d"); | |
| 1295 | } | |
| 1296 | ||
| 1297 | test "n_string_escaped_emoji" { | |
| 1298 | err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]"); | |
| 1299 | } | |
| 1300 | ||
| 1301 | test "n_string_escape_x" { | |
| 1302 | err( | |
| 1303 | \\["\x00"] | |
| 1304 | ); | |
| 1305 | } | |
| 1306 | ||
| 1307 | test "n_string_incomplete_escaped_character" { | |
| 1308 | err( | |
| 1309 | \\["\u00A"] | |
| 1310 | ); | |
| 1311 | } | |
| 1312 | ||
| 1313 | test "n_string_incomplete_escape" { | |
| 1314 | err( | |
| 1315 | \\["\"] | |
| 1316 | ); | |
| 1317 | } | |
| 1318 | ||
| 1319 | test "n_string_incomplete_surrogate_escape_invalid" { | |
| 1320 | err( | |
| 1321 | \\["\uD800\uD800\x"] | |
| 1322 | ); | |
| 1323 | } | |
| 1324 | ||
| 1325 | test "n_string_incomplete_surrogate" { | |
| 1326 | err( | |
| 1327 | \\["\uD834\uDd"] | |
| 1328 | ); | |
| 1329 | } | |
| 1330 | ||
| 1331 | test "n_string_invalid_backslash_esc" { | |
| 1332 | err( | |
| 1333 | \\["\a"] | |
| 1334 | ); | |
| 1335 | } | |
| 1336 | ||
| 1337 | test "n_string_invalid_unicode_escape" { | |
| 1338 | err( | |
| 1339 | \\["\uqqqq"] | |
| 1340 | ); | |
| 1341 | } | |
| 1342 | ||
| 1343 | test "n_string_invalid_utf8_after_escape" { | |
| 1344 | err("[\"\\\x75\xc3\xa5\"]"); | |
| 1345 | } | |
| 1346 | ||
| 1347 | test "n_string_invalid-utf-8-in-escape" { | |
| 1348 | err( | |
| 1349 | \\["\uå"] | |
| 1350 | ); | |
| 1351 | } | |
| 1352 | ||
| 1353 | test "n_string_leading_uescaped_thinspace" { | |
| 1354 | err( | |
| 1355 | \\[\u0020"asd"] | |
| 1356 | ); | |
| 1357 | } | |
| 1358 | ||
| 1359 | test "n_string_no_quotes_with_bad_escape" { | |
| 1360 | err( | |
| 1361 | \\[\n] | |
| 1362 | ); | |
| 1363 | } | |
| 1364 | ||
| 1365 | test "n_string_single_doublequote" { | |
| 1366 | err( | |
| 1367 | \\" | |
| 1368 | ); | |
| 1369 | } | |
| 1370 | ||
| 1371 | test "n_string_single_quote" { | |
| 1372 | err( | |
| 1373 | \\['single quote'] | |
| 1374 | ); | |
| 1375 | } | |
| 1376 | ||
| 1377 | test "n_string_single_string_no_double_quotes" { | |
| 1378 | err( | |
| 1379 | \\abc | |
| 1380 | ); | |
| 1381 | } | |
| 1382 | ||
| 1383 | test "n_string_start_escape_unclosed" { | |
| 1384 | err( | |
| 1385 | \\["\ | |
| 1386 | ); | |
| 1387 | } | |
| 1388 | ||
| 1389 | test "n_string_unescaped_crtl_char" { | |
| 1390 | err("[\"a\x00a\"]"); | |
| 1391 | } | |
| 1392 | ||
| 1393 | test "n_string_unescaped_newline" { | |
| 1394 | err( | |
| 1395 | \\["new | |
| 1396 | \\line"] | |
| 1397 | ); | |
| 1398 | } | |
| 1399 | ||
| 1400 | test "n_string_unescaped_tab" { | |
| 1401 | err("[\"\t\"]"); | |
| 1402 | } | |
| 1403 | ||
| 1404 | test "n_string_unicode_CapitalU" { | |
| 1405 | err( | |
| 1406 | \\"\UA66D" | |
| 1407 | ); | |
| 1408 | } | |
| 1409 | ||
| 1410 | test "n_string_with_trailing_garbage" { | |
| 1411 | err( | |
| 1412 | \\""x | |
| 1413 | ); | |
| 1414 | } | |
| 1415 | ||
| 1416 | test "n_structure_100000_opening_arrays" { | |
| 1417 | err("[" ** 100000); | |
| 1418 | } | |
| 1419 | ||
| 1420 | test "n_structure_angle_bracket_." { | |
| 1421 | err( | |
| 1422 | \\<.> | |
| 1423 | ); | |
| 1424 | } | |
| 1425 | ||
| 1426 | test "n_structure_angle_bracket_null" { | |
| 1427 | err( | |
| 1428 | \\[<null>] | |
| 1429 | ); | |
| 1430 | } | |
| 1431 | ||
| 1432 | test "n_structure_array_trailing_garbage" { | |
| 1433 | err( | |
| 1434 | \\[1]x | |
| 1435 | ); | |
| 1436 | } | |
| 1437 | ||
| 1438 | test "n_structure_array_with_extra_array_close" { | |
| 1439 | err( | |
| 1440 | \\[1]] | |
| 1441 | ); | |
| 1442 | } | |
| 1443 | ||
| 1444 | test "n_structure_array_with_unclosed_string" { | |
| 1445 | err( | |
| 1446 | \\["asd] | |
| 1447 | ); | |
| 1448 | } | |
| 1449 | ||
| 1450 | test "n_structure_ascii-unicode-identifier" { | |
| 1451 | err( | |
| 1452 | \\aå | |
| 1453 | ); | |
| 1454 | } | |
| 1455 | ||
| 1456 | test "n_structure_capitalized_True" { | |
| 1457 | err( | |
| 1458 | \\[True] | |
| 1459 | ); | |
| 1460 | } | |
| 1461 | ||
| 1462 | test "n_structure_close_unopened_array" { | |
| 1463 | err( | |
| 1464 | \\1] | |
| 1465 | ); | |
| 1466 | } | |
| 1467 | ||
| 1468 | test "n_structure_comma_instead_of_closing_brace" { | |
| 1469 | err( | |
| 1470 | \\{"x": true, | |
| 1471 | ); | |
| 1472 | } | |
| 1473 | ||
| 1474 | test "n_structure_double_array" { | |
| 1475 | err( | |
| 1476 | \\[][] | |
| 1477 | ); | |
| 1478 | } | |
| 1479 | ||
| 1480 | test "n_structure_end_array" { | |
| 1481 | err( | |
| 1482 | \\] | |
| 1483 | ); | |
| 1484 | } | |
| 1485 | ||
| 1486 | test "n_structure_incomplete_UTF8_BOM" { | |
| 1487 | err( | |
| 1488 | \\ï»{} | |
| 1489 | ); | |
| 1490 | } | |
| 1491 | ||
| 1492 | test "n_structure_lone-invalid-utf-8" { | |
| 1493 | err( | |
| 1494 | \\å | |
| 1495 | ); | |
| 1496 | } | |
| 1497 | ||
| 1498 | test "n_structure_lone-open-bracket" { | |
| 1499 | err( | |
| 1500 | \\[ | |
| 1501 | ); | |
| 1502 | } | |
| 1503 | ||
| 1504 | test "n_structure_no_data" { | |
| 1505 | err( | |
| 1506 | \\ | |
| 1507 | ); | |
| 1508 | } | |
| 1509 | ||
| 1510 | test "n_structure_null-byte-outside-string" { | |
| 1511 | err("[\x00]"); | |
| 1512 | } | |
| 1513 | ||
| 1514 | test "n_structure_number_with_trailing_garbage" { | |
| 1515 | err( | |
| 1516 | \\2@ | |
| 1517 | ); | |
| 1518 | } | |
| 1519 | ||
| 1520 | test "n_structure_object_followed_by_closing_object" { | |
| 1521 | err( | |
| 1522 | \\{}} | |
| 1523 | ); | |
| 1524 | } | |
| 1525 | ||
| 1526 | test "n_structure_object_unclosed_no_value" { | |
| 1527 | err( | |
| 1528 | \\{"": | |
| 1529 | ); | |
| 1530 | } | |
| 1531 | ||
| 1532 | test "n_structure_object_with_comment" { | |
| 1533 | err( | |
| 1534 | \\{"a":/*comment*/"b"} | |
| 1535 | ); | |
| 1536 | } | |
| 1537 | ||
| 1538 | test "n_structure_object_with_trailing_garbage" { | |
| 1539 | err( | |
| 1540 | \\{"a": true} "x" | |
| 1541 | ); | |
| 1542 | } | |
| 1543 | ||
| 1544 | test "n_structure_open_array_apostrophe" { | |
| 1545 | err( | |
| 1546 | \\[' | |
| 1547 | ); | |
| 1548 | } | |
| 1549 | ||
| 1550 | test "n_structure_open_array_comma" { | |
| 1551 | err( | |
| 1552 | \\[, | |
| 1553 | ); | |
| 1554 | } | |
| 1555 | ||
| 1556 | test "n_structure_open_array_object" { | |
| 1557 | err("[{\"\":" ** 50000); | |
| 1558 | } | |
| 1559 | ||
| 1560 | test "n_structure_open_array_open_object" { | |
| 1561 | err( | |
| 1562 | \\[{ | |
| 1563 | ); | |
| 1564 | } | |
| 1565 | ||
| 1566 | test "n_structure_open_array_open_string" { | |
| 1567 | err( | |
| 1568 | \\["a | |
| 1569 | ); | |
| 1570 | } | |
| 1571 | ||
| 1572 | test "n_structure_open_array_string" { | |
| 1573 | err( | |
| 1574 | \\["a" | |
| 1575 | ); | |
| 1576 | } | |
| 1577 | ||
| 1578 | test "n_structure_open_object_close_array" { | |
| 1579 | err( | |
| 1580 | \\{] | |
| 1581 | ); | |
| 1582 | } | |
| 1583 | ||
| 1584 | test "n_structure_open_object_comma" { | |
| 1585 | err( | |
| 1586 | \\{, | |
| 1587 | ); | |
| 1588 | } | |
| 1589 | ||
| 1590 | test "n_structure_open_object" { | |
| 1591 | err( | |
| 1592 | \\{ | |
| 1593 | ); | |
| 1594 | } | |
| 1595 | ||
| 1596 | test "n_structure_open_object_open_array" { | |
| 1597 | err( | |
| 1598 | \\{[ | |
| 1599 | ); | |
| 1600 | } | |
| 1601 | ||
| 1602 | test "n_structure_open_object_open_string" { | |
| 1603 | err( | |
| 1604 | \\{"a | |
| 1605 | ); | |
| 1606 | } | |
| 1607 | ||
| 1608 | test "n_structure_open_object_string_with_apostrophes" { | |
| 1609 | err( | |
| 1610 | \\{'a' | |
| 1611 | ); | |
| 1612 | } | |
| 1613 | ||
| 1614 | test "n_structure_open_open" { | |
| 1615 | err( | |
| 1616 | \\["\{["\{["\{["\{ | |
| 1617 | ); | |
| 1618 | } | |
| 1619 | ||
| 1620 | test "n_structure_single_eacute" { | |
| 1621 | err( | |
| 1622 | \\é | |
| 1623 | ); | |
| 1624 | } | |
| 1625 | ||
| 1626 | test "n_structure_single_star" { | |
| 1627 | err( | |
| 1628 | \\* | |
| 1629 | ); | |
| 1630 | } | |
| 1631 | ||
| 1632 | test "n_structure_trailing_#" { | |
| 1633 | err( | |
| 1634 | \\{"a":"b"}#{} | |
| 1635 | ); | |
| 1636 | } | |
| 1637 | ||
| 1638 | test "n_structure_U+2060_word_joined" { | |
| 1639 | err( | |
| 1640 | \\[â ] | |
| 1641 | ); | |
| 1642 | } | |
| 1643 | ||
| 1644 | test "n_structure_uescaped_LF_before_string" { | |
| 1645 | err( | |
| 1646 | \\[\u000A""] | |
| 1647 | ); | |
| 1648 | } | |
| 1649 | ||
| 1650 | test "n_structure_unclosed_array" { | |
| 1651 | err( | |
| 1652 | \\[1 | |
| 1653 | ); | |
| 1654 | } | |
| 1655 | ||
| 1656 | test "n_structure_unclosed_array_partial_null" { | |
| 1657 | err( | |
| 1658 | \\[ false, nul | |
| 1659 | ); | |
| 1660 | } | |
| 1661 | ||
| 1662 | test "n_structure_unclosed_array_unfinished_false" { | |
| 1663 | err( | |
| 1664 | \\[ true, fals | |
| 1665 | ); | |
| 1666 | } | |
| 1667 | ||
| 1668 | test "n_structure_unclosed_array_unfinished_true" { | |
| 1669 | err( | |
| 1670 | \\[ false, tru | |
| 1671 | ); | |
| 1672 | } | |
| 1673 | ||
| 1674 | test "n_structure_unclosed_object" { | |
| 1675 | err( | |
| 1676 | \\{"asd":"asd" | |
| 1677 | ); | |
| 1678 | } | |
| 1679 | ||
| 1680 | test "n_structure_unicode-identifier" { | |
| 1681 | err( | |
| 1682 | \\Ã¥ | |
| 1683 | ); | |
| 1684 | } | |
| 1685 | ||
| 1686 | test "n_structure_UTF8_BOM_no_data" { | |
| 1687 | err( | |
| 1688 | \\ | |
| 1689 | ); | |
| 1690 | } | |
| 1691 | ||
| 1692 | test "n_structure_whitespace_formfeed" { | |
| 1693 | err("[\x0c]"); | |
| 1694 | } | |
| 1695 | ||
| 1696 | test "n_structure_whitespace_U+2060_word_joiner" { | |
| 1697 | err( | |
| 1698 | \\[â ] | |
| 1699 | ); | |
| 1700 | } | |
| 1701 | ||
| 1702 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 1703 | ||
| 1704 | test "i_number_double_huge_neg_exp" { | |
| 1705 | any( | |
| 1706 | \\[123.456e-789] | |
| 1707 | ); | |
| 1708 | } | |
| 1709 | ||
| 1710 | test "i_number_huge_exp" { | |
| 1711 | any( | |
| 1712 | \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006] | |
| 1713 | ); | |
| 1714 | } | |
| 1715 | ||
| 1716 | test "i_number_neg_int_huge_exp" { | |
| 1717 | any( | |
| 1718 | \\[-1e+9999] | |
| 1719 | ); | |
| 1720 | } | |
| 1721 | ||
| 1722 | test "i_number_pos_double_huge_exp" { | |
| 1723 | any( | |
| 1724 | \\[1.5e+9999] | |
| 1725 | ); | |
| 1726 | } | |
| 1727 | ||
| 1728 | test "i_number_real_neg_overflow" { | |
| 1729 | any( | |
| 1730 | \\[-123123e100000] | |
| 1731 | ); | |
| 1732 | } | |
| 1733 | ||
| 1734 | test "i_number_real_pos_overflow" { | |
| 1735 | any( | |
| 1736 | \\[123123e100000] | |
| 1737 | ); | |
| 1738 | } | |
| 1739 | ||
| 1740 | test "i_number_real_underflow" { | |
| 1741 | any( | |
| 1742 | \\[123e-10000000] | |
| 1743 | ); | |
| 1744 | } | |
| 1745 | ||
| 1746 | test "i_number_too_big_neg_int" { | |
| 1747 | any( | |
| 1748 | \\[-123123123123123123123123123123] | |
| 1749 | ); | |
| 1750 | } | |
| 1751 | ||
| 1752 | test "i_number_too_big_pos_int" { | |
| 1753 | any( | |
| 1754 | \\[100000000000000000000] | |
| 1755 | ); | |
| 1756 | } | |
| 1757 | ||
| 1758 | test "i_number_very_big_negative_int" { | |
| 1759 | any( | |
| 1760 | \\[-237462374673276894279832749832423479823246327846] | |
| 1761 | ); | |
| 1762 | } | |
| 1763 | ||
| 1764 | test "i_object_key_lone_2nd_surrogate" { | |
| 1765 | any( | |
| 1766 | \\{"\uDFAA":0} | |
| 1767 | ); | |
| 1768 | } | |
| 1769 | ||
| 1770 | test "i_string_1st_surrogate_but_2nd_missing" { | |
| 1771 | any( | |
| 1772 | \\["\uDADA"] | |
| 1773 | ); | |
| 1774 | } | |
| 1775 | ||
| 1776 | test "i_string_1st_valid_surrogate_2nd_invalid" { | |
| 1777 | any( | |
| 1778 | \\["\uD888\u1234"] | |
| 1779 | ); | |
| 1780 | } | |
| 1781 | ||
| 1782 | test "i_string_incomplete_surrogate_and_escape_valid" { | |
| 1783 | any( | |
| 1784 | \\["\uD800\n"] | |
| 1785 | ); | |
| 1786 | } | |
| 1787 | ||
| 1788 | test "i_string_incomplete_surrogate_pair" { | |
| 1789 | any( | |
| 1790 | \\["\uDd1ea"] | |
| 1791 | ); | |
| 1792 | } | |
| 1793 | ||
| 1794 | test "i_string_incomplete_surrogates_escape_valid" { | |
| 1795 | any( | |
| 1796 | \\["\uD800\uD800\n"] | |
| 1797 | ); | |
| 1798 | } | |
| 1799 | ||
| 1800 | test "i_string_invalid_lonely_surrogate" { | |
| 1801 | any( | |
| 1802 | \\["\ud800"] | |
| 1803 | ); | |
| 1804 | } | |
| 1805 | ||
| 1806 | test "i_string_invalid_surrogate" { | |
| 1807 | any( | |
| 1808 | \\["\ud800abc"] | |
| 1809 | ); | |
| 1810 | } | |
| 1811 | ||
| 1812 | test "i_string_invalid_utf-8" { | |
| 1813 | any( | |
| 1814 | \\["ÿ"] | |
| 1815 | ); | |
| 1816 | } | |
| 1817 | ||
| 1818 | test "i_string_inverted_surrogates_U+1D11E" { | |
| 1819 | any( | |
| 1820 | \\["\uDd1e\uD834"] | |
| 1821 | ); | |
| 1822 | } | |
| 1823 | ||
| 1824 | test "i_string_iso_latin_1" { | |
| 1825 | any( | |
| 1826 | \\["é"] | |
| 1827 | ); | |
| 1828 | } | |
| 1829 | ||
| 1830 | test "i_string_lone_second_surrogate" { | |
| 1831 | any( | |
| 1832 | \\["\uDFAA"] | |
| 1833 | ); | |
| 1834 | } | |
| 1835 | ||
| 1836 | test "i_string_lone_utf8_continuation_byte" { | |
| 1837 | any( | |
| 1838 | \\[""] | |
| 1839 | ); | |
| 1840 | } | |
| 1841 | ||
| 1842 | test "i_string_not_in_unicode_range" { | |
| 1843 | any( | |
| 1844 | \\["ô¿¿¿"] | |
| 1845 | ); | |
| 1846 | } | |
| 1847 | ||
| 1848 | test "i_string_overlong_sequence_2_bytes" { | |
| 1849 | any( | |
| 1850 | \\["À¯"] | |
| 1851 | ); | |
| 1852 | } | |
| 1853 | ||
| 1854 | test "i_string_overlong_sequence_6_bytes" { | |
| 1855 | any( | |
| 1856 | \\["ü¿¿¿¿"] | |
| 1857 | ); | |
| 1858 | } | |
| 1859 | ||
| 1860 | test "i_string_overlong_sequence_6_bytes_null" { | |
| 1861 | any( | |
| 1862 | \\["ü"] | |
| 1863 | ); | |
| 1864 | } | |
| 1865 | ||
| 1866 | test "i_string_truncated-utf-8" { | |
| 1867 | any( | |
| 1868 | \\["àÿ"] | |
| 1869 | ); | |
| 1870 | } | |
| 1871 | ||
| 1872 | test "i_string_utf16BE_no_BOM" { | |
| 1873 | any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d"); | |
| 1874 | } | |
| 1875 | ||
| 1876 | test "i_string_utf16LE_no_BOM" { | |
| 1877 | any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00"); | |
| 1878 | } | |
| 1879 | ||
| 1880 | 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 | ||
| 1884 | test "i_string_UTF-8_invalid_sequence" { | |
| 1885 | any( | |
| 1886 | \\["æ¥Ñú"] | |
| 1887 | ); | |
| 1888 | } | |
| 1889 | ||
| 1890 | test "i_string_UTF8_surrogate_U+D800" { | |
| 1891 | any( | |
| 1892 | \\["í "] | |
| 1893 | ); | |
| 1894 | } | |
| 1895 | ||
| 1896 | test "i_structure_500_nested_arrays" { | |
| 1897 | any(("[" ** 500) ++ ("]" ** 500)); | |
| 1898 | } | |
| 1899 | ||
| 1900 | test "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 | ||
| 6 | const std = @import("std.zig"); | |
| 7 | ||
| 8 | fn ok(comptime s: []const u8) void { | |
| 9 | std.testing.expect(std.json.validate(s)); | |
| 10 | } | |
| 11 | ||
| 12 | fn err(comptime s: []const u8) void { | |
| 13 | std.testing.expect(!std.json.validate(s)); | |
| 14 | } | |
| 15 | ||
| 16 | fn any(comptime s: []const u8) void { | |
| 17 | std.testing.expect(true); | |
| 18 | } | |
| 19 | ||
| 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 21 | // | |
| 22 | // Additional tests not part of test JSONTestSuite. | |
| 23 | ||
| 24 | test "json.test.y_trailing_comma_after_empty" { | |
| 25 | ok( | |
| 26 | \\{"1":[],"2":{},"3":"4"} | |
| 27 | ); | |
| 28 | } | |
| 29 | ||
| 30 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 31 | ||
| 32 | test "json.test.y_array_arraysWithSpaces" { | |
| 33 | ok( | |
| 34 | \\[[] ] | |
| 35 | ); | |
| 36 | } | |
| 37 | ||
| 38 | test "json.test.y_array_empty" { | |
| 39 | ok( | |
| 40 | \\[] | |
| 41 | ); | |
| 42 | } | |
| 43 | ||
| 44 | test "json.test.y_array_empty-string" { | |
| 45 | ok( | |
| 46 | \\[""] | |
| 47 | ); | |
| 48 | } | |
| 49 | ||
| 50 | test "json.test.y_array_ending_with_newline" { | |
| 51 | ok( | |
| 52 | \\["a"] | |
| 53 | ); | |
| 54 | } | |
| 55 | ||
| 56 | test "json.test.y_array_false" { | |
| 57 | ok( | |
| 58 | \\[false] | |
| 59 | ); | |
| 60 | } | |
| 61 | ||
| 62 | test "json.test.y_array_heterogeneous" { | |
| 63 | ok( | |
| 64 | \\[null, 1, "1", {}] | |
| 65 | ); | |
| 66 | } | |
| 67 | ||
| 68 | test "json.test.y_array_null" { | |
| 69 | ok( | |
| 70 | \\[null] | |
| 71 | ); | |
| 72 | } | |
| 73 | ||
| 74 | test "json.test.y_array_with_1_and_newline" { | |
| 75 | ok( | |
| 76 | \\[1 | |
| 77 | \\] | |
| 78 | ); | |
| 79 | } | |
| 80 | ||
| 81 | test "json.test.y_array_with_leading_space" { | |
| 82 | ok( | |
| 83 | \\ [1] | |
| 84 | ); | |
| 85 | } | |
| 86 | ||
| 87 | test "json.test.y_array_with_several_null" { | |
| 88 | ok( | |
| 89 | \\[1,null,null,null,2] | |
| 90 | ); | |
| 91 | } | |
| 92 | ||
| 93 | test "json.test.y_array_with_trailing_space" { | |
| 94 | ok("[2] "); | |
| 95 | } | |
| 96 | ||
| 97 | test "json.test.y_number_0e+1" { | |
| 98 | ok( | |
| 99 | \\[0e+1] | |
| 100 | ); | |
| 101 | } | |
| 102 | ||
| 103 | test "json.test.y_number_0e1" { | |
| 104 | ok( | |
| 105 | \\[0e1] | |
| 106 | ); | |
| 107 | } | |
| 108 | ||
| 109 | test "json.test.y_number_after_space" { | |
| 110 | ok( | |
| 111 | \\[ 4] | |
| 112 | ); | |
| 113 | } | |
| 114 | ||
| 115 | test "json.test.y_number_double_close_to_zero" { | |
| 116 | ok( | |
| 117 | \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001] | |
| 118 | ); | |
| 119 | } | |
| 120 | ||
| 121 | test "json.test.y_number_int_with_exp" { | |
| 122 | ok( | |
| 123 | \\[20e1] | |
| 124 | ); | |
| 125 | } | |
| 126 | ||
| 127 | test "json.test.y_number" { | |
| 128 | ok( | |
| 129 | \\[123e65] | |
| 130 | ); | |
| 131 | } | |
| 132 | ||
| 133 | test "json.test.y_number_minus_zero" { | |
| 134 | ok( | |
| 135 | \\[-0] | |
| 136 | ); | |
| 137 | } | |
| 138 | ||
| 139 | test "json.test.y_number_negative_int" { | |
| 140 | ok( | |
| 141 | \\[-123] | |
| 142 | ); | |
| 143 | } | |
| 144 | ||
| 145 | test "json.test.y_number_negative_one" { | |
| 146 | ok( | |
| 147 | \\[-1] | |
| 148 | ); | |
| 149 | } | |
| 150 | ||
| 151 | test "json.test.y_number_negative_zero" { | |
| 152 | ok( | |
| 153 | \\[-0] | |
| 154 | ); | |
| 155 | } | |
| 156 | ||
| 157 | test "json.test.y_number_real_capital_e" { | |
| 158 | ok( | |
| 159 | \\[1E22] | |
| 160 | ); | |
| 161 | } | |
| 162 | ||
| 163 | test "json.test.y_number_real_capital_e_neg_exp" { | |
| 164 | ok( | |
| 165 | \\[1E-2] | |
| 166 | ); | |
| 167 | } | |
| 168 | ||
| 169 | test "json.test.y_number_real_capital_e_pos_exp" { | |
| 170 | ok( | |
| 171 | \\[1E+2] | |
| 172 | ); | |
| 173 | } | |
| 174 | ||
| 175 | test "json.test.y_number_real_exponent" { | |
| 176 | ok( | |
| 177 | \\[123e45] | |
| 178 | ); | |
| 179 | } | |
| 180 | ||
| 181 | test "json.test.y_number_real_fraction_exponent" { | |
| 182 | ok( | |
| 183 | \\[123.456e78] | |
| 184 | ); | |
| 185 | } | |
| 186 | ||
| 187 | test "json.test.y_number_real_neg_exp" { | |
| 188 | ok( | |
| 189 | \\[1e-2] | |
| 190 | ); | |
| 191 | } | |
| 192 | ||
| 193 | test "json.test.y_number_real_pos_exponent" { | |
| 194 | ok( | |
| 195 | \\[1e+2] | |
| 196 | ); | |
| 197 | } | |
| 198 | ||
| 199 | test "json.test.y_number_simple_int" { | |
| 200 | ok( | |
| 201 | \\[123] | |
| 202 | ); | |
| 203 | } | |
| 204 | ||
| 205 | test "json.test.y_number_simple_real" { | |
| 206 | ok( | |
| 207 | \\[123.456789] | |
| 208 | ); | |
| 209 | } | |
| 210 | ||
| 211 | test "json.test.y_object_basic" { | |
| 212 | ok( | |
| 213 | \\{"asd":"sdf"} | |
| 214 | ); | |
| 215 | } | |
| 216 | ||
| 217 | test "json.test.y_object_duplicated_key_and_value" { | |
| 218 | ok( | |
| 219 | \\{"a":"b","a":"b"} | |
| 220 | ); | |
| 221 | } | |
| 222 | ||
| 223 | test "json.test.y_object_duplicated_key" { | |
| 224 | ok( | |
| 225 | \\{"a":"b","a":"c"} | |
| 226 | ); | |
| 227 | } | |
| 228 | ||
| 229 | test "json.test.y_object_empty" { | |
| 230 | ok( | |
| 231 | \\{} | |
| 232 | ); | |
| 233 | } | |
| 234 | ||
| 235 | test "json.test.y_object_empty_key" { | |
| 236 | ok( | |
| 237 | \\{"":0} | |
| 238 | ); | |
| 239 | } | |
| 240 | ||
| 241 | test "json.test.y_object_escaped_null_in_key" { | |
| 242 | ok( | |
| 243 | \\{"foo\u0000bar": 42} | |
| 244 | ); | |
| 245 | } | |
| 246 | ||
| 247 | test "json.test.y_object_extreme_numbers" { | |
| 248 | ok( | |
| 249 | \\{ "min": -1.0e+28, "max": 1.0e+28 } | |
| 250 | ); | |
| 251 | } | |
| 252 | ||
| 253 | test "json.test.y_object" { | |
| 254 | ok( | |
| 255 | \\{"asd":"sdf", "dfg":"fgh"} | |
| 256 | ); | |
| 257 | } | |
| 258 | ||
| 259 | test "json.test.y_object_long_strings" { | |
| 260 | ok( | |
| 261 | \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} | |
| 262 | ); | |
| 263 | } | |
| 264 | ||
| 265 | test "json.test.y_object_simple" { | |
| 266 | ok( | |
| 267 | \\{"a":[]} | |
| 268 | ); | |
| 269 | } | |
| 270 | ||
| 271 | test "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 | ||
| 277 | test "json.test.y_object_with_newlines" { | |
| 278 | ok( | |
| 279 | \\{ | |
| 280 | \\"a": "b" | |
| 281 | \\} | |
| 282 | ); | |
| 283 | } | |
| 284 | ||
| 285 | test "json.test.y_string_1_2_3_bytes_UTF-8_sequences" { | |
| 286 | ok( | |
| 287 | \\["\u0060\u012a\u12AB"] | |
| 288 | ); | |
| 289 | } | |
| 290 | ||
| 291 | test "json.test.y_string_accepted_surrogate_pair" { | |
| 292 | ok( | |
| 293 | \\["\uD801\udc37"] | |
| 294 | ); | |
| 295 | } | |
| 296 | ||
| 297 | test "json.test.y_string_accepted_surrogate_pairs" { | |
| 298 | ok( | |
| 299 | \\["\ud83d\ude39\ud83d\udc8d"] | |
| 300 | ); | |
| 301 | } | |
| 302 | ||
| 303 | test "json.test.y_string_allowed_escapes" { | |
| 304 | ok( | |
| 305 | \\["\"\\\/\b\f\n\r\t"] | |
| 306 | ); | |
| 307 | } | |
| 308 | ||
| 309 | test "json.test.y_string_backslash_and_u_escaped_zero" { | |
| 310 | ok( | |
| 311 | \\["\\u0000"] | |
| 312 | ); | |
| 313 | } | |
| 314 | ||
| 315 | test "json.test.y_string_backslash_doublequotes" { | |
| 316 | ok( | |
| 317 | \\["\""] | |
| 318 | ); | |
| 319 | } | |
| 320 | ||
| 321 | test "json.test.y_string_comments" { | |
| 322 | ok( | |
| 323 | \\["a/*b*/c/*d//e"] | |
| 324 | ); | |
| 325 | } | |
| 326 | ||
| 327 | test "json.test.y_string_double_escape_a" { | |
| 328 | ok( | |
| 329 | \\["\\a"] | |
| 330 | ); | |
| 331 | } | |
| 332 | ||
| 333 | test "json.test.y_string_double_escape_n" { | |
| 334 | ok( | |
| 335 | \\["\\n"] | |
| 336 | ); | |
| 337 | } | |
| 338 | ||
| 339 | test "json.test.y_string_escaped_control_character" { | |
| 340 | ok( | |
| 341 | \\["\u0012"] | |
| 342 | ); | |
| 343 | } | |
| 344 | ||
| 345 | test "json.test.y_string_escaped_noncharacter" { | |
| 346 | ok( | |
| 347 | \\["\uFFFF"] | |
| 348 | ); | |
| 349 | } | |
| 350 | ||
| 351 | test "json.test.y_string_in_array" { | |
| 352 | ok( | |
| 353 | \\["asd"] | |
| 354 | ); | |
| 355 | } | |
| 356 | ||
| 357 | test "json.test.y_string_in_array_with_leading_space" { | |
| 358 | ok( | |
| 359 | \\[ "asd"] | |
| 360 | ); | |
| 361 | } | |
| 362 | ||
| 363 | test "json.test.y_string_last_surrogates_1_and_2" { | |
| 364 | ok( | |
| 365 | \\["\uDBFF\uDFFF"] | |
| 366 | ); | |
| 367 | } | |
| 368 | ||
| 369 | test "json.test.y_string_nbsp_uescaped" { | |
| 370 | ok( | |
| 371 | \\["new\u00A0line"] | |
| 372 | ); | |
| 373 | } | |
| 374 | ||
| 375 | test "json.test.y_string_nonCharacterInUTF-8_U+10FFFF" { | |
| 376 | ok( | |
| 377 | \\[""] | |
| 378 | ); | |
| 379 | } | |
| 380 | ||
| 381 | test "json.test.y_string_nonCharacterInUTF-8_U+FFFF" { | |
| 382 | ok( | |
| 383 | \\[""] | |
| 384 | ); | |
| 385 | } | |
| 386 | ||
| 387 | test "json.test.y_string_null_escape" { | |
| 388 | ok( | |
| 389 | \\["\u0000"] | |
| 390 | ); | |
| 391 | } | |
| 392 | ||
| 393 | test "json.test.y_string_one-byte-utf-8" { | |
| 394 | ok( | |
| 395 | \\["\u002c"] | |
| 396 | ); | |
| 397 | } | |
| 398 | ||
| 399 | test "json.test.y_string_pi" { | |
| 400 | ok( | |
| 401 | \\["π"] | |
| 402 | ); | |
| 403 | } | |
| 404 | ||
| 405 | test "json.test.y_string_reservedCharacterInUTF-8_U+1BFFF" { | |
| 406 | ok( | |
| 407 | \\[""] | |
| 408 | ); | |
| 409 | } | |
| 410 | ||
| 411 | test "json.test.y_string_simple_ascii" { | |
| 412 | ok( | |
| 413 | \\["asd "] | |
| 414 | ); | |
| 415 | } | |
| 416 | ||
| 417 | test "json.test.y_string_space" { | |
| 418 | ok( | |
| 419 | \\" " | |
| 420 | ); | |
| 421 | } | |
| 422 | ||
| 423 | test "json.test.y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" { | |
| 424 | ok( | |
| 425 | \\["\uD834\uDd1e"] | |
| 426 | ); | |
| 427 | } | |
| 428 | ||
| 429 | test "json.test.y_string_three-byte-utf-8" { | |
| 430 | ok( | |
| 431 | \\["\u0821"] | |
| 432 | ); | |
| 433 | } | |
| 434 | ||
| 435 | test "json.test.y_string_two-byte-utf-8" { | |
| 436 | ok( | |
| 437 | \\["\u0123"] | |
| 438 | ); | |
| 439 | } | |
| 440 | ||
| 441 | test "json.test.y_string_u+2028_line_sep" { | |
| 442 | ok("[\"\xe2\x80\xa8\"]"); | |
| 443 | } | |
| 444 | ||
| 445 | test "json.test.y_string_u+2029_par_sep" { | |
| 446 | ok("[\"\xe2\x80\xa9\"]"); | |
| 447 | } | |
| 448 | ||
| 449 | test "json.test.y_string_uescaped_newline" { | |
| 450 | ok( | |
| 451 | \\["new\u000Aline"] | |
| 452 | ); | |
| 453 | } | |
| 454 | ||
| 455 | test "json.test.y_string_uEscape" { | |
| 456 | ok( | |
| 457 | \\["\u0061\u30af\u30EA\u30b9"] | |
| 458 | ); | |
| 459 | } | |
| 460 | ||
| 461 | test "json.test.y_string_unescaped_char_delete" { | |
| 462 | ok("[\"\x7f\"]"); | |
| 463 | } | |
| 464 | ||
| 465 | test "json.test.y_string_unicode_2" { | |
| 466 | ok( | |
| 467 | \\["⍂㈴⍂"] | |
| 468 | ); | |
| 469 | } | |
| 470 | ||
| 471 | test "json.test.y_string_unicodeEscapedBackslash" { | |
| 472 | ok( | |
| 473 | \\["\u005C"] | |
| 474 | ); | |
| 475 | } | |
| 476 | ||
| 477 | test "json.test.y_string_unicode_escaped_double_quote" { | |
| 478 | ok( | |
| 479 | \\["\u0022"] | |
| 480 | ); | |
| 481 | } | |
| 482 | ||
| 483 | test "json.test.y_string_unicode" { | |
| 484 | ok( | |
| 485 | \\["\uA66D"] | |
| 486 | ); | |
| 487 | } | |
| 488 | ||
| 489 | test "json.test.y_string_unicode_U+10FFFE_nonchar" { | |
| 490 | ok( | |
| 491 | \\["\uDBFF\uDFFE"] | |
| 492 | ); | |
| 493 | } | |
| 494 | ||
| 495 | test "json.test.y_string_unicode_U+1FFFE_nonchar" { | |
| 496 | ok( | |
| 497 | \\["\uD83F\uDFFE"] | |
| 498 | ); | |
| 499 | } | |
| 500 | ||
| 501 | test "json.test.y_string_unicode_U+200B_ZERO_WIDTH_SPACE" { | |
| 502 | ok( | |
| 503 | \\["\u200B"] | |
| 504 | ); | |
| 505 | } | |
| 506 | ||
| 507 | test "json.test.y_string_unicode_U+2064_invisible_plus" { | |
| 508 | ok( | |
| 509 | \\["\u2064"] | |
| 510 | ); | |
| 511 | } | |
| 512 | ||
| 513 | test "json.test.y_string_unicode_U+FDD0_nonchar" { | |
| 514 | ok( | |
| 515 | \\["\uFDD0"] | |
| 516 | ); | |
| 517 | } | |
| 518 | ||
| 519 | test "json.test.y_string_unicode_U+FFFE_nonchar" { | |
| 520 | ok( | |
| 521 | \\["\uFFFE"] | |
| 522 | ); | |
| 523 | } | |
| 524 | ||
| 525 | test "json.test.y_string_utf8" { | |
| 526 | ok( | |
| 527 | \\["€𝄞"] | |
| 528 | ); | |
| 529 | } | |
| 530 | ||
| 531 | test "json.test.y_string_with_del_character" { | |
| 532 | ok("[\"a\x7fa\"]"); | |
| 533 | } | |
| 534 | ||
| 535 | test "json.test.y_structure_lonely_false" { | |
| 536 | ok( | |
| 537 | \\false | |
| 538 | ); | |
| 539 | } | |
| 540 | ||
| 541 | test "json.test.y_structure_lonely_int" { | |
| 542 | ok( | |
| 543 | \\42 | |
| 544 | ); | |
| 545 | } | |
| 546 | ||
| 547 | test "json.test.y_structure_lonely_negative_real" { | |
| 548 | ok( | |
| 549 | \\-0.1 | |
| 550 | ); | |
| 551 | } | |
| 552 | ||
| 553 | test "json.test.y_structure_lonely_null" { | |
| 554 | ok( | |
| 555 | \\null | |
| 556 | ); | |
| 557 | } | |
| 558 | ||
| 559 | test "json.test.y_structure_lonely_string" { | |
| 560 | ok( | |
| 561 | \\"asd" | |
| 562 | ); | |
| 563 | } | |
| 564 | ||
| 565 | test "json.test.y_structure_lonely_true" { | |
| 566 | ok( | |
| 567 | \\true | |
| 568 | ); | |
| 569 | } | |
| 570 | ||
| 571 | test "json.test.y_structure_string_empty" { | |
| 572 | ok( | |
| 573 | \\"" | |
| 574 | ); | |
| 575 | } | |
| 576 | ||
| 577 | test "json.test.y_structure_trailing_newline" { | |
| 578 | ok( | |
| 579 | \\["a"] | |
| 580 | ); | |
| 581 | } | |
| 582 | ||
| 583 | test "json.test.y_structure_true_in_array" { | |
| 584 | ok( | |
| 585 | \\[true] | |
| 586 | ); | |
| 587 | } | |
| 588 | ||
| 589 | test "json.test.y_structure_whitespace_array" { | |
| 590 | ok(" [] "); | |
| 591 | } | |
| 592 | ||
| 593 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 594 | ||
| 595 | test "json.test.n_array_1_true_without_comma" { | |
| 596 | err( | |
| 597 | \\[1 true] | |
| 598 | ); | |
| 599 | } | |
| 600 | ||
| 601 | test "json.test.n_array_a_invalid_utf8" { | |
| 602 | err( | |
| 603 | \\[aå] | |
| 604 | ); | |
| 605 | } | |
| 606 | ||
| 607 | test "json.test.n_array_colon_instead_of_comma" { | |
| 608 | err( | |
| 609 | \\["": 1] | |
| 610 | ); | |
| 611 | } | |
| 612 | ||
| 613 | test "json.test.n_array_comma_after_close" { | |
| 614 | //err( | |
| 615 | // \\[""], | |
| 616 | //); | |
| 617 | } | |
| 618 | ||
| 619 | test "json.test.n_array_comma_and_number" { | |
| 620 | err( | |
| 621 | \\[,1] | |
| 622 | ); | |
| 623 | } | |
| 624 | ||
| 625 | test "json.test.n_array_double_comma" { | |
| 626 | err( | |
| 627 | \\[1,,2] | |
| 628 | ); | |
| 629 | } | |
| 630 | ||
| 631 | test "json.test.n_array_double_extra_comma" { | |
| 632 | err( | |
| 633 | \\["x",,] | |
| 634 | ); | |
| 635 | } | |
| 636 | ||
| 637 | test "json.test.n_array_extra_close" { | |
| 638 | err( | |
| 639 | \\["x"]] | |
| 640 | ); | |
| 641 | } | |
| 642 | ||
| 643 | test "json.test.n_array_extra_comma" { | |
| 644 | //err( | |
| 645 | // \\["",] | |
| 646 | //); | |
| 647 | } | |
| 648 | ||
| 649 | test "json.test.n_array_incomplete_invalid_value" { | |
| 650 | err( | |
| 651 | \\[x | |
| 652 | ); | |
| 653 | } | |
| 654 | ||
| 655 | test "json.test.n_array_incomplete" { | |
| 656 | err( | |
| 657 | \\["x" | |
| 658 | ); | |
| 659 | } | |
| 660 | ||
| 661 | test "json.test.n_array_inner_array_no_comma" { | |
| 662 | err( | |
| 663 | \\[3[4]] | |
| 664 | ); | |
| 665 | } | |
| 666 | ||
| 667 | test "json.test.n_array_invalid_utf8" { | |
| 668 | err( | |
| 669 | \\[ÿ] | |
| 670 | ); | |
| 671 | } | |
| 672 | ||
| 673 | test "json.test.n_array_items_separated_by_semicolon" { | |
| 674 | err( | |
| 675 | \\[1:2] | |
| 676 | ); | |
| 677 | } | |
| 678 | ||
| 679 | test "json.test.n_array_just_comma" { | |
| 680 | err( | |
| 681 | \\[,] | |
| 682 | ); | |
| 683 | } | |
| 684 | ||
| 685 | test "json.test.n_array_just_minus" { | |
| 686 | err( | |
| 687 | \\[-] | |
| 688 | ); | |
| 689 | } | |
| 690 | ||
| 691 | test "json.test.n_array_missing_value" { | |
| 692 | err( | |
| 693 | \\[ , ""] | |
| 694 | ); | |
| 695 | } | |
| 696 | ||
| 697 | test "json.test.n_array_newlines_unclosed" { | |
| 698 | err( | |
| 699 | \\["a", | |
| 700 | \\4 | |
| 701 | \\,1, | |
| 702 | ); | |
| 703 | } | |
| 704 | ||
| 705 | test "json.test.n_array_number_and_comma" { | |
| 706 | err( | |
| 707 | \\[1,] | |
| 708 | ); | |
| 709 | } | |
| 710 | ||
| 711 | test "json.test.n_array_number_and_several_commas" { | |
| 712 | err( | |
| 713 | \\[1,,] | |
| 714 | ); | |
| 715 | } | |
| 716 | ||
| 717 | test "json.test.n_array_spaces_vertical_tab_formfeed" { | |
| 718 | err("[\"\x0aa\"\\f]"); | |
| 719 | } | |
| 720 | ||
| 721 | test "json.test.n_array_star_inside" { | |
| 722 | err( | |
| 723 | \\[*] | |
| 724 | ); | |
| 725 | } | |
| 726 | ||
| 727 | test "json.test.n_array_unclosed" { | |
| 728 | err( | |
| 729 | \\["" | |
| 730 | ); | |
| 731 | } | |
| 732 | ||
| 733 | test "json.test.n_array_unclosed_trailing_comma" { | |
| 734 | err( | |
| 735 | \\[1, | |
| 736 | ); | |
| 737 | } | |
| 738 | ||
| 739 | test "json.test.n_array_unclosed_with_new_lines" { | |
| 740 | err( | |
| 741 | \\[1, | |
| 742 | \\1 | |
| 743 | \\,1 | |
| 744 | ); | |
| 745 | } | |
| 746 | ||
| 747 | test "json.test.n_array_unclosed_with_object_inside" { | |
| 748 | err( | |
| 749 | \\[{} | |
| 750 | ); | |
| 751 | } | |
| 752 | ||
| 753 | test "json.test.n_incomplete_false" { | |
| 754 | err( | |
| 755 | \\[fals] | |
| 756 | ); | |
| 757 | } | |
| 758 | ||
| 759 | test "json.test.n_incomplete_null" { | |
| 760 | err( | |
| 761 | \\[nul] | |
| 762 | ); | |
| 763 | } | |
| 764 | ||
| 765 | test "json.test.n_incomplete_true" { | |
| 766 | err( | |
| 767 | \\[tru] | |
| 768 | ); | |
| 769 | } | |
| 770 | ||
| 771 | test "json.test.n_multidigit_number_then_00" { | |
| 772 | err("123\x00"); | |
| 773 | } | |
| 774 | ||
| 775 | test "json.test.n_number_0.1.2" { | |
| 776 | err( | |
| 777 | \\[0.1.2] | |
| 778 | ); | |
| 779 | } | |
| 780 | ||
| 781 | test "json.test.n_number_-01" { | |
| 782 | err( | |
| 783 | \\[-01] | |
| 784 | ); | |
| 785 | } | |
| 786 | ||
| 787 | test "json.test.n_number_0.3e" { | |
| 788 | err( | |
| 789 | \\[0.3e] | |
| 790 | ); | |
| 791 | } | |
| 792 | ||
| 793 | test "json.test.n_number_0.3e+" { | |
| 794 | err( | |
| 795 | \\[0.3e+] | |
| 796 | ); | |
| 797 | } | |
| 798 | ||
| 799 | test "json.test.n_number_0_capital_E" { | |
| 800 | err( | |
| 801 | \\[0E] | |
| 802 | ); | |
| 803 | } | |
| 804 | ||
| 805 | test "json.test.n_number_0_capital_E+" { | |
| 806 | err( | |
| 807 | \\[0E+] | |
| 808 | ); | |
| 809 | } | |
| 810 | ||
| 811 | test "json.test.n_number_0.e1" { | |
| 812 | err( | |
| 813 | \\[0.e1] | |
| 814 | ); | |
| 815 | } | |
| 816 | ||
| 817 | test "json.test.n_number_0e" { | |
| 818 | err( | |
| 819 | \\[0e] | |
| 820 | ); | |
| 821 | } | |
| 822 | ||
| 823 | test "json.test.n_number_0e+" { | |
| 824 | err( | |
| 825 | \\[0e+] | |
| 826 | ); | |
| 827 | } | |
| 828 | ||
| 829 | test "json.test.n_number_1_000" { | |
| 830 | err( | |
| 831 | \\[1 000.0] | |
| 832 | ); | |
| 833 | } | |
| 834 | ||
| 835 | test "json.test.n_number_1.0e-" { | |
| 836 | err( | |
| 837 | \\[1.0e-] | |
| 838 | ); | |
| 839 | } | |
| 840 | ||
| 841 | test "json.test.n_number_1.0e" { | |
| 842 | err( | |
| 843 | \\[1.0e] | |
| 844 | ); | |
| 845 | } | |
| 846 | ||
| 847 | test "json.test.n_number_1.0e+" { | |
| 848 | err( | |
| 849 | \\[1.0e+] | |
| 850 | ); | |
| 851 | } | |
| 852 | ||
| 853 | test "json.test.n_number_-1.0." { | |
| 854 | err( | |
| 855 | \\[-1.0.] | |
| 856 | ); | |
| 857 | } | |
| 858 | ||
| 859 | test "json.test.n_number_1eE2" { | |
| 860 | err( | |
| 861 | \\[1eE2] | |
| 862 | ); | |
| 863 | } | |
| 864 | ||
| 865 | test "json.test.n_number_.-1" { | |
| 866 | err( | |
| 867 | \\[.-1] | |
| 868 | ); | |
| 869 | } | |
| 870 | ||
| 871 | test "json.test.n_number_+1" { | |
| 872 | err( | |
| 873 | \\[+1] | |
| 874 | ); | |
| 875 | } | |
| 876 | ||
| 877 | test "json.test.n_number_.2e-3" { | |
| 878 | err( | |
| 879 | \\[.2e-3] | |
| 880 | ); | |
| 881 | } | |
| 882 | ||
| 883 | test "json.test.n_number_2.e-3" { | |
| 884 | err( | |
| 885 | \\[2.e-3] | |
| 886 | ); | |
| 887 | } | |
| 888 | ||
| 889 | test "json.test.n_number_2.e+3" { | |
| 890 | err( | |
| 891 | \\[2.e+3] | |
| 892 | ); | |
| 893 | } | |
| 894 | ||
| 895 | test "json.test.n_number_2.e3" { | |
| 896 | err( | |
| 897 | \\[2.e3] | |
| 898 | ); | |
| 899 | } | |
| 900 | ||
| 901 | test "json.test.n_number_-2." { | |
| 902 | err( | |
| 903 | \\[-2.] | |
| 904 | ); | |
| 905 | } | |
| 906 | ||
| 907 | test "json.test.n_number_9.e+" { | |
| 908 | err( | |
| 909 | \\[9.e+] | |
| 910 | ); | |
| 911 | } | |
| 912 | ||
| 913 | test "json.test.n_number_expression" { | |
| 914 | err( | |
| 915 | \\[1+2] | |
| 916 | ); | |
| 917 | } | |
| 918 | ||
| 919 | test "json.test.n_number_hex_1_digit" { | |
| 920 | err( | |
| 921 | \\[0x1] | |
| 922 | ); | |
| 923 | } | |
| 924 | ||
| 925 | test "json.test.n_number_hex_2_digits" { | |
| 926 | err( | |
| 927 | \\[0x42] | |
| 928 | ); | |
| 929 | } | |
| 930 | ||
| 931 | test "json.test.n_number_infinity" { | |
| 932 | err( | |
| 933 | \\[Infinity] | |
| 934 | ); | |
| 935 | } | |
| 936 | ||
| 937 | test "json.test.n_number_+Inf" { | |
| 938 | err( | |
| 939 | \\[+Inf] | |
| 940 | ); | |
| 941 | } | |
| 942 | ||
| 943 | test "json.test.n_number_Inf" { | |
| 944 | err( | |
| 945 | \\[Inf] | |
| 946 | ); | |
| 947 | } | |
| 948 | ||
| 949 | test "json.test.n_number_invalid+-" { | |
| 950 | err( | |
| 951 | \\[0e+-1] | |
| 952 | ); | |
| 953 | } | |
| 954 | ||
| 955 | test "json.test.n_number_invalid-negative-real" { | |
| 956 | err( | |
| 957 | \\[-123.123foo] | |
| 958 | ); | |
| 959 | } | |
| 960 | ||
| 961 | test "json.test.n_number_invalid-utf-8-in-bigger-int" { | |
| 962 | err( | |
| 963 | \\[123å] | |
| 964 | ); | |
| 965 | } | |
| 966 | ||
| 967 | test "json.test.n_number_invalid-utf-8-in-exponent" { | |
| 968 | err( | |
| 969 | \\[1e1å] | |
| 970 | ); | |
| 971 | } | |
| 972 | ||
| 973 | test "json.test.n_number_invalid-utf-8-in-int" { | |
| 974 | err( | |
| 975 | \\[0å] | |
| 976 | ); | |
| 977 | } | |
| 978 | ||
| 979 | test "json.test.n_number_++" { | |
| 980 | err( | |
| 981 | \\[++1234] | |
| 982 | ); | |
| 983 | } | |
| 984 | ||
| 985 | test "json.test.n_number_minus_infinity" { | |
| 986 | err( | |
| 987 | \\[-Infinity] | |
| 988 | ); | |
| 989 | } | |
| 990 | ||
| 991 | test "json.test.n_number_minus_sign_with_trailing_garbage" { | |
| 992 | err( | |
| 993 | \\[-foo] | |
| 994 | ); | |
| 995 | } | |
| 996 | ||
| 997 | test "json.test.n_number_minus_space_1" { | |
| 998 | err( | |
| 999 | \\[- 1] | |
| 1000 | ); | |
| 1001 | } | |
| 1002 | ||
| 1003 | test "json.test.n_number_-NaN" { | |
| 1004 | err( | |
| 1005 | \\[-NaN] | |
| 1006 | ); | |
| 1007 | } | |
| 1008 | ||
| 1009 | test "json.test.n_number_NaN" { | |
| 1010 | err( | |
| 1011 | \\[NaN] | |
| 1012 | ); | |
| 1013 | } | |
| 1014 | ||
| 1015 | test "json.test.n_number_neg_int_starting_with_zero" { | |
| 1016 | err( | |
| 1017 | \\[-012] | |
| 1018 | ); | |
| 1019 | } | |
| 1020 | ||
| 1021 | test "json.test.n_number_neg_real_without_int_part" { | |
| 1022 | err( | |
| 1023 | \\[-.123] | |
| 1024 | ); | |
| 1025 | } | |
| 1026 | ||
| 1027 | test "json.test.n_number_neg_with_garbage_at_end" { | |
| 1028 | err( | |
| 1029 | \\[-1x] | |
| 1030 | ); | |
| 1031 | } | |
| 1032 | ||
| 1033 | test "json.test.n_number_real_garbage_after_e" { | |
| 1034 | err( | |
| 1035 | \\[1ea] | |
| 1036 | ); | |
| 1037 | } | |
| 1038 | ||
| 1039 | test "json.test.n_number_real_with_invalid_utf8_after_e" { | |
| 1040 | err( | |
| 1041 | \\[1eå] | |
| 1042 | ); | |
| 1043 | } | |
| 1044 | ||
| 1045 | test "json.test.n_number_real_without_fractional_part" { | |
| 1046 | err( | |
| 1047 | \\[1.] | |
| 1048 | ); | |
| 1049 | } | |
| 1050 | ||
| 1051 | test "json.test.n_number_starting_with_dot" { | |
| 1052 | err( | |
| 1053 | \\[.123] | |
| 1054 | ); | |
| 1055 | } | |
| 1056 | ||
| 1057 | test "json.test.n_number_U+FF11_fullwidth_digit_one" { | |
| 1058 | err( | |
| 1059 | \\[ï¼] | |
| 1060 | ); | |
| 1061 | } | |
| 1062 | ||
| 1063 | test "json.test.n_number_with_alpha_char" { | |
| 1064 | err( | |
| 1065 | \\[1.8011670033376514H-308] | |
| 1066 | ); | |
| 1067 | } | |
| 1068 | ||
| 1069 | test "json.test.n_number_with_alpha" { | |
| 1070 | err( | |
| 1071 | \\[1.2a-3] | |
| 1072 | ); | |
| 1073 | } | |
| 1074 | ||
| 1075 | test "json.test.n_number_with_leading_zero" { | |
| 1076 | err( | |
| 1077 | \\[012] | |
| 1078 | ); | |
| 1079 | } | |
| 1080 | ||
| 1081 | test "json.test.n_object_bad_value" { | |
| 1082 | err( | |
| 1083 | \\["x", truth] | |
| 1084 | ); | |
| 1085 | } | |
| 1086 | ||
| 1087 | test "json.test.n_object_bracket_key" { | |
| 1088 | err( | |
| 1089 | \\{[: "x"} | |
| 1090 | ); | |
| 1091 | } | |
| 1092 | ||
| 1093 | test "json.test.n_object_comma_instead_of_colon" { | |
| 1094 | err( | |
| 1095 | \\{"x", null} | |
| 1096 | ); | |
| 1097 | } | |
| 1098 | ||
| 1099 | test "json.test.n_object_double_colon" { | |
| 1100 | err( | |
| 1101 | \\{"x"::"b"} | |
| 1102 | ); | |
| 1103 | } | |
| 1104 | ||
| 1105 | test "json.test.n_object_emoji" { | |
| 1106 | err( | |
| 1107 | \\{ð¨ð} | |
| 1108 | ); | |
| 1109 | } | |
| 1110 | ||
| 1111 | test "json.test.n_object_garbage_at_end" { | |
| 1112 | err( | |
| 1113 | \\{"a":"a" 123} | |
| 1114 | ); | |
| 1115 | } | |
| 1116 | ||
| 1117 | test "json.test.n_object_key_with_single_quotes" { | |
| 1118 | err( | |
| 1119 | \\{key: 'value'} | |
| 1120 | ); | |
| 1121 | } | |
| 1122 | ||
| 1123 | test "json.test.n_object_lone_continuation_byte_in_key_and_trailing_comma" { | |
| 1124 | err( | |
| 1125 | \\{"¹":"0",} | |
| 1126 | ); | |
| 1127 | } | |
| 1128 | ||
| 1129 | test "json.test.n_object_missing_colon" { | |
| 1130 | err( | |
| 1131 | \\{"a" b} | |
| 1132 | ); | |
| 1133 | } | |
| 1134 | ||
| 1135 | test "json.test.n_object_missing_key" { | |
| 1136 | err( | |
| 1137 | \\{:"b"} | |
| 1138 | ); | |
| 1139 | } | |
| 1140 | ||
| 1141 | test "json.test.n_object_missing_semicolon" { | |
| 1142 | err( | |
| 1143 | \\{"a" "b"} | |
| 1144 | ); | |
| 1145 | } | |
| 1146 | ||
| 1147 | test "json.test.n_object_missing_value" { | |
| 1148 | err( | |
| 1149 | \\{"a": | |
| 1150 | ); | |
| 1151 | } | |
| 1152 | ||
| 1153 | test "json.test.n_object_no-colon" { | |
| 1154 | err( | |
| 1155 | \\{"a" | |
| 1156 | ); | |
| 1157 | } | |
| 1158 | ||
| 1159 | test "json.test.n_object_non_string_key_but_huge_number_instead" { | |
| 1160 | err( | |
| 1161 | \\{9999E9999:1} | |
| 1162 | ); | |
| 1163 | } | |
| 1164 | ||
| 1165 | test "json.test.n_object_non_string_key" { | |
| 1166 | err( | |
| 1167 | \\{1:1} | |
| 1168 | ); | |
| 1169 | } | |
| 1170 | ||
| 1171 | test "json.test.n_object_repeated_null_null" { | |
| 1172 | err( | |
| 1173 | \\{null:null,null:null} | |
| 1174 | ); | |
| 1175 | } | |
| 1176 | ||
| 1177 | test "json.test.n_object_several_trailing_commas" { | |
| 1178 | err( | |
| 1179 | \\{"id":0,,,,,} | |
| 1180 | ); | |
| 1181 | } | |
| 1182 | ||
| 1183 | test "json.test.n_object_single_quote" { | |
| 1184 | err( | |
| 1185 | \\{'a':0} | |
| 1186 | ); | |
| 1187 | } | |
| 1188 | ||
| 1189 | test "json.test.n_object_trailing_comma" { | |
| 1190 | err( | |
| 1191 | \\{"id":0,} | |
| 1192 | ); | |
| 1193 | } | |
| 1194 | ||
| 1195 | test "json.test.n_object_trailing_comment" { | |
| 1196 | err( | |
| 1197 | \\{"a":"b"}/**/ | |
| 1198 | ); | |
| 1199 | } | |
| 1200 | ||
| 1201 | test "json.test.n_object_trailing_comment_open" { | |
| 1202 | err( | |
| 1203 | \\{"a":"b"}/**// | |
| 1204 | ); | |
| 1205 | } | |
| 1206 | ||
| 1207 | test "json.test.n_object_trailing_comment_slash_open_incomplete" { | |
| 1208 | err( | |
| 1209 | \\{"a":"b"}/ | |
| 1210 | ); | |
| 1211 | } | |
| 1212 | ||
| 1213 | test "json.test.n_object_trailing_comment_slash_open" { | |
| 1214 | err( | |
| 1215 | \\{"a":"b"}// | |
| 1216 | ); | |
| 1217 | } | |
| 1218 | ||
| 1219 | test "json.test.n_object_two_commas_in_a_row" { | |
| 1220 | err( | |
| 1221 | \\{"a":"b",,"c":"d"} | |
| 1222 | ); | |
| 1223 | } | |
| 1224 | ||
| 1225 | test "json.test.n_object_unquoted_key" { | |
| 1226 | err( | |
| 1227 | \\{a: "b"} | |
| 1228 | ); | |
| 1229 | } | |
| 1230 | ||
| 1231 | test "json.test.n_object_unterminated-value" { | |
| 1232 | err( | |
| 1233 | \\{"a":"a | |
| 1234 | ); | |
| 1235 | } | |
| 1236 | ||
| 1237 | test "json.test.n_object_with_single_string" { | |
| 1238 | err( | |
| 1239 | \\{ "foo" : "bar", "a" } | |
| 1240 | ); | |
| 1241 | } | |
| 1242 | ||
| 1243 | test "json.test.n_object_with_trailing_garbage" { | |
| 1244 | err( | |
| 1245 | \\{"a":"b"}# | |
| 1246 | ); | |
| 1247 | } | |
| 1248 | ||
| 1249 | test "json.test.n_single_space" { | |
| 1250 | err(" "); | |
| 1251 | } | |
| 1252 | ||
| 1253 | test "json.test.n_string_1_surrogate_then_escape" { | |
| 1254 | err( | |
| 1255 | \\["\uD800\"] | |
| 1256 | ); | |
| 1257 | } | |
| 1258 | ||
| 1259 | test "json.test.n_string_1_surrogate_then_escape_u1" { | |
| 1260 | err( | |
| 1261 | \\["\uD800\u1"] | |
| 1262 | ); | |
| 1263 | } | |
| 1264 | ||
| 1265 | test "json.test.n_string_1_surrogate_then_escape_u1x" { | |
| 1266 | err( | |
| 1267 | \\["\uD800\u1x"] | |
| 1268 | ); | |
| 1269 | } | |
| 1270 | ||
| 1271 | test "json.test.n_string_1_surrogate_then_escape_u" { | |
| 1272 | err( | |
| 1273 | \\["\uD800\u"] | |
| 1274 | ); | |
| 1275 | } | |
| 1276 | ||
| 1277 | test "json.test.n_string_accentuated_char_no_quotes" { | |
| 1278 | err( | |
| 1279 | \\[é] | |
| 1280 | ); | |
| 1281 | } | |
| 1282 | ||
| 1283 | test "json.test.n_string_backslash_00" { | |
| 1284 | err("[\"\x00\"]"); | |
| 1285 | } | |
| 1286 | ||
| 1287 | test "json.test.n_string_escaped_backslash_bad" { | |
| 1288 | err( | |
| 1289 | \\["\\\"] | |
| 1290 | ); | |
| 1291 | } | |
| 1292 | ||
| 1293 | test "json.test.n_string_escaped_ctrl_char_tab" { | |
| 1294 | err("\x5b\x22\x5c\x09\x22\x5d"); | |
| 1295 | } | |
| 1296 | ||
| 1297 | test "json.test.n_string_escaped_emoji" { | |
| 1298 | err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]"); | |
| 1299 | } | |
| 1300 | ||
| 1301 | test "json.test.n_string_escape_x" { | |
| 1302 | err( | |
| 1303 | \\["\x00"] | |
| 1304 | ); | |
| 1305 | } | |
| 1306 | ||
| 1307 | test "json.test.n_string_incomplete_escaped_character" { | |
| 1308 | err( | |
| 1309 | \\["\u00A"] | |
| 1310 | ); | |
| 1311 | } | |
| 1312 | ||
| 1313 | test "json.test.n_string_incomplete_escape" { | |
| 1314 | err( | |
| 1315 | \\["\"] | |
| 1316 | ); | |
| 1317 | } | |
| 1318 | ||
| 1319 | test "json.test.n_string_incomplete_surrogate_escape_invalid" { | |
| 1320 | err( | |
| 1321 | \\["\uD800\uD800\x"] | |
| 1322 | ); | |
| 1323 | } | |
| 1324 | ||
| 1325 | test "json.test.n_string_incomplete_surrogate" { | |
| 1326 | err( | |
| 1327 | \\["\uD834\uDd"] | |
| 1328 | ); | |
| 1329 | } | |
| 1330 | ||
| 1331 | test "json.test.n_string_invalid_backslash_esc" { | |
| 1332 | err( | |
| 1333 | \\["\a"] | |
| 1334 | ); | |
| 1335 | } | |
| 1336 | ||
| 1337 | test "json.test.n_string_invalid_unicode_escape" { | |
| 1338 | err( | |
| 1339 | \\["\uqqqq"] | |
| 1340 | ); | |
| 1341 | } | |
| 1342 | ||
| 1343 | test "json.test.n_string_invalid_utf8_after_escape" { | |
| 1344 | err("[\"\\\x75\xc3\xa5\"]"); | |
| 1345 | } | |
| 1346 | ||
| 1347 | test "json.test.n_string_invalid-utf-8-in-escape" { | |
| 1348 | err( | |
| 1349 | \\["\uå"] | |
| 1350 | ); | |
| 1351 | } | |
| 1352 | ||
| 1353 | test "json.test.n_string_leading_uescaped_thinspace" { | |
| 1354 | err( | |
| 1355 | \\[\u0020"asd"] | |
| 1356 | ); | |
| 1357 | } | |
| 1358 | ||
| 1359 | test "json.test.n_string_no_quotes_with_bad_escape" { | |
| 1360 | err( | |
| 1361 | \\[\n] | |
| 1362 | ); | |
| 1363 | } | |
| 1364 | ||
| 1365 | test "json.test.n_string_single_doublequote" { | |
| 1366 | err( | |
| 1367 | \\" | |
| 1368 | ); | |
| 1369 | } | |
| 1370 | ||
| 1371 | test "json.test.n_string_single_quote" { | |
| 1372 | err( | |
| 1373 | \\['single quote'] | |
| 1374 | ); | |
| 1375 | } | |
| 1376 | ||
| 1377 | test "json.test.n_string_single_string_no_double_quotes" { | |
| 1378 | err( | |
| 1379 | \\abc | |
| 1380 | ); | |
| 1381 | } | |
| 1382 | ||
| 1383 | test "json.test.n_string_start_escape_unclosed" { | |
| 1384 | err( | |
| 1385 | \\["\ | |
| 1386 | ); | |
| 1387 | } | |
| 1388 | ||
| 1389 | test "json.test.n_string_unescaped_crtl_char" { | |
| 1390 | err("[\"a\x00a\"]"); | |
| 1391 | } | |
| 1392 | ||
| 1393 | test "json.test.n_string_unescaped_newline" { | |
| 1394 | err( | |
| 1395 | \\["new | |
| 1396 | \\line"] | |
| 1397 | ); | |
| 1398 | } | |
| 1399 | ||
| 1400 | test "json.test.n_string_unescaped_tab" { | |
| 1401 | err("[\"\t\"]"); | |
| 1402 | } | |
| 1403 | ||
| 1404 | test "json.test.n_string_unicode_CapitalU" { | |
| 1405 | err( | |
| 1406 | \\"\UA66D" | |
| 1407 | ); | |
| 1408 | } | |
| 1409 | ||
| 1410 | test "json.test.n_string_with_trailing_garbage" { | |
| 1411 | err( | |
| 1412 | \\""x | |
| 1413 | ); | |
| 1414 | } | |
| 1415 | ||
| 1416 | test "json.test.n_structure_100000_opening_arrays" { | |
| 1417 | err("[" ** 100000); | |
| 1418 | } | |
| 1419 | ||
| 1420 | test "json.test.n_structure_angle_bracket_." { | |
| 1421 | err( | |
| 1422 | \\<.> | |
| 1423 | ); | |
| 1424 | } | |
| 1425 | ||
| 1426 | test "json.test.n_structure_angle_bracket_null" { | |
| 1427 | err( | |
| 1428 | \\[<null>] | |
| 1429 | ); | |
| 1430 | } | |
| 1431 | ||
| 1432 | test "json.test.n_structure_array_trailing_garbage" { | |
| 1433 | err( | |
| 1434 | \\[1]x | |
| 1435 | ); | |
| 1436 | } | |
| 1437 | ||
| 1438 | test "json.test.n_structure_array_with_extra_array_close" { | |
| 1439 | err( | |
| 1440 | \\[1]] | |
| 1441 | ); | |
| 1442 | } | |
| 1443 | ||
| 1444 | test "json.test.n_structure_array_with_unclosed_string" { | |
| 1445 | err( | |
| 1446 | \\["asd] | |
| 1447 | ); | |
| 1448 | } | |
| 1449 | ||
| 1450 | test "json.test.n_structure_ascii-unicode-identifier" { | |
| 1451 | err( | |
| 1452 | \\aå | |
| 1453 | ); | |
| 1454 | } | |
| 1455 | ||
| 1456 | test "json.test.n_structure_capitalized_True" { | |
| 1457 | err( | |
| 1458 | \\[True] | |
| 1459 | ); | |
| 1460 | } | |
| 1461 | ||
| 1462 | test "json.test.n_structure_close_unopened_array" { | |
| 1463 | err( | |
| 1464 | \\1] | |
| 1465 | ); | |
| 1466 | } | |
| 1467 | ||
| 1468 | test "json.test.n_structure_comma_instead_of_closing_brace" { | |
| 1469 | err( | |
| 1470 | \\{"x": true, | |
| 1471 | ); | |
| 1472 | } | |
| 1473 | ||
| 1474 | test "json.test.n_structure_double_array" { | |
| 1475 | err( | |
| 1476 | \\[][] | |
| 1477 | ); | |
| 1478 | } | |
| 1479 | ||
| 1480 | test "json.test.n_structure_end_array" { | |
| 1481 | err( | |
| 1482 | \\] | |
| 1483 | ); | |
| 1484 | } | |
| 1485 | ||
| 1486 | test "json.test.n_structure_incomplete_UTF8_BOM" { | |
| 1487 | err( | |
| 1488 | \\ï»{} | |
| 1489 | ); | |
| 1490 | } | |
| 1491 | ||
| 1492 | test "json.test.n_structure_lone-invalid-utf-8" { | |
| 1493 | err( | |
| 1494 | \\å | |
| 1495 | ); | |
| 1496 | } | |
| 1497 | ||
| 1498 | test "json.test.n_structure_lone-open-bracket" { | |
| 1499 | err( | |
| 1500 | \\[ | |
| 1501 | ); | |
| 1502 | } | |
| 1503 | ||
| 1504 | test "json.test.n_structure_no_data" { | |
| 1505 | err( | |
| 1506 | \\ | |
| 1507 | ); | |
| 1508 | } | |
| 1509 | ||
| 1510 | test "json.test.n_structure_null-byte-outside-string" { | |
| 1511 | err("[\x00]"); | |
| 1512 | } | |
| 1513 | ||
| 1514 | test "json.test.n_structure_number_with_trailing_garbage" { | |
| 1515 | err( | |
| 1516 | \\2@ | |
| 1517 | ); | |
| 1518 | } | |
| 1519 | ||
| 1520 | test "json.test.n_structure_object_followed_by_closing_object" { | |
| 1521 | err( | |
| 1522 | \\{}} | |
| 1523 | ); | |
| 1524 | } | |
| 1525 | ||
| 1526 | test "json.test.n_structure_object_unclosed_no_value" { | |
| 1527 | err( | |
| 1528 | \\{"": | |
| 1529 | ); | |
| 1530 | } | |
| 1531 | ||
| 1532 | test "json.test.n_structure_object_with_comment" { | |
| 1533 | err( | |
| 1534 | \\{"a":/*comment*/"b"} | |
| 1535 | ); | |
| 1536 | } | |
| 1537 | ||
| 1538 | test "json.test.n_structure_object_with_trailing_garbage" { | |
| 1539 | err( | |
| 1540 | \\{"a": true} "x" | |
| 1541 | ); | |
| 1542 | } | |
| 1543 | ||
| 1544 | test "json.test.n_structure_open_array_apostrophe" { | |
| 1545 | err( | |
| 1546 | \\[' | |
| 1547 | ); | |
| 1548 | } | |
| 1549 | ||
| 1550 | test "json.test.n_structure_open_array_comma" { | |
| 1551 | err( | |
| 1552 | \\[, | |
| 1553 | ); | |
| 1554 | } | |
| 1555 | ||
| 1556 | test "json.test.n_structure_open_array_object" { | |
| 1557 | err("[{\"\":" ** 50000); | |
| 1558 | } | |
| 1559 | ||
| 1560 | test "json.test.n_structure_open_array_open_object" { | |
| 1561 | err( | |
| 1562 | \\[{ | |
| 1563 | ); | |
| 1564 | } | |
| 1565 | ||
| 1566 | test "json.test.n_structure_open_array_open_string" { | |
| 1567 | err( | |
| 1568 | \\["a | |
| 1569 | ); | |
| 1570 | } | |
| 1571 | ||
| 1572 | test "json.test.n_structure_open_array_string" { | |
| 1573 | err( | |
| 1574 | \\["a" | |
| 1575 | ); | |
| 1576 | } | |
| 1577 | ||
| 1578 | test "json.test.n_structure_open_object_close_array" { | |
| 1579 | err( | |
| 1580 | \\{] | |
| 1581 | ); | |
| 1582 | } | |
| 1583 | ||
| 1584 | test "json.test.n_structure_open_object_comma" { | |
| 1585 | err( | |
| 1586 | \\{, | |
| 1587 | ); | |
| 1588 | } | |
| 1589 | ||
| 1590 | test "json.test.n_structure_open_object" { | |
| 1591 | err( | |
| 1592 | \\{ | |
| 1593 | ); | |
| 1594 | } | |
| 1595 | ||
| 1596 | test "json.test.n_structure_open_object_open_array" { | |
| 1597 | err( | |
| 1598 | \\{[ | |
| 1599 | ); | |
| 1600 | } | |
| 1601 | ||
| 1602 | test "json.test.n_structure_open_object_open_string" { | |
| 1603 | err( | |
| 1604 | \\{"a | |
| 1605 | ); | |
| 1606 | } | |
| 1607 | ||
| 1608 | test "json.test.n_structure_open_object_string_with_apostrophes" { | |
| 1609 | err( | |
| 1610 | \\{'a' | |
| 1611 | ); | |
| 1612 | } | |
| 1613 | ||
| 1614 | test "json.test.n_structure_open_open" { | |
| 1615 | err( | |
| 1616 | \\["\{["\{["\{["\{ | |
| 1617 | ); | |
| 1618 | } | |
| 1619 | ||
| 1620 | test "json.test.n_structure_single_eacute" { | |
| 1621 | err( | |
| 1622 | \\é | |
| 1623 | ); | |
| 1624 | } | |
| 1625 | ||
| 1626 | test "json.test.n_structure_single_star" { | |
| 1627 | err( | |
| 1628 | \\* | |
| 1629 | ); | |
| 1630 | } | |
| 1631 | ||
| 1632 | test "json.test.n_structure_trailing_#" { | |
| 1633 | err( | |
| 1634 | \\{"a":"b"}#{} | |
| 1635 | ); | |
| 1636 | } | |
| 1637 | ||
| 1638 | test "json.test.n_structure_U+2060_word_joined" { | |
| 1639 | err( | |
| 1640 | \\[â ] | |
| 1641 | ); | |
| 1642 | } | |
| 1643 | ||
| 1644 | test "json.test.n_structure_uescaped_LF_before_string" { | |
| 1645 | err( | |
| 1646 | \\[\u000A""] | |
| 1647 | ); | |
| 1648 | } | |
| 1649 | ||
| 1650 | test "json.test.n_structure_unclosed_array" { | |
| 1651 | err( | |
| 1652 | \\[1 | |
| 1653 | ); | |
| 1654 | } | |
| 1655 | ||
| 1656 | test "json.test.n_structure_unclosed_array_partial_null" { | |
| 1657 | err( | |
| 1658 | \\[ false, nul | |
| 1659 | ); | |
| 1660 | } | |
| 1661 | ||
| 1662 | test "json.test.n_structure_unclosed_array_unfinished_false" { | |
| 1663 | err( | |
| 1664 | \\[ true, fals | |
| 1665 | ); | |
| 1666 | } | |
| 1667 | ||
| 1668 | test "json.test.n_structure_unclosed_array_unfinished_true" { | |
| 1669 | err( | |
| 1670 | \\[ false, tru | |
| 1671 | ); | |
| 1672 | } | |
| 1673 | ||
| 1674 | test "json.test.n_structure_unclosed_object" { | |
| 1675 | err( | |
| 1676 | \\{"asd":"asd" | |
| 1677 | ); | |
| 1678 | } | |
| 1679 | ||
| 1680 | test "json.test.n_structure_unicode-identifier" { | |
| 1681 | err( | |
| 1682 | \\Ã¥ | |
| 1683 | ); | |
| 1684 | } | |
| 1685 | ||
| 1686 | test "json.test.n_structure_UTF8_BOM_no_data" { | |
| 1687 | err( | |
| 1688 | \\ | |
| 1689 | ); | |
| 1690 | } | |
| 1691 | ||
| 1692 | test "json.test.n_structure_whitespace_formfeed" { | |
| 1693 | err("[\x0c]"); | |
| 1694 | } | |
| 1695 | ||
| 1696 | test "json.test.n_structure_whitespace_U+2060_word_joiner" { | |
| 1697 | err( | |
| 1698 | \\[â ] | |
| 1699 | ); | |
| 1700 | } | |
| 1701 | ||
| 1702 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 1703 | ||
| 1704 | test "json.test.i_number_double_huge_neg_exp" { | |
| 1705 | any( | |
| 1706 | \\[123.456e-789] | |
| 1707 | ); | |
| 1708 | } | |
| 1709 | ||
| 1710 | test "json.test.i_number_huge_exp" { | |
| 1711 | any( | |
| 1712 | \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006] | |
| 1713 | ); | |
| 1714 | } | |
| 1715 | ||
| 1716 | test "json.test.i_number_neg_int_huge_exp" { | |
| 1717 | any( | |
| 1718 | \\[-1e+9999] | |
| 1719 | ); | |
| 1720 | } | |
| 1721 | ||
| 1722 | test "json.test.i_number_pos_double_huge_exp" { | |
| 1723 | any( | |
| 1724 | \\[1.5e+9999] | |
| 1725 | ); | |
| 1726 | } | |
| 1727 | ||
| 1728 | test "json.test.i_number_real_neg_overflow" { | |
| 1729 | any( | |
| 1730 | \\[-123123e100000] | |
| 1731 | ); | |
| 1732 | } | |
| 1733 | ||
| 1734 | test "json.test.i_number_real_pos_overflow" { | |
| 1735 | any( | |
| 1736 | \\[123123e100000] | |
| 1737 | ); | |
| 1738 | } | |
| 1739 | ||
| 1740 | test "json.test.i_number_real_underflow" { | |
| 1741 | any( | |
| 1742 | \\[123e-10000000] | |
| 1743 | ); | |
| 1744 | } | |
| 1745 | ||
| 1746 | test "json.test.i_number_too_big_neg_int" { | |
| 1747 | any( | |
| 1748 | \\[-123123123123123123123123123123] | |
| 1749 | ); | |
| 1750 | } | |
| 1751 | ||
| 1752 | test "json.test.i_number_too_big_pos_int" { | |
| 1753 | any( | |
| 1754 | \\[100000000000000000000] | |
| 1755 | ); | |
| 1756 | } | |
| 1757 | ||
| 1758 | test "json.test.i_number_very_big_negative_int" { | |
| 1759 | any( | |
| 1760 | \\[-237462374673276894279832749832423479823246327846] | |
| 1761 | ); | |
| 1762 | } | |
| 1763 | ||
| 1764 | test "json.test.i_object_key_lone_2nd_surrogate" { | |
| 1765 | any( | |
| 1766 | \\{"\uDFAA":0} | |
| 1767 | ); | |
| 1768 | } | |
| 1769 | ||
| 1770 | test "json.test.i_string_1st_surrogate_but_2nd_missing" { | |
| 1771 | any( | |
| 1772 | \\["\uDADA"] | |
| 1773 | ); | |
| 1774 | } | |
| 1775 | ||
| 1776 | test "json.test.i_string_1st_valid_surrogate_2nd_invalid" { | |
| 1777 | any( | |
| 1778 | \\["\uD888\u1234"] | |
| 1779 | ); | |
| 1780 | } | |
| 1781 | ||
| 1782 | test "json.test.i_string_incomplete_surrogate_and_escape_valid" { | |
| 1783 | any( | |
| 1784 | \\["\uD800\n"] | |
| 1785 | ); | |
| 1786 | } | |
| 1787 | ||
| 1788 | test "json.test.i_string_incomplete_surrogate_pair" { | |
| 1789 | any( | |
| 1790 | \\["\uDd1ea"] | |
| 1791 | ); | |
| 1792 | } | |
| 1793 | ||
| 1794 | test "json.test.i_string_incomplete_surrogates_escape_valid" { | |
| 1795 | any( | |
| 1796 | \\["\uD800\uD800\n"] | |
| 1797 | ); | |
| 1798 | } | |
| 1799 | ||
| 1800 | test "json.test.i_string_invalid_lonely_surrogate" { | |
| 1801 | any( | |
| 1802 | \\["\ud800"] | |
| 1803 | ); | |
| 1804 | } | |
| 1805 | ||
| 1806 | test "json.test.i_string_invalid_surrogate" { | |
| 1807 | any( | |
| 1808 | \\["\ud800abc"] | |
| 1809 | ); | |
| 1810 | } | |
| 1811 | ||
| 1812 | test "json.test.i_string_invalid_utf-8" { | |
| 1813 | any( | |
| 1814 | \\["ÿ"] | |
| 1815 | ); | |
| 1816 | } | |
| 1817 | ||
| 1818 | test "json.test.i_string_inverted_surrogates_U+1D11E" { | |
| 1819 | any( | |
| 1820 | \\["\uDd1e\uD834"] | |
| 1821 | ); | |
| 1822 | } | |
| 1823 | ||
| 1824 | test "json.test.i_string_iso_latin_1" { | |
| 1825 | any( | |
| 1826 | \\["é"] | |
| 1827 | ); | |
| 1828 | } | |
| 1829 | ||
| 1830 | test "json.test.i_string_lone_second_surrogate" { | |
| 1831 | any( | |
| 1832 | \\["\uDFAA"] | |
| 1833 | ); | |
| 1834 | } | |
| 1835 | ||
| 1836 | test "json.test.i_string_lone_utf8_continuation_byte" { | |
| 1837 | any( | |
| 1838 | \\[""] | |
| 1839 | ); | |
| 1840 | } | |
| 1841 | ||
| 1842 | test "json.test.i_string_not_in_unicode_range" { | |
| 1843 | any( | |
| 1844 | \\["ô¿¿¿"] | |
| 1845 | ); | |
| 1846 | } | |
| 1847 | ||
| 1848 | test "json.test.i_string_overlong_sequence_2_bytes" { | |
| 1849 | any( | |
| 1850 | \\["À¯"] | |
| 1851 | ); | |
| 1852 | } | |
| 1853 | ||
| 1854 | test "json.test.i_string_overlong_sequence_6_bytes" { | |
| 1855 | any( | |
| 1856 | \\["ü¿¿¿¿"] | |
| 1857 | ); | |
| 1858 | } | |
| 1859 | ||
| 1860 | test "json.test.i_string_overlong_sequence_6_bytes_null" { | |
| 1861 | any( | |
| 1862 | \\["ü"] | |
| 1863 | ); | |
| 1864 | } | |
| 1865 | ||
| 1866 | test "json.test.i_string_truncated-utf-8" { | |
| 1867 | any( | |
| 1868 | \\["àÿ"] | |
| 1869 | ); | |
| 1870 | } | |
| 1871 | ||
| 1872 | test "json.test.i_string_utf16BE_no_BOM" { | |
| 1873 | any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d"); | |
| 1874 | } | |
| 1875 | ||
| 1876 | test "json.test.i_string_utf16LE_no_BOM" { | |
| 1877 | any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00"); | |
| 1878 | } | |
| 1879 | ||
| 1880 | test "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 | ||
| 1884 | test "json.test.i_string_UTF-8_invalid_sequence" { | |
| 1885 | any( | |
| 1886 | \\["æ¥Ñú"] | |
| 1887 | ); | |
| 1888 | } | |
| 1889 | ||
| 1890 | test "json.test.i_string_UTF8_surrogate_U+D800" { | |
| 1891 | any( | |
| 1892 | \\["í "] | |
| 1893 | ); | |
| 1894 | } | |
| 1895 | ||
| 1896 | test "json.test.i_structure_500_nested_arrays" { | |
| 1897 | any(("[" ** 500) ++ ("]" ** 500)); | |
| 1898 | } | |
| 1899 | ||
| 1900 | test "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 | // 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 > 1 | |
| 4 | // 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 | |
| 4 | 6 | |
| 5 | 7 | const std = @import("../std.zig"); |
| 6 | 8 | const math = std.math; |
| 7 | 9 | const expect = std.testing.expect; |
| 8 | 10 | |
| 11 | /// Returns the arc-cosine of x. | |
| 12 | /// | |
| 13 | /// Special cases: | |
| 14 | /// - acos(x) = nan if x < -1 or x > 1 | |
| 9 | 15 | pub fn acos(x: var) @typeOf(x) { |
| 10 | 16 | const T = @typeOf(x); |
| 11 | 17 | return switch (T) { |
std/math/acosh.zig+9-3| ... | ... | @@ -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 < 1 | |
| 4 | // - acosh(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/acoshf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/acosh.c | |
| 5 | 6 | |
| 6 | 7 | const builtin = @import("builtin"); |
| 7 | 8 | const std = @import("../std.zig"); |
| 8 | 9 | const math = std.math; |
| 9 | 10 | const expect = std.testing.expect; |
| 10 | 11 | |
| 12 | /// Returns the hyperbolic arc-cosine of x. | |
| 13 | /// | |
| 14 | /// Special cases: | |
| 15 | /// - acosh(x) = snan if x < 1 | |
| 16 | /// - acosh(nan) = nan | |
| 11 | 17 | pub fn acosh(x: var) @typeOf(x) { |
| 12 | 18 | const T = @typeOf(x); |
| 13 | 19 | return switch (T) { |
std/math/asin.zig+9-3| ... | ... | @@ -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) = +-0 | |
| 4 | // - asin(x) = nan if x < -1 or x > 1 | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/asinf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/asin.c | |
| 5 | 6 | |
| 6 | 7 | const std = @import("../std.zig"); |
| 7 | 8 | const math = std.math; |
| 8 | 9 | const expect = std.testing.expect; |
| 9 | 10 | |
| 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 | |
| 10 | 16 | pub fn asin(x: var) @typeOf(x) { |
| 11 | 17 | const T = @typeOf(x); |
| 12 | 18 | return switch (T) { |
std/math/asinh.zig+10-4| ... | ... | @@ -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) = +-0 | |
| 4 | // - asinh(+-inf) = +-inf | |
| 5 | // - asinh(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/asinhf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/asinh.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("../std.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const expect = std.testing.expect; |
| 10 | 10 | const maxInt = std.math.maxInt; |
| 11 | 11 | |
| 12 | /// Returns the hyperbolic arc-sin of x. | |
| 13 | /// | |
| 14 | /// Special Cases: | |
| 15 | /// - asinh(+-0) = +-0 | |
| 16 | /// - asinh(+-inf) = +-inf | |
| 17 | /// - asinh(nan) = nan | |
| 12 | 18 | pub fn asinh(x: var) @typeOf(x) { |
| 13 | 19 | const T = @typeOf(x); |
| 14 | 20 | return switch (T) { |
std/math/atan.zig+9-3| ... | ... | @@ -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) = +-0 | |
| 4 | // - atan(+-inf) = +-pi/2 | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/atanf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/atan.c | |
| 5 | 6 | |
| 6 | 7 | const std = @import("../std.zig"); |
| 7 | 8 | const math = std.math; |
| 8 | 9 | const expect = std.testing.expect; |
| 9 | 10 | |
| 11 | /// Returns the arc-tangent of x. | |
| 12 | /// | |
| 13 | /// Special Cases: | |
| 14 | /// - atan(+-0) = +-0 | |
| 15 | /// - atan(+-inf) = +-pi/2 | |
| 10 | 16 | pub fn atan(x: var) @typeOf(x) { |
| 11 | 17 | const T = @typeOf(x); |
| 12 | 18 | return switch (T) { |
std/math/atan2.zig+24-18| ... | ... | @@ -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) = nan | |
| 4 | // atan2(nan, x) = nan | |
| 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 | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/atan2f.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/atan2.c | |
| 20 | 6 | |
| 21 | 7 | const std = @import("../std.zig"); |
| 22 | 8 | const math = std.math; |
| 23 | 9 | const expect = std.testing.expect; |
| 24 | 10 | |
| 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 | |
| 25 | 31 | pub fn atan2(comptime T: type, y: T, x: T) T { |
| 26 | 32 | return switch (T) { |
| 27 | 33 | f32 => atan2_32(y, x), |
std/math/atanh.zig+10-4| ... | ... | @@ -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 signal | |
| 4 | // - atanh(x) = nan if |x| > 1 with signal | |
| 5 | // - atanh(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/atanhf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/atanh.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("../std.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const expect = std.testing.expect; |
| 10 | 10 | const maxInt = std.math.maxInt; |
| 11 | 11 | |
| 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 | |
| 12 | 18 | pub fn atanh(x: var) @typeOf(x) { |
| 13 | 19 | const T = @typeOf(x); |
| 14 | 20 | return switch (T) { |
std/math/big.zig+2| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 1 | pub use @import("big/int.zig"); |
| 2 | pub use @import("big/rational.zig"); | |
| 2 | 3 | |
| 3 | 4 | test "math.big" { |
| 4 | 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 | 21 | debug.assert(Limb.is_signed == false); |
| 22 | 22 | } |
| 23 | 23 | |
| 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. | |
| 24 | 28 | pub const Int = struct { |
| 25 | allocator: *Allocator, | |
| 26 | positive: bool, | |
| 27 | // - little-endian ordered | |
| 28 | // - len >= 1 always | |
| 29 | // - zero value -> len == 1 with limbs[0] == 0 | |
| 29 | const sign_bit: usize = 1 << (usize.bit_count - 1); | |
| 30 | ||
| 31 | /// Default number of limbs to allocate on creation of an Int. | |
| 32 | pub const default_capacity = 4; | |
| 33 | ||
| 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 | 44 | limbs: []Limb, |
| 31 | len: usize, | |
| 32 | 45 | |
| 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, | |
| 34 | 49 | |
| 50 | /// Creates a new Int. default_capacity limbs will be allocated immediately. | |
| 51 | /// Int will be zeroed. | |
| 35 | 52 | pub fn init(allocator: *Allocator) !Int { |
| 36 | 53 | return try Int.initCapacity(allocator, default_capacity); |
| 37 | 54 | } |
| 38 | 55 | |
| 56 | /// Creates a new Int. Int will be set to `value`. | |
| 57 | /// | |
| 58 | /// This is identical to an `init`, followed by a `set`. | |
| 39 | 59 | pub fn initSet(allocator: *Allocator, value: var) !Int { |
| 40 | 60 | var s = try Int.init(allocator); |
| 41 | 61 | try s.set(value); |
| 42 | 62 | return s; |
| 43 | 63 | } |
| 44 | 64 | |
| 65 | /// Creates a new Int with a specific capacity. If capacity < default_capacity then the | |
| 66 | /// default capacity will be used instead. | |
| 45 | 67 | pub fn initCapacity(allocator: *Allocator, capacity: usize) !Int { |
| 46 | 68 | return Int{ |
| 47 | 69 | .allocator = allocator, |
| 48 | .positive = true, | |
| 70 | .metadata = 1, | |
| 49 | 71 | .limbs = block: { |
| 50 | 72 | var limbs = try allocator.alloc(Limb, math.max(default_capacity, capacity)); |
| 51 | 73 | limbs[0] = 0; |
| 52 | 74 | break :block limbs; |
| 53 | 75 | }, |
| 54 | .len = 1, | |
| 55 | 76 | }; |
| 56 | 77 | } |
| 57 | 78 | |
| 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 | 124 | pub fn ensureCapacity(self: *Int, capacity: usize) !void { |
| 125 | self.assertWritable(); | |
| 59 | 126 | if (capacity <= self.limbs.len) { |
| 60 | 127 | return; |
| 61 | 128 | } |
| 62 | 129 | |
| 63 | self.limbs = try self.allocator.realloc(self.limbs, capacity); | |
| 130 | self.limbs = try self.allocator.?.realloc(self.limbs, capacity); | |
| 64 | 131 | } |
| 65 | 132 | |
| 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 | 140 | pub fn deinit(self: *Int) void { |
| 67 | self.allocator.free(self.limbs); | |
| 141 | self.assertWritable(); | |
| 142 | self.allocator.?.free(self.limbs); | |
| 68 | 143 | self.* = undefined; |
| 69 | 144 | } |
| 70 | 145 | |
| 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 | 148 | pub fn clone(other: Int) !Int { |
| 149 | other.assertWritable(); | |
| 72 | 150 | return Int{ |
| 73 | 151 | .allocator = other.allocator, |
| 74 | .positive = other.positive, | |
| 152 | .metadata = other.metadata, | |
| 75 | 153 | .limbs = block: { |
| 76 | var limbs = try other.allocator.alloc(Limb, other.len); | |
| 77 | mem.copy(Limb, limbs[0..], other.limbs[0..other.len]); | |
| 154 | var limbs = try other.allocator.?.alloc(Limb, other.len()); | |
| 155 | mem.copy(Limb, limbs[0..], other.limbs[0..other.len()]); | |
| 78 | 156 | break :block limbs; |
| 79 | 157 | }, |
| 80 | .len = other.len, | |
| 81 | 158 | }; |
| 82 | 159 | } |
| 83 | 160 | |
| 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 | 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 | 166 | return; |
| 87 | 167 | } |
| 88 | 168 | |
| 89 | self.positive = other.positive; | |
| 90 | try self.ensureCapacity(other.len); | |
| 91 | mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len]); | |
| 92 | self.len = other.len; | |
| 169 | try self.ensureCapacity(other.len()); | |
| 170 | mem.copy(Limb, self.limbs[0..], other.limbs[0..other.len()]); | |
| 171 | self.metadata = other.metadata; | |
| 93 | 172 | } |
| 94 | 173 | |
| 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 | 176 | pub fn swap(self: *Int, other: *Int) void { |
| 177 | self.assertWritable(); | |
| 96 | 178 | mem.swap(Int, self, other); |
| 97 | 179 | } |
| 98 | 180 | |
| ... | ... | @@ -103,45 +185,49 @@ pub const Int = struct { |
| 103 | 185 | debug.warn("\n"); |
| 104 | 186 | } |
| 105 | 187 | |
| 106 | pub fn negate(r: *Int) void { | |
| 107 | r.positive = !r.positive; | |
| 188 | /// Negate the sign of an Int. | |
| 189 | pub fn negate(self: *Int) void { | |
| 190 | self.metadata ^= sign_bit; | |
| 108 | 191 | } |
| 109 | 192 | |
| 110 | pub fn abs(r: *Int) void { | |
| 111 | r.positive = true; | |
| 193 | /// Make an Int positive. | |
| 194 | pub fn abs(self: *Int) void { | |
| 195 | self.metadata &= ~sign_bit; | |
| 112 | 196 | } |
| 113 | 197 | |
| 114 | pub fn isOdd(r: Int) bool { | |
| 115 | return r.limbs[0] & 1 != 0; | |
| 198 | /// Returns true if an Int is odd. | |
| 199 | pub fn isOdd(self: Int) bool { | |
| 200 | return self.limbs[0] & 1 != 0; | |
| 116 | 201 | } |
| 117 | 202 | |
| 118 | pub fn isEven(r: Int) bool { | |
| 119 | return !r.isOdd(); | |
| 203 | /// Returns true if an Int is even. | |
| 204 | pub fn isEven(self: Int) bool { | |
| 205 | return !self.isOdd(); | |
| 120 | 206 | } |
| 121 | 207 | |
| 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 | 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 | } |
| 126 | 212 | |
| 127 | // Returns the number of bits required to represent the integer in twos-complement form. | |
| 128 | // | |
| 129 | // 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 an | |
| 131 | // unsigned integer. Any unsigned integer will fit in the signed integer with bitcount | |
| 132 | // one greater than the returned value. | |
| 133 | // | |
| 134 | // e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7. | |
| 213 | /// Returns the number of bits required to represent the integer in twos-complement form. | |
| 214 | /// | |
| 215 | /// If the integer is negative the value returned is the number of bits needed by a signed | |
| 216 | /// integer to represent the value. If positive the value is the number of bits for an | |
| 217 | /// unsigned integer. Any unsigned integer will fit in the signed integer with bitcount | |
| 218 | /// one greater than the returned value. | |
| 219 | /// | |
| 220 | /// e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7. | |
| 135 | 221 | fn bitCountTwosComp(self: Int) usize { |
| 136 | 222 | var bits = self.bitCountAbs(); |
| 137 | 223 | |
| 138 | 224 | // If the entire value has only one bit set (e.g. 0b100000000) then the negation in twos |
| 139 | 225 | // complement requires one less bit. |
| 140 | if (!self.positive) block: { | |
| 226 | if (!self.isPositive()) block: { | |
| 141 | 227 | bits += 1; |
| 142 | 228 | |
| 143 | if (@popCount(self.limbs[self.len - 1]) == 1) { | |
| 144 | for (self.limbs[0 .. self.len - 1]) |limb| { | |
| 229 | if (@popCount(self.limbs[self.len() - 1]) == 1) { | |
| 230 | for (self.limbs[0 .. self.len() - 1]) |limb| { | |
| 145 | 231 | if (@popCount(limb) != 0) { |
| 146 | 232 | break :block; |
| 147 | 233 | } |
| ... | ... | @@ -154,31 +240,34 @@ pub const Int = struct { |
| 154 | 240 | return bits; |
| 155 | 241 | } |
| 156 | 242 | |
| 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 | 244 | if (self.eqZero()) { |
| 159 | 245 | return true; |
| 160 | 246 | } |
| 161 | if (!is_signed and !self.positive) { | |
| 247 | if (!is_signed and !self.isPositive()) { | |
| 162 | 248 | return false; |
| 163 | 249 | } |
| 164 | 250 | |
| 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 | 252 | return bit_count >= req_bits; |
| 167 | 253 | } |
| 168 | 254 | |
| 255 | /// Returns whether self can fit into an integer of the requested type. | |
| 169 | 256 | pub fn fits(self: Int, comptime T: type) bool { |
| 170 | 257 | return self.fitsInTwosComp(T.is_signed, T.bit_count); |
| 171 | 258 | } |
| 172 | 259 | |
| 173 | // 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 the | |
| 175 | // value. It is inexact and will exceed the given value by 1-2 digits. | |
| 260 | /// Returns the approximate size of the integer in the given base. Negative values accommodate for | |
| 261 | /// the minus sign. This is used for determining the number of characters needed to print the | |
| 262 | /// value. It is inexact and may exceed the given value by ~1-2 bytes. | |
| 176 | 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 | 265 | return (bit_count / math.log2(base)) + 1; |
| 179 | 266 | } |
| 180 | 267 | |
| 268 | /// Sets an Int to value. Value must be an primitive integer type. | |
| 181 | 269 | pub fn set(self: *Int, value: var) Allocator.Error!void { |
| 270 | self.assertWritable(); | |
| 182 | 271 | const T = @typeOf(value); |
| 183 | 272 | |
| 184 | 273 | switch (@typeInfo(T)) { |
| ... | ... | @@ -186,19 +275,19 @@ pub const Int = struct { |
| 186 | 275 | const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T; |
| 187 | 276 | |
| 188 | 277 | try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb)); |
| 189 | self.positive = value >= 0; | |
| 190 | self.len = 0; | |
| 278 | self.metadata = 0; | |
| 279 | self.setSign(value >= 0); | |
| 191 | 280 | |
| 192 | 281 | var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value); |
| 193 | 282 | |
| 194 | 283 | if (info.bits <= Limb.bit_count) { |
| 195 | 284 | self.limbs[0] = Limb(w_value); |
| 196 | self.len = 1; | |
| 285 | self.metadata += 1; | |
| 197 | 286 | } else { |
| 198 | 287 | var i: usize = 0; |
| 199 | 288 | while (w_value != 0) : (i += 1) { |
| 200 | 289 | self.limbs[i] = @truncate(Limb, w_value); |
| 201 | self.len += 1; | |
| 290 | self.metadata += 1; | |
| 202 | 291 | |
| 203 | 292 | // TODO: shift == 64 at compile-time fails. Fails on u128 limbs. |
| 204 | 293 | w_value >>= Limb.bit_count / 2; |
| ... | ... | @@ -212,8 +301,8 @@ pub const Int = struct { |
| 212 | 301 | const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1; |
| 213 | 302 | try self.ensureCapacity(req_limbs); |
| 214 | 303 | |
| 215 | self.positive = value >= 0; | |
| 216 | self.len = req_limbs; | |
| 304 | self.metadata = req_limbs; | |
| 305 | self.setSign(value >= 0); | |
| 217 | 306 | |
| 218 | 307 | if (w_value <= maxInt(Limb)) { |
| 219 | 308 | self.limbs[0] = w_value; |
| ... | ... | @@ -240,6 +329,9 @@ pub const Int = struct { |
| 240 | 329 | TargetTooSmall, |
| 241 | 330 | }; |
| 242 | 331 | |
| 332 | /// Convert self to type T. | |
| 333 | /// | |
| 334 | /// Returns an error if self cannot be narrowed into the requested type without truncation. | |
| 243 | 335 | pub fn to(self: Int, comptime T: type) ConvertError!T { |
| 244 | 336 | switch (@typeId(T)) { |
| 245 | 337 | TypeId.Int => { |
| ... | ... | @@ -254,17 +346,17 @@ pub const Int = struct { |
| 254 | 346 | if (@sizeOf(UT) <= @sizeOf(Limb)) { |
| 255 | 347 | r = @intCast(UT, self.limbs[0]); |
| 256 | 348 | } else { |
| 257 | for (self.limbs[0..self.len]) |_, ri| { | |
| 258 | const limb = self.limbs[self.len - ri - 1]; | |
| 349 | for (self.limbs[0..self.len()]) |_, ri| { | |
| 350 | const limb = self.limbs[self.len() - ri - 1]; | |
| 259 | 351 | r <<= Limb.bit_count; |
| 260 | 352 | r |= limb; |
| 261 | 353 | } |
| 262 | 354 | } |
| 263 | 355 | |
| 264 | 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 | 358 | } else { |
| 267 | if (self.positive) { | |
| 359 | if (self.isPositive()) { | |
| 268 | 360 | return @intCast(T, r); |
| 269 | 361 | } else { |
| 270 | 362 | if (math.cast(T, r)) |ok| { |
| ... | ... | @@ -303,7 +395,15 @@ pub const Int = struct { |
| 303 | 395 | }; |
| 304 | 396 | } |
| 305 | 397 | |
| 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 | 405 | pub fn setString(self: *Int, base: u8, value: []const u8) !void { |
| 406 | self.assertWritable(); | |
| 307 | 407 | if (base < 2 or base > 16) { |
| 308 | 408 | return error.InvalidBase; |
| 309 | 409 | } |
| ... | ... | @@ -315,27 +415,22 @@ pub const Int = struct { |
| 315 | 415 | i += 1; |
| 316 | 416 | } |
| 317 | 417 | |
| 318 | // TODO values less than limb size should guarantee non allocating | |
| 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 | ||
| 418 | const ap_base = Int.initFixed(([]Limb{base})[0..]); | |
| 327 | 419 | try self.set(0); |
| 420 | ||
| 328 | 421 | for (value[i..]) |ch| { |
| 329 | 422 | const d = try charToDigit(ch, base); |
| 330 | d_fba.end_index = 0; | |
| 331 | const d_ap = try Int.initSet(d_al, d); | |
| 332 | 423 | |
| 333 | try self.mul(self.*, base_ap); | |
| 334 | try self.add(self.*, d_ap); | |
| 424 | const ap_d = Int.initFixed(([]Limb{d})[0..]); | |
| 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 | } |
| 338 | 431 | |
| 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 | 434 | /// TODO make this call format instead of the other way around |
| 340 | 435 | pub fn toString(self: Int, allocator: *Allocator, base: u8) ![]const u8 { |
| 341 | 436 | if (base < 2 or base > 16) { |
| ... | ... | @@ -355,7 +450,7 @@ pub const Int = struct { |
| 355 | 450 | if (base & (base - 1) == 0) { |
| 356 | 451 | const base_shift = math.log2_int(Limb, base); |
| 357 | 452 | |
| 358 | for (self.limbs[0..self.len]) |limb| { | |
| 453 | for (self.limbs[0..self.len()]) |limb| { | |
| 359 | 454 | var shift: usize = 0; |
| 360 | 455 | while (shift < Limb.bit_count) : (shift += base_shift) { |
| 361 | 456 | const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & Limb(base - 1)); |
| ... | ... | @@ -382,11 +477,11 @@ pub const Int = struct { |
| 382 | 477 | } |
| 383 | 478 | |
| 384 | 479 | var q = try self.clone(); |
| 385 | q.positive = true; | |
| 480 | q.abs(); | |
| 386 | 481 | var r = try Int.init(allocator); |
| 387 | 482 | var b = try Int.initSet(allocator, limb_base); |
| 388 | 483 | |
| 389 | while (q.len >= 2) { | |
| 484 | while (q.len() >= 2) { | |
| 390 | 485 | try Int.divTrunc(&q, &r, q, b); |
| 391 | 486 | |
| 392 | 487 | var r_word = r.limbs[0]; |
| ... | ... | @@ -399,7 +494,7 @@ pub const Int = struct { |
| 399 | 494 | } |
| 400 | 495 | |
| 401 | 496 | { |
| 402 | debug.assert(q.len == 1); | |
| 497 | debug.assert(q.len() == 1); | |
| 403 | 498 | |
| 404 | 499 | var r_word = q.limbs[0]; |
| 405 | 500 | while (r_word != 0) { |
| ... | ... | @@ -410,7 +505,7 @@ pub const Int = struct { |
| 410 | 505 | } |
| 411 | 506 | } |
| 412 | 507 | |
| 413 | if (!self.positive) { | |
| 508 | if (!self.isPositive()) { | |
| 414 | 509 | try digits.append('-'); |
| 415 | 510 | } |
| 416 | 511 | |
| ... | ... | @@ -419,7 +514,7 @@ pub const Int = struct { |
| 419 | 514 | return s; |
| 420 | 515 | } |
| 421 | 516 | |
| 422 | /// for the std lib format function | |
| 517 | /// To allow `std.fmt.printf` to work with Int. | |
| 423 | 518 | /// TODO make this non-allocating |
| 424 | 519 | pub fn format( |
| 425 | 520 | self: Int, |
| ... | ... | @@ -428,22 +523,24 @@ pub const Int = struct { |
| 428 | 523 | comptime FmtError: type, |
| 429 | 524 | output: fn (@typeOf(context), []const u8) FmtError!void, |
| 430 | 525 | ) FmtError!void { |
| 526 | self.assertWritable(); | |
| 431 | 527 | // TODO look at fmt and support other bases |
| 432 | const str = self.toString(self.allocator, 10) catch @panic("TODO make this non allocating"); | |
| 433 | defer self.allocator.free(str); | |
| 528 | // TODO support read-only fixed integers | |
| 529 | const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating"); | |
| 530 | defer self.allocator.?.free(str); | |
| 434 | 531 | return output(context, str); |
| 435 | 532 | } |
| 436 | 533 | |
| 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 | 535 | pub fn cmpAbs(a: Int, b: Int) i8 { |
| 439 | if (a.len < b.len) { | |
| 536 | if (a.len() < b.len()) { | |
| 440 | 537 | return -1; |
| 441 | 538 | } |
| 442 | if (a.len > b.len) { | |
| 539 | if (a.len() > b.len()) { | |
| 443 | 540 | return 1; |
| 444 | 541 | } |
| 445 | 542 | |
| 446 | var i: usize = a.len - 1; | |
| 543 | var i: usize = a.len() - 1; | |
| 447 | 544 | while (i != 0) : (i -= 1) { |
| 448 | 545 | if (a.limbs[i] != b.limbs[i]) { |
| 449 | 546 | break; |
| ... | ... | @@ -459,53 +556,37 @@ pub const Int = struct { |
| 459 | 556 | } |
| 460 | 557 | } |
| 461 | 558 | |
| 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 | 560 | pub fn cmp(a: Int, b: Int) i8 { |
| 464 | if (a.positive != b.positive) { | |
| 465 | return if (a.positive) i8(1) else -1; | |
| 561 | if (a.isPositive() != b.isPositive()) { | |
| 562 | return if (a.isPositive()) i8(1) else -1; | |
| 466 | 563 | } else { |
| 467 | 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 | } |
| 471 | 568 | |
| 472 | // if a == 0 | |
| 569 | /// Returns true if a == 0. | |
| 473 | 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 | } |
| 476 | 573 | |
| 477 | // if |a| == |b| | |
| 574 | /// Returns true if |a| == |b|. | |
| 478 | 575 | pub fn eqAbs(a: Int, b: Int) bool { |
| 479 | 576 | return cmpAbs(a, b) == 0; |
| 480 | 577 | } |
| 481 | 578 | |
| 482 | // if a == b | |
| 579 | /// Returns true if a == b. | |
| 483 | 580 | pub fn eq(a: Int, b: Int) bool { |
| 484 | 581 | return cmp(a, b) == 0; |
| 485 | 582 | } |
| 486 | 583 | |
| 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 | 584 | // Normalize a possible sequence of leading zeros. |
| 504 | 585 | // |
| 505 | 586 | // [1, 2, 3, 4, 0] -> [1, 2, 3, 4] |
| 506 | 587 | // [1, 2, 0, 0, 0] -> [1, 2] |
| 507 | 588 | // [0, 0, 0, 0, 0] -> [0] |
| 508 | fn normN(r: *Int, length: usize) void { | |
| 589 | fn normalize(r: *Int, length: usize) void { | |
| 509 | 590 | debug.assert(length > 0); |
| 510 | 591 | debug.assert(length <= r.limbs.len); |
| 511 | 592 | |
| ... | ... | @@ -517,11 +598,25 @@ pub const Int = struct { |
| 517 | 598 | } |
| 518 | 599 | |
| 519 | 600 | // Handle zero |
| 520 | r.len = if (j != 0) j else 1; | |
| 601 | r.setLen(if (j != 0) j else 1); | |
| 521 | 602 | } |
| 522 | 603 | |
| 523 | // r = a + b | |
| 604 | // 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 | 618 | pub fn add(r: *Int, a: Int, b: Int) Allocator.Error!void { |
| 619 | r.assertWritable(); | |
| 525 | 620 | if (a.eqZero()) { |
| 526 | 621 | try r.copy(b); |
| 527 | 622 | return; |
| ... | ... | @@ -530,38 +625,26 @@ pub const Int = struct { |
| 530 | 625 | return; |
| 531 | 626 | } |
| 532 | 627 | |
| 533 | if (a.positive != b.positive) { | |
| 534 | if (a.positive) { | |
| 628 | if (a.isPositive() != b.isPositive()) { | |
| 629 | if (a.isPositive()) { | |
| 535 | 630 | // (a) + (-b) => a - b |
| 536 | const bp = Int{ | |
| 537 | .allocator = undefined, | |
| 538 | .positive = true, | |
| 539 | .limbs = b.limbs, | |
| 540 | .len = b.len, | |
| 541 | }; | |
| 542 | try r.sub(a, bp); | |
| 631 | try r.sub(a, readOnlyPositive(b)); | |
| 543 | 632 | } else { |
| 544 | 633 | // (-a) + (b) => b - a |
| 545 | const ap = Int{ | |
| 546 | .allocator = undefined, | |
| 547 | .positive = true, | |
| 548 | .limbs = a.limbs, | |
| 549 | .len = a.len, | |
| 550 | }; | |
| 551 | try r.sub(b, ap); | |
| 634 | try r.sub(b, readOnlyPositive(a)); | |
| 552 | 635 | } |
| 553 | 636 | } else { |
| 554 | if (a.len >= b.len) { | |
| 555 | try r.ensureCapacity(a.len + 1); | |
| 556 | lladd(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); | |
| 557 | r.norm1(a.len + 1); | |
| 637 | if (a.len() >= b.len()) { | |
| 638 | try r.ensureCapacity(a.len() + 1); | |
| 639 | lladd(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); | |
| 640 | r.normalize(a.len() + 1); | |
| 558 | 641 | } else { |
| 559 | try r.ensureCapacity(b.len + 1); | |
| 560 | lladd(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); | |
| 561 | r.norm1(b.len + 1); | |
| 642 | try r.ensureCapacity(b.len() + 1); | |
| 643 | lladd(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); | |
| 644 | r.normalize(b.len() + 1); | |
| 562 | 645 | } |
| 563 | 646 | |
| 564 | r.positive = a.positive; | |
| 647 | r.setSign(a.isPositive()); | |
| 565 | 648 | } |
| 566 | 649 | } |
| 567 | 650 | |
| ... | ... | @@ -589,55 +672,48 @@ pub const Int = struct { |
| 589 | 672 | r[i] = carry; |
| 590 | 673 | } |
| 591 | 674 | |
| 592 | // r = a - b | |
| 675 | /// r = a - b | |
| 676 | /// | |
| 677 | /// r, a and b may be aliases. | |
| 678 | /// | |
| 679 | /// Returns an error if memory could not be allocated. | |
| 593 | 680 | pub fn sub(r: *Int, a: Int, b: Int) !void { |
| 594 | if (a.positive != b.positive) { | |
| 595 | if (a.positive) { | |
| 681 | r.assertWritable(); | |
| 682 | if (a.isPositive() != b.isPositive()) { | |
| 683 | if (a.isPositive()) { | |
| 596 | 684 | // (a) - (-b) => a + b |
| 597 | const bp = Int{ | |
| 598 | .allocator = undefined, | |
| 599 | .positive = true, | |
| 600 | .limbs = b.limbs, | |
| 601 | .len = b.len, | |
| 602 | }; | |
| 603 | try r.add(a, bp); | |
| 685 | try r.add(a, readOnlyPositive(b)); | |
| 604 | 686 | } else { |
| 605 | 687 | // (-a) - (b) => -(a + b) |
| 606 | const ap = Int{ | |
| 607 | .allocator = undefined, | |
| 608 | .positive = true, | |
| 609 | .limbs = a.limbs, | |
| 610 | .len = a.len, | |
| 611 | }; | |
| 612 | try r.add(ap, b); | |
| 613 | r.positive = false; | |
| 688 | try r.add(readOnlyPositive(a), b); | |
| 689 | r.setSign(false); | |
| 614 | 690 | } |
| 615 | 691 | } else { |
| 616 | if (a.positive) { | |
| 692 | if (a.isPositive()) { | |
| 617 | 693 | // (a) - (b) => a - b |
| 618 | 694 | if (a.cmp(b) >= 0) { |
| 619 | try r.ensureCapacity(a.len + 1); | |
| 620 | llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); | |
| 621 | r.normN(a.len); | |
| 622 | r.positive = true; | |
| 695 | try r.ensureCapacity(a.len() + 1); | |
| 696 | llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); | |
| 697 | r.normalize(a.len()); | |
| 698 | r.setSign(true); | |
| 623 | 699 | } else { |
| 624 | try r.ensureCapacity(b.len + 1); | |
| 625 | llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); | |
| 626 | r.normN(b.len); | |
| 627 | r.positive = false; | |
| 700 | try r.ensureCapacity(b.len() + 1); | |
| 701 | llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); | |
| 702 | r.normalize(b.len()); | |
| 703 | r.setSign(false); | |
| 628 | 704 | } |
| 629 | 705 | } else { |
| 630 | 706 | // (-a) - (-b) => -(a - b) |
| 631 | 707 | if (a.cmp(b) < 0) { |
| 632 | try r.ensureCapacity(a.len + 1); | |
| 633 | llsub(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); | |
| 634 | r.normN(a.len); | |
| 635 | r.positive = false; | |
| 708 | try r.ensureCapacity(a.len() + 1); | |
| 709 | llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); | |
| 710 | r.normalize(a.len()); | |
| 711 | r.setSign(false); | |
| 636 | 712 | } else { |
| 637 | try r.ensureCapacity(b.len + 1); | |
| 638 | llsub(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); | |
| 639 | r.normN(b.len); | |
| 640 | r.positive = true; | |
| 713 | try r.ensureCapacity(b.len() + 1); | |
| 714 | llsub(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); | |
| 715 | r.normalize(b.len()); | |
| 716 | r.setSign(true); | |
| 641 | 717 | } |
| 642 | 718 | } |
| 643 | 719 | } |
| ... | ... | @@ -667,16 +743,20 @@ pub const Int = struct { |
| 667 | 743 | debug.assert(borrow == 0); |
| 668 | 744 | } |
| 669 | 745 | |
| 670 | // rma = a * b | |
| 671 | // | |
| 672 | // For greatest efficiency, ensure rma does not alias a or b. | |
| 746 | /// rma = a * b | |
| 747 | /// | |
| 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 | 751 | pub fn mul(rma: *Int, a: Int, b: Int) !void { |
| 752 | rma.assertWritable(); | |
| 753 | ||
| 674 | 754 | var r = rma; |
| 675 | 755 | var aliased = rma.limbs.ptr == a.limbs.ptr or rma.limbs.ptr == b.limbs.ptr; |
| 676 | 756 | |
| 677 | 757 | var sr: Int = undefined; |
| 678 | 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 | 760 | r = &sr; |
| 681 | 761 | aliased = true; |
| 682 | 762 | } |
| ... | ... | @@ -685,16 +765,16 @@ pub const Int = struct { |
| 685 | 765 | r.deinit(); |
| 686 | 766 | }; |
| 687 | 767 | |
| 688 | try r.ensureCapacity(a.len + b.len); | |
| 768 | try r.ensureCapacity(a.len() + b.len()); | |
| 689 | 769 | |
| 690 | if (a.len >= b.len) { | |
| 691 | llmul(r.limbs, a.limbs[0..a.len], b.limbs[0..b.len]); | |
| 770 | if (a.len() >= b.len()) { | |
| 771 | llmul(r.limbs, a.limbs[0..a.len()], b.limbs[0..b.len()]); | |
| 692 | 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 | } |
| 695 | 775 | |
| 696 | r.positive = a.positive == b.positive; | |
| 697 | r.normN(a.len + b.len); | |
| 776 | r.normalize(a.len() + b.len()); | |
| 777 | r.setSign(a.isPositive() == b.isPositive()); | |
| 698 | 778 | } |
| 699 | 779 | |
| 700 | 780 | // a + b * c + *carry, sets carry to the overflow bits |
| ... | ... | @@ -740,29 +820,34 @@ pub const Int = struct { |
| 740 | 820 | } |
| 741 | 821 | } |
| 742 | 822 | |
| 823 | /// q = a / b (rem r) | |
| 824 | /// | |
| 825 | /// a / b are floored (rounded towards 0). | |
| 743 | 826 | pub fn divFloor(q: *Int, r: *Int, a: Int, b: Int) !void { |
| 744 | 827 | try div(q, r, a, b); |
| 745 | 828 | |
| 746 | 829 | // Trunc -> Floor. |
| 747 | if (!q.positive) { | |
| 748 | // TODO values less than limb size should guarantee non allocating | |
| 749 | var one_buffer: [512]u8 = undefined; | |
| 750 | const one_al = &std.heap.FixedBufferAllocator.init(one_buffer[0..]).allocator; | |
| 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); | |
| 830 | if (!q.isPositive()) { | |
| 831 | const one = Int.initFixed(([]Limb{1})[0..]); | |
| 832 | try q.sub(q.*, one); | |
| 833 | try r.add(q.*, one); | |
| 755 | 834 | } |
| 756 | r.positive = b.positive; | |
| 835 | r.setSign(b.isPositive()); | |
| 757 | 836 | } |
| 758 | 837 | |
| 838 | /// q = a / b (rem r) | |
| 839 | /// | |
| 840 | /// a / b are truncated (rounded towards -inf). | |
| 759 | 841 | pub fn divTrunc(q: *Int, r: *Int, a: Int, b: Int) !void { |
| 760 | 842 | try div(q, r, a, b); |
| 761 | r.positive = a.positive; | |
| 843 | r.setSign(a.isPositive()); | |
| 762 | 844 | } |
| 763 | 845 | |
| 764 | 846 | // Truncates by default. |
| 765 | 847 | fn div(quo: *Int, rem: *Int, a: Int, b: Int) !void { |
| 848 | quo.assertWritable(); | |
| 849 | rem.assertWritable(); | |
| 850 | ||
| 766 | 851 | if (b.eqZero()) { |
| 767 | 852 | @panic("division by zero"); |
| 768 | 853 | } |
| ... | ... | @@ -773,36 +858,67 @@ pub const Int = struct { |
| 773 | 858 | if (a.cmpAbs(b) < 0) { |
| 774 | 859 | // quo may alias a so handle rem first |
| 775 | 860 | try rem.copy(a); |
| 776 | rem.positive = a.positive == b.positive; | |
| 861 | rem.setSign(a.isPositive() == b.isPositive()); | |
| 777 | 862 | |
| 778 | quo.positive = true; | |
| 779 | quo.len = 1; | |
| 863 | quo.metadata = 1; | |
| 780 | 864 | quo.limbs[0] = 0; |
| 781 | 865 | return; |
| 782 | 866 | } |
| 783 | 867 | |
| 784 | if (b.len == 1) { | |
| 785 | try quo.ensureCapacity(a.len); | |
| 868 | // Handle trailing zero-words of divisor/dividend. These are not handled in the following | |
| 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 | }; | |
| 786 | 884 | |
| 787 | lldiv1(quo.limbs[0..], &rem.limbs[0], a.limbs[0..a.len], b.limbs[0]); | |
| 788 | quo.norm1(a.len); | |
| 789 | quo.positive = a.positive == b.positive; | |
| 885 | const ab_zero_limb_count = std.math.min(a_zero_limb_count, b_zero_limb_count); | |
| 790 | 886 | |
| 791 | rem.len = 1; | |
| 792 | rem.positive = true; | |
| 887 | if (b.len() - ab_zero_limb_count == 1) { | |
| 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 | 895 | } else { |
| 794 | 896 | // x and y are modified during division |
| 795 | var x = try a.clone(); | |
| 897 | var x = try Int.initCapacity(quo.allocator.?, a.len()); | |
| 796 | 898 | defer x.deinit(); |
| 899 | try x.copy(a); | |
| 797 | 900 | |
| 798 | var y = try b.clone(); | |
| 901 | var y = try Int.initCapacity(quo.allocator.?, b.len()); | |
| 799 | 902 | defer y.deinit(); |
| 903 | try y.copy(b); | |
| 800 | 904 | |
| 801 | 905 | // x may grow one limb during normalization |
| 802 | try quo.ensureCapacity(a.len + y.len); | |
| 803 | try divN(quo.allocator, quo, rem, &x, &y); | |
| 906 | try quo.ensureCapacity(a.len() + y.len()); | |
| 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 | } | |
| 804 | 915 | |
| 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 | } |
| 808 | 924 | |
| ... | ... | @@ -837,25 +953,28 @@ pub const Int = struct { |
| 837 | 953 | // |
| 838 | 954 | // x = qy + r where 0 <= r < y |
| 839 | 955 | fn divN(allocator: *Allocator, q: *Int, r: *Int, x: *Int, y: *Int) !void { |
| 840 | debug.assert(y.len >= 2); | |
| 841 | debug.assert(x.len >= y.len); | |
| 842 | debug.assert(q.limbs.len >= x.len + y.len - 1); | |
| 956 | debug.assert(y.len() >= 2); | |
| 957 | debug.assert(x.len() >= y.len()); | |
| 958 | debug.assert(q.limbs.len >= x.len() + y.len() - 1); | |
| 843 | 959 | debug.assert(default_capacity >= 3); // see 3.2 |
| 844 | 960 | |
| 845 | 961 | var tmp = try Int.init(allocator); |
| 846 | 962 | defer tmp.deinit(); |
| 847 | 963 | |
| 848 | // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) | |
| 849 | const norm_shift = @clz(y.limbs[y.len - 1]); | |
| 964 | // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) and even | |
| 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 | 969 | try x.shiftLeft(x.*, norm_shift); |
| 851 | 970 | try y.shiftLeft(y.*, norm_shift); |
| 852 | 971 | |
| 853 | const n = x.len - 1; | |
| 854 | const t = y.len - 1; | |
| 972 | const n = x.len() - 1; | |
| 973 | const t = y.len() - 1; | |
| 855 | 974 | |
| 856 | 975 | // 1. |
| 857 | q.len = n - t + 1; | |
| 858 | mem.set(Limb, q.limbs[0..q.len], 0); | |
| 976 | q.metadata = n - t + 1; | |
| 977 | mem.set(Limb, q.limbs[0..q.len()], 0); | |
| 859 | 978 | |
| 860 | 979 | // 2. |
| 861 | 980 | try tmp.shiftLeft(y.*, Limb.bit_count * (n - t)); |
| ... | ... | @@ -880,7 +999,7 @@ pub const Int = struct { |
| 880 | 999 | tmp.limbs[0] = if (i >= 2) x.limbs[i - 2] else 0; |
| 881 | 1000 | tmp.limbs[1] = if (i >= 1) x.limbs[i - 1] else 0; |
| 882 | 1001 | tmp.limbs[2] = x.limbs[i]; |
| 883 | tmp.normN(3); | |
| 1002 | tmp.normalize(3); | |
| 884 | 1003 | |
| 885 | 1004 | while (true) { |
| 886 | 1005 | // 2x1 limb multiplication unrolled against single-limb q[i-t-1] |
| ... | ... | @@ -888,7 +1007,7 @@ pub const Int = struct { |
| 888 | 1007 | r.limbs[0] = addMulLimbWithCarry(0, if (t >= 1) y.limbs[t - 1] else 0, q.limbs[i - t - 1], &carry); |
| 889 | 1008 | r.limbs[1] = addMulLimbWithCarry(0, y.limbs[t], q.limbs[i - t - 1], &carry); |
| 890 | 1009 | r.limbs[2] = carry; |
| 891 | r.normN(3); | |
| 1010 | r.normalize(3); | |
| 892 | 1011 | |
| 893 | 1012 | if (r.cmpAbs(tmp) <= 0) { |
| 894 | 1013 | break; |
| ... | ... | @@ -903,7 +1022,7 @@ pub const Int = struct { |
| 903 | 1022 | try tmp.shiftLeft(tmp, Limb.bit_count * (i - t - 1)); |
| 904 | 1023 | try x.sub(x.*, tmp); |
| 905 | 1024 | |
| 906 | if (!x.positive) { | |
| 1025 | if (!x.isPositive()) { | |
| 907 | 1026 | try tmp.shiftLeft(y.*, Limb.bit_count * (i - t - 1)); |
| 908 | 1027 | try x.add(x.*, tmp); |
| 909 | 1028 | q.limbs[i - t - 1] -= 1; |
| ... | ... | @@ -911,18 +1030,20 @@ pub const Int = struct { |
| 911 | 1030 | } |
| 912 | 1031 | |
| 913 | 1032 | // Denormalize |
| 914 | q.normN(q.len); | |
| 1033 | q.normalize(q.len()); | |
| 915 | 1034 | |
| 916 | 1035 | try r.shiftRight(x.*, norm_shift); |
| 917 | r.normN(r.len); | |
| 1036 | r.normalize(r.len()); | |
| 918 | 1037 | } |
| 919 | 1038 | |
| 920 | // r = a << shift, in other words, r = a * 2^shift | |
| 1039 | /// r = a << shift, in other words, r = a * 2^shift | |
| 921 | 1040 | pub fn shiftLeft(r: *Int, a: Int, shift: usize) !void { |
| 922 | try r.ensureCapacity(a.len + (shift / Limb.bit_count) + 1); | |
| 923 | llshl(r.limbs[0..], a.limbs[0..a.len], shift); | |
| 924 | r.norm1(a.len + (shift / Limb.bit_count) + 1); | |
| 925 | r.positive = a.positive; | |
| 1041 | r.assertWritable(); | |
| 1042 | ||
| 1043 | try r.ensureCapacity(a.len() + (shift / Limb.bit_count) + 1); | |
| 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 | } |
| 927 | 1048 | |
| 928 | 1049 | fn llshl(r: []Limb, a: []const Limb, shift: usize) void { |
| ... | ... | @@ -948,19 +1069,20 @@ pub const Int = struct { |
| 948 | 1069 | mem.set(Limb, r[0 .. limb_shift - 1], 0); |
| 949 | 1070 | } |
| 950 | 1071 | |
| 951 | // r = a >> shift | |
| 1072 | /// r = a >> shift | |
| 952 | 1073 | pub fn shiftRight(r: *Int, a: Int, shift: usize) !void { |
| 953 | if (a.len <= shift / Limb.bit_count) { | |
| 954 | r.len = 1; | |
| 1074 | r.assertWritable(); | |
| 1075 | ||
| 1076 | if (a.len() <= shift / Limb.bit_count) { | |
| 1077 | r.metadata = 1; | |
| 955 | 1078 | r.limbs[0] = 0; |
| 956 | r.positive = true; | |
| 957 | 1079 | return; |
| 958 | 1080 | } |
| 959 | 1081 | |
| 960 | try r.ensureCapacity(a.len - (shift / Limb.bit_count)); | |
| 961 | const r_len = llshr(r.limbs[0..], a.limbs[0..a.len], shift); | |
| 962 | r.len = a.len - (shift / Limb.bit_count); | |
| 963 | r.positive = a.positive; | |
| 1082 | try r.ensureCapacity(a.len() - (shift / Limb.bit_count)); | |
| 1083 | const r_len = llshr(r.limbs[0..], a.limbs[0..a.len()], shift); | |
| 1084 | r.metadata = a.len() - (shift / Limb.bit_count); | |
| 1085 | r.setSign(a.isPositive()); | |
| 964 | 1086 | } |
| 965 | 1087 | |
| 966 | 1088 | fn llshr(r: []Limb, a: []const Limb, shift: usize) void { |
| ... | ... | @@ -983,16 +1105,20 @@ pub const Int = struct { |
| 983 | 1105 | } |
| 984 | 1106 | } |
| 985 | 1107 | |
| 986 | // r = a | b | |
| 1108 | /// r = a | b | |
| 1109 | /// | |
| 1110 | /// a and b are zero-extended to the longer of a or b. | |
| 987 | 1111 | pub fn bitOr(r: *Int, a: Int, b: Int) !void { |
| 988 | if (a.len > b.len) { | |
| 989 | try r.ensureCapacity(a.len); | |
| 990 | llor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); | |
| 991 | r.len = a.len; | |
| 1112 | r.assertWritable(); | |
| 1113 | ||
| 1114 | if (a.len() > b.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 | 1118 | } else { |
| 993 | try r.ensureCapacity(b.len); | |
| 994 | llor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); | |
| 995 | r.len = b.len; | |
| 1119 | try r.ensureCapacity(b.len()); | |
| 1120 | llor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); | |
| 1121 | r.setLen(b.len()); | |
| 996 | 1122 | } |
| 997 | 1123 | } |
| 998 | 1124 | |
| ... | ... | @@ -1010,16 +1136,18 @@ pub const Int = struct { |
| 1010 | 1136 | } |
| 1011 | 1137 | } |
| 1012 | 1138 | |
| 1013 | // r = a & b | |
| 1139 | /// r = a & b | |
| 1014 | 1140 | pub fn bitAnd(r: *Int, a: Int, b: Int) !void { |
| 1015 | if (a.len > b.len) { | |
| 1016 | try r.ensureCapacity(b.len); | |
| 1017 | lland(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); | |
| 1018 | r.normN(b.len); | |
| 1141 | r.assertWritable(); | |
| 1142 | ||
| 1143 | if (a.len() > 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 | 1147 | } else { |
| 1020 | try r.ensureCapacity(a.len); | |
| 1021 | lland(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); | |
| 1022 | r.normN(a.len); | |
| 1148 | try r.ensureCapacity(a.len()); | |
| 1149 | lland(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); | |
| 1150 | r.normalize(a.len()); | |
| 1023 | 1151 | } |
| 1024 | 1152 | } |
| 1025 | 1153 | |
| ... | ... | @@ -1034,16 +1162,18 @@ pub const Int = struct { |
| 1034 | 1162 | } |
| 1035 | 1163 | } |
| 1036 | 1164 | |
| 1037 | // r = a ^ b | |
| 1165 | /// r = a ^ b | |
| 1038 | 1166 | pub fn bitXor(r: *Int, a: Int, b: Int) !void { |
| 1039 | if (a.len > b.len) { | |
| 1040 | try r.ensureCapacity(a.len); | |
| 1041 | llxor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]); | |
| 1042 | r.normN(a.len); | |
| 1167 | r.assertWritable(); | |
| 1168 | ||
| 1169 | if (a.len() > b.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 | 1173 | } else { |
| 1044 | try r.ensureCapacity(b.len); | |
| 1045 | llxor(r.limbs[0..], b.limbs[0..b.len], a.limbs[0..a.len]); | |
| 1046 | r.normN(b.len); | |
| 1174 | try r.ensureCapacity(b.len()); | |
| 1175 | llxor(r.limbs[0..], b.limbs[0..b.len()], a.limbs[0..a.len()]); | |
| 1176 | r.normalize(b.len()); | |
| 1047 | 1177 | } |
| 1048 | 1178 | } |
| 1049 | 1179 | |
| ... | ... | @@ -1067,7 +1197,9 @@ pub const Int = struct { |
| 1067 | 1197 | // They will still run on larger than this and should pass, but the multi-limb code-paths |
| 1068 | 1198 | // may be untested in some cases. |
| 1069 | 1199 | |
| 1070 | const al = debug.global_allocator; | |
| 1200 | var buffer: [64 * 8192]u8 = undefined; | |
| 1201 | var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); | |
| 1202 | const al = &fixed.allocator; | |
| 1071 | 1203 | |
| 1072 | 1204 | test "big.int comptime_int set" { |
| 1073 | 1205 | comptime var s = 0xefffffff00000001eeeeeeefaaaaaaab; |
| ... | ... | @@ -1088,14 +1220,14 @@ test "big.int comptime_int set negative" { |
| 1088 | 1220 | var a = try Int.initSet(al, -10); |
| 1089 | 1221 | |
| 1090 | 1222 | testing.expect(a.limbs[0] == 10); |
| 1091 | testing.expect(a.positive == false); | |
| 1223 | testing.expect(a.isPositive() == false); | |
| 1092 | 1224 | } |
| 1093 | 1225 | |
| 1094 | 1226 | test "big.int int set unaligned small" { |
| 1095 | 1227 | var a = try Int.initSet(al, u7(45)); |
| 1096 | 1228 | |
| 1097 | 1229 | testing.expect(a.limbs[0] == 45); |
| 1098 | testing.expect(a.positive == true); | |
| 1230 | testing.expect(a.isPositive() == true); | |
| 1099 | 1231 | } |
| 1100 | 1232 | |
| 1101 | 1233 | test "big.int comptime_int to" { |
| ... | ... | @@ -1116,7 +1248,7 @@ test "big.int to target too small error" { |
| 1116 | 1248 | testing.expectError(error.TargetTooSmall, a.to(u8)); |
| 1117 | 1249 | } |
| 1118 | 1250 | |
| 1119 | test "big.int norm1" { | |
| 1251 | test "big.int normalize" { | |
| 1120 | 1252 | var a = try Int.init(al); |
| 1121 | 1253 | try a.ensureCapacity(8); |
| 1122 | 1254 | |
| ... | ... | @@ -1124,26 +1256,26 @@ test "big.int norm1" { |
| 1124 | 1256 | a.limbs[1] = 2; |
| 1125 | 1257 | a.limbs[2] = 3; |
| 1126 | 1258 | a.limbs[3] = 0; |
| 1127 | a.norm1(4); | |
| 1128 | testing.expect(a.len == 3); | |
| 1259 | a.normalize(4); | |
| 1260 | testing.expect(a.len() == 3); | |
| 1129 | 1261 | |
| 1130 | 1262 | a.limbs[0] = 1; |
| 1131 | 1263 | a.limbs[1] = 2; |
| 1132 | 1264 | a.limbs[2] = 3; |
| 1133 | a.norm1(3); | |
| 1134 | testing.expect(a.len == 3); | |
| 1265 | a.normalize(3); | |
| 1266 | testing.expect(a.len() == 3); | |
| 1135 | 1267 | |
| 1136 | 1268 | a.limbs[0] = 0; |
| 1137 | 1269 | a.limbs[1] = 0; |
| 1138 | a.norm1(2); | |
| 1139 | testing.expect(a.len == 1); | |
| 1270 | a.normalize(2); | |
| 1271 | testing.expect(a.len() == 1); | |
| 1140 | 1272 | |
| 1141 | 1273 | a.limbs[0] = 0; |
| 1142 | a.norm1(1); | |
| 1143 | testing.expect(a.len == 1); | |
| 1274 | a.normalize(1); | |
| 1275 | testing.expect(a.len() == 1); | |
| 1144 | 1276 | } |
| 1145 | 1277 | |
| 1146 | test "big.int normN" { | |
| 1278 | test "big.int normalize multi" { | |
| 1147 | 1279 | var a = try Int.init(al); |
| 1148 | 1280 | try a.ensureCapacity(8); |
| 1149 | 1281 | |
| ... | ... | @@ -1151,25 +1283,25 @@ test "big.int normN" { |
| 1151 | 1283 | a.limbs[1] = 2; |
| 1152 | 1284 | a.limbs[2] = 0; |
| 1153 | 1285 | a.limbs[3] = 0; |
| 1154 | a.normN(4); | |
| 1155 | testing.expect(a.len == 2); | |
| 1286 | a.normalize(4); | |
| 1287 | testing.expect(a.len() == 2); | |
| 1156 | 1288 | |
| 1157 | 1289 | a.limbs[0] = 1; |
| 1158 | 1290 | a.limbs[1] = 2; |
| 1159 | 1291 | a.limbs[2] = 3; |
| 1160 | a.normN(3); | |
| 1161 | testing.expect(a.len == 3); | |
| 1292 | a.normalize(3); | |
| 1293 | testing.expect(a.len() == 3); | |
| 1162 | 1294 | |
| 1163 | 1295 | a.limbs[0] = 0; |
| 1164 | 1296 | a.limbs[1] = 0; |
| 1165 | 1297 | a.limbs[2] = 0; |
| 1166 | 1298 | a.limbs[3] = 0; |
| 1167 | a.normN(4); | |
| 1168 | testing.expect(a.len == 1); | |
| 1299 | a.normalize(4); | |
| 1300 | testing.expect(a.len() == 1); | |
| 1169 | 1301 | |
| 1170 | 1302 | a.limbs[0] = 0; |
| 1171 | a.normN(1); | |
| 1172 | testing.expect(a.len == 1); | |
| 1303 | a.normalize(1); | |
| 1304 | testing.expect(a.len() == 1); | |
| 1173 | 1305 | } |
| 1174 | 1306 | |
| 1175 | 1307 | test "big.int parity" { |
| ... | ... | @@ -1204,7 +1336,7 @@ test "big.int bitcount + sizeInBase" { |
| 1204 | 1336 | try a.shiftLeft(a, 5000); |
| 1205 | 1337 | testing.expect(a.bitCountAbs() == 5032); |
| 1206 | 1338 | testing.expect(a.sizeInBase(2) >= 5032); |
| 1207 | a.positive = false; | |
| 1339 | a.setSign(false); | |
| 1208 | 1340 | |
| 1209 | 1341 | testing.expect(a.bitCountAbs() == 5032); |
| 1210 | 1342 | testing.expect(a.sizeInBase(2) >= 5033); |
| ... | ... | @@ -1216,10 +1348,8 @@ test "big.int bitcount/to" { |
| 1216 | 1348 | try a.set(0); |
| 1217 | 1349 | testing.expect(a.bitCountTwosComp() == 0); |
| 1218 | 1350 | |
| 1219 | // TODO: stack smashing | |
| 1220 | // testing.expect((try a.to(u0)) == 0); | |
| 1221 | // TODO: sigsegv | |
| 1222 | // testing.expect((try a.to(i0)) == 0); | |
| 1351 | testing.expect((try a.to(u0)) == 0); | |
| 1352 | testing.expect((try a.to(i0)) == 0); | |
| 1223 | 1353 | |
| 1224 | 1354 | try a.set(-1); |
| 1225 | 1355 | testing.expect(a.bitCountTwosComp() == 1); |
| ... | ... | @@ -1980,6 +2110,98 @@ test "big.int div multi-multi (3.1/3.3 branch)" { |
| 1980 | 2110 | testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282); |
| 1981 | 2111 | } |
| 1982 | 2112 | |
| 2113 | test "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 | ||
| 2126 | test "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 | ||
| 2140 | test "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 | ||
| 2154 | test "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 | ||
| 2169 | test "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 | ||
| 2187 | test "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 | ||
| 1983 | 2205 | test "big.int shift-right single" { |
| 1984 | 2206 | var a = try Int.initSet(al, 0xffff0000); |
| 1985 | 2207 | try a.shiftRight(a, 16); |
std/math/big/rational.zig created+938| ... | ... | @@ -0,0 +1,938 @@ |
| 1 | const std = @import("../../std.zig"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const debug = std.debug; | |
| 4 | const math = std.math; | |
| 5 | const mem = std.mem; | |
| 6 | const testing = std.testing; | |
| 7 | const Allocator = mem.Allocator; | |
| 8 | const ArrayList = std.ArrayList; | |
| 9 | ||
| 10 | const TypeId = builtin.TypeId; | |
| 11 | ||
| 12 | const bn = @import("int.zig"); | |
| 13 | const Limb = bn.Limb; | |
| 14 | const DoubleLimb = bn.DoubleLimb; | |
| 15 | const 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. | |
| 24 | pub 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 | ||
| 468 | const SignedDoubleLimb = @IntType(true, DoubleLimb.bit_count); | |
| 469 | ||
| 470 | fn 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 | |
| 490 | fn 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 | ||
| 502 | fn 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 | ||
| 590 | var buffer: [64 * 8192]u8 = undefined; | |
| 591 | var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); | |
| 592 | var al = &fixed.allocator; | |
| 593 | ||
| 594 | test "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 | ||
| 604 | test "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 | ||
| 614 | test "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 | ||
| 624 | test "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 | ||
| 634 | test "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 | ||
| 644 | fn 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 | ||
| 663 | test "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 | ||
| 682 | test "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 | ||
| 710 | test "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 | ||
| 734 | test "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 | ||
| 744 | test "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 | ||
| 756 | test "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 | ||
| 767 | test "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 | ||
| 791 | test "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 | ||
| 807 | test "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 | ||
| 823 | test "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 | ||
| 845 | test "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 | ||
| 858 | test "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 | ||
| 871 | test "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 | ||
| 884 | test "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 | ||
| 897 | test "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 | ||
| 910 | test "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 | ||
| 923 | test "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 | // 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) = +-0 | |
| 4 | // - cbrt(+-inf) = +-inf | |
| 5 | // - cbrt(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/cbrtf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/cbrt.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("../std.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const expect = std.testing.expect; |
| 10 | 10 | |
| 11 | /// Returns the cube root of x. | |
| 12 | /// | |
| 13 | /// Special Cases: | |
| 14 | /// - cbrt(+-0) = +-0 | |
| 15 | /// - cbrt(+-inf) = +-inf | |
| 16 | /// - cbrt(nan) = nan | |
| 11 | 17 | pub fn cbrt(x: var) @typeOf(x) { |
| 12 | 18 | const T = @typeOf(x); |
| 13 | 19 | return switch (T) { |
std/math/ceil.zig+10-4| ... | ... | @@ -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) = +-0 | |
| 4 | // - ceil(+-inf) = +-inf | |
| 5 | // - ceil(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c | |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | 8 | const std = @import("../std.zig"); |
| 9 | 9 | const math = std.math; |
| 10 | 10 | const expect = std.testing.expect; |
| 11 | 11 | |
| 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 | |
| 12 | 18 | pub fn ceil(x: var) @typeOf(x) { |
| 13 | 19 | const T = @typeOf(x); |
| 14 | 20 | return switch (T) { |
std/math/complex.zig+12| ... | ... | @@ -23,13 +23,18 @@ pub const sqrt = @import("complex/sqrt.zig").sqrt; |
| 23 | 23 | pub const tanh = @import("complex/tanh.zig").tanh; |
| 24 | 24 | pub const tan = @import("complex/tan.zig").tan; |
| 25 | 25 | |
| 26 | /// A complex number consisting of a real an imaginary part. T must be a floating-point value. | |
| 26 | 27 | pub fn Complex(comptime T: type) type { |
| 27 | 28 | return struct { |
| 28 | 29 | const Self = @This(); |
| 29 | 30 | |
| 31 | /// Real part. | |
| 30 | 32 | re: T, |
| 33 | ||
| 34 | /// Imaginary part. | |
| 31 | 35 | im: T, |
| 32 | 36 | |
| 37 | /// Create a new Complex number from the given real and imaginary parts. | |
| 33 | 38 | pub fn new(re: T, im: T) Self { |
| 34 | 39 | return Self{ |
| 35 | 40 | .re = re, |
| ... | ... | @@ -37,6 +42,7 @@ pub fn Complex(comptime T: type) type { |
| 37 | 42 | }; |
| 38 | 43 | } |
| 39 | 44 | |
| 45 | /// Returns the sum of two complex numbers. | |
| 40 | 46 | pub fn add(self: Self, other: Self) Self { |
| 41 | 47 | return Self{ |
| 42 | 48 | .re = self.re + other.re, |
| ... | ... | @@ -44,6 +50,7 @@ pub fn Complex(comptime T: type) type { |
| 44 | 50 | }; |
| 45 | 51 | } |
| 46 | 52 | |
| 53 | /// Returns the subtraction of two complex numbers. | |
| 47 | 54 | pub fn sub(self: Self, other: Self) Self { |
| 48 | 55 | return Self{ |
| 49 | 56 | .re = self.re - other.re, |
| ... | ... | @@ -51,6 +58,7 @@ pub fn Complex(comptime T: type) type { |
| 51 | 58 | }; |
| 52 | 59 | } |
| 53 | 60 | |
| 61 | /// Returns the product of two complex numbers. | |
| 54 | 62 | pub fn mul(self: Self, other: Self) Self { |
| 55 | 63 | return Self{ |
| 56 | 64 | .re = self.re * other.re - self.im * other.im, |
| ... | ... | @@ -58,6 +66,7 @@ pub fn Complex(comptime T: type) type { |
| 58 | 66 | }; |
| 59 | 67 | } |
| 60 | 68 | |
| 69 | /// Returns the quotient of two complex numbers. | |
| 61 | 70 | pub fn div(self: Self, other: Self) Self { |
| 62 | 71 | const re_num = self.re * other.re + self.im * other.im; |
| 63 | 72 | const im_num = self.im * other.re - self.re * other.im; |
| ... | ... | @@ -69,6 +78,7 @@ pub fn Complex(comptime T: type) type { |
| 69 | 78 | }; |
| 70 | 79 | } |
| 71 | 80 | |
| 81 | /// Returns the complex conjugate of a number. | |
| 72 | 82 | pub fn conjugate(self: Self) Self { |
| 73 | 83 | return Self{ |
| 74 | 84 | .re = self.re, |
| ... | ... | @@ -76,6 +86,7 @@ pub fn Complex(comptime T: type) type { |
| 76 | 86 | }; |
| 77 | 87 | } |
| 78 | 88 | |
| 89 | /// Returns the reciprocal of a complex number. | |
| 79 | 90 | pub fn reciprocal(self: Self) Self { |
| 80 | 91 | const m = self.re * self.re + self.im * self.im; |
| 81 | 92 | return Self{ |
| ... | ... | @@ -84,6 +95,7 @@ pub fn Complex(comptime T: type) type { |
| 84 | 95 | }; |
| 85 | 96 | } |
| 86 | 97 | |
| 98 | /// Returns the magnitude of a complex number. | |
| 87 | 99 | pub fn magnitude(self: Self) T { |
| 88 | 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 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the absolute value (modulus) of z. | |
| 7 | 8 | pub fn abs(z: var) @typeOf(z.re) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | return math.hypot(T, z.re, z.im); |
std/math/complex/acos.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the arc-cosine of z. | |
| 7 | 8 | pub fn acos(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | const q = cmath.asin(z); |
std/math/complex/acosh.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the hyperbolic arc-cosine of z. | |
| 7 | 8 | pub fn acosh(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | const q = cmath.acos(z); |
std/math/complex/arg.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the angular component (in radians) of z. | |
| 7 | 8 | pub fn arg(z: var) @typeOf(z.re) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | return math.atan2(T, z.im, z.re); |
std/math/complex/asin.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | // Returns the arc-sine of z. | |
| 7 | 8 | pub fn asin(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | const x = z.re; |
std/math/complex/asinh.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the hyperbolic arc-sine of z. | |
| 7 | 8 | pub fn asinh(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | const q = Complex(T).new(-z.im, z.re); |
std/math/complex/atan.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../../std.zig"); |
| 2 | 8 | const testing = std.testing; |
| 3 | 9 | const math = std.math; |
| 4 | 10 | const cmath = math.complex; |
| 5 | 11 | const Complex = cmath.Complex; |
| 6 | 12 | |
| 13 | /// Returns the arc-tangent of z. | |
| 7 | 14 | pub fn atan(z: var) @typeOf(z) { |
| 8 | 15 | const T = @typeOf(z.re); |
| 9 | 16 | return switch (T) { |
std/math/complex/atanh.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the hyperbolic arc-tangent of z. | |
| 7 | 8 | pub fn atanh(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 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 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the complex conjugate of z. | |
| 7 | 8 | pub fn conj(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | return Complex(T).new(z.re, -z.im); |
std/math/complex/cos.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the cosine of z. | |
| 7 | 8 | pub fn cos(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | const p = Complex(T).new(-z.im, z.re); |
std/math/complex/cosh.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../../std.zig"); |
| 2 | 8 | const testing = std.testing; |
| 3 | 9 | const math = std.math; |
| ... | ... | @@ -6,6 +12,7 @@ const Complex = cmath.Complex; |
| 6 | 12 | |
| 7 | 13 | const ldexp_cexp = @import("ldexp.zig").ldexp_cexp; |
| 8 | 14 | |
| 15 | /// Returns the hyperbolic arc-cosine of z. | |
| 9 | 16 | pub fn cosh(z: var) Complex(@typeOf(z.re)) { |
| 10 | 17 | const T = @typeOf(z.re); |
| 11 | 18 | return switch (T) { |
std/math/complex/exp.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../../std.zig"); |
| 2 | 8 | const testing = std.testing; |
| 3 | 9 | const math = std.math; |
| ... | ... | @@ -6,6 +12,7 @@ const Complex = cmath.Complex; |
| 6 | 12 | |
| 7 | 13 | const ldexp_cexp = @import("ldexp.zig").ldexp_cexp; |
| 8 | 14 | |
| 15 | /// Returns e raised to the power of z (e^z). | |
| 9 | 16 | pub fn exp(z: var) @typeOf(z) { |
| 10 | 17 | const T = @typeOf(z.re); |
| 11 | 18 |
std/math/complex/ldexp.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../../std.zig"); |
| 2 | 8 | const debug = std.debug; |
| 3 | 9 | const math = std.math; |
| 4 | 10 | const cmath = math.complex; |
| 5 | 11 | const Complex = cmath.Complex; |
| 6 | 12 | |
| 13 | /// Returns exp(z) scaled to avoid overflow. | |
| 7 | 14 | pub fn ldexp_cexp(z: var, expt: i32) @typeOf(z) { |
| 8 | 15 | const T = @typeOf(z.re); |
| 9 | 16 |
std/math/complex/log.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the natural logarithm of z. | |
| 7 | 8 | pub fn log(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | const r = cmath.abs(z); |
std/math/complex/pow.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns z raised to the complex power of c. | |
| 7 | 8 | pub fn pow(comptime T: type, z: T, c: T) T { |
| 8 | 9 | const p = cmath.log(z); |
| 9 | 10 | const q = c.mul(p); |
std/math/complex/proj.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the projection of z onto the riemann sphere. | |
| 7 | 8 | pub fn proj(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 |
std/math/complex/sin.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the sine of z. | |
| 7 | 8 | pub fn sin(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | const p = Complex(T).new(-z.im, z.re); |
std/math/complex/sinh.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../../std.zig"); |
| 2 | 8 | const testing = std.testing; |
| 3 | 9 | const math = std.math; |
| ... | ... | @@ -6,6 +12,7 @@ const Complex = cmath.Complex; |
| 6 | 12 | |
| 7 | 13 | const ldexp_cexp = @import("ldexp.zig").ldexp_cexp; |
| 8 | 14 | |
| 15 | /// Returns the hyperbolic sine of z. | |
| 9 | 16 | pub fn sinh(z: var) @typeOf(z) { |
| 10 | 17 | const T = @typeOf(z.re); |
| 11 | 18 | return switch (T) { |
std/math/complex/sqrt.zig+8| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../../std.zig"); |
| 2 | 8 | const testing = std.testing; |
| 3 | 9 | const math = std.math; |
| 4 | 10 | const cmath = math.complex; |
| 5 | 11 | const Complex = cmath.Complex; |
| 6 | 12 | |
| 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. | |
| 7 | 15 | pub fn sqrt(z: var) @typeOf(z) { |
| 8 | 16 | const T = @typeOf(z.re); |
| 9 | 17 |
std/math/complex/tan.zig+1| ... | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | 4 | const cmath = math.complex; |
| 5 | 5 | const Complex = cmath.Complex; |
| 6 | 6 | |
| 7 | /// Returns the tanget of z. | |
| 7 | 8 | pub fn tan(z: var) Complex(@typeOf(z.re)) { |
| 8 | 9 | const T = @typeOf(z.re); |
| 9 | 10 | const q = Complex(T).new(-z.im, z.re); |
std/math/complex/tanh.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../../std.zig"); |
| 2 | 8 | const testing = std.testing; |
| 3 | 9 | const math = std.math; |
| 4 | 10 | const cmath = math.complex; |
| 5 | 11 | const Complex = cmath.Complex; |
| 6 | 12 | |
| 13 | /// Returns the hyperbolic tangent of z. | |
| 7 | 14 | pub fn tanh(z: var) @typeOf(z) { |
| 8 | 15 | const T = @typeOf(z.re); |
| 9 | 16 | return switch (T) { |
std/math/copysign.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../std.zig"); |
| 2 | 8 | const math = std.math; |
| 3 | 9 | const expect = std.testing.expect; |
| 4 | 10 | const maxInt = std.math.maxInt; |
| 5 | 11 | |
| 12 | /// Returns a value with the magnitude of x and the sign of y. | |
| 6 | 13 | pub fn copysign(comptime T: type, x: T, y: T) T { |
| 7 | 14 | return switch (T) { |
| 8 | 15 | f16 => copysign16(x, y), |
std/math/cos.zig+46-100| ... | ... | @@ -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) = nan | |
| 4 | // - cos(nan) = nan | |
| 4 | // https://golang.org/src/math/sin.go | |
| 5 | 5 | |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | 7 | const std = @import("../std.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const expect = std.testing.expect; |
| 10 | 10 | |
| 11 | /// Returns the cosine of the radian value x. | |
| 12 | /// | |
| 13 | /// Special Cases: | |
| 14 | /// - cos(+-inf) = nan | |
| 15 | /// - cos(nan) = nan | |
| 11 | 16 | pub fn cos(x: var) @typeOf(x) { |
| 12 | 17 | const T = @typeOf(x); |
| 13 | 18 | return switch (T) { |
| 14 | f32 => cos32(x), | |
| 15 | f64 => cos64(x), | |
| 19 | f32 => cos_(f32, x), | |
| 20 | f64 => cos_(f64, x), | |
| 16 | 21 | else => @compileError("cos not implemented for " ++ @typeName(T)), |
| 17 | 22 | }; |
| 18 | 23 | } |
| ... | ... | @@ -33,78 +38,24 @@ const C3 = 2.48015872888517045348E-5; |
| 33 | 38 | const C4 = -1.38888888888730564116E-3; |
| 34 | 39 | const C5 = 4.16666666666665929218E-2; |
| 35 | 40 | |
| 36 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. | |
| 37 | // | |
| 38 | // This may have slight differences on some edge cases and may need to replaced if so. | |
| 39 | fn cos32(x_: f32) f32 { | |
| 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); | |
| 41 | const pi4a = 7.85398125648498535156e-1; | |
| 42 | const pi4b = 3.77489470793079817668E-8; | |
| 43 | const pi4c = 2.69515142907905952645E-15; | |
| 44 | const m4pi = 1.273239544735162542821171882678754627704620361328125; | |
| 57 | 45 | |
| 58 | if (j & 1 == 1) { | |
| 59 | j += 1; | |
| 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 | ||
| 90 | fn 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; | |
| 46 | fn cos_(comptime T: type, x_: T) T { | |
| 47 | const I = @IntType(true, T.bit_count); | |
| 95 | 48 | |
| 96 | 49 | var x = x_; |
| 97 | 50 | if (math.isNan(x) or math.isInf(x)) { |
| 98 | return math.nan(f64); | |
| 51 | return math.nan(T); | |
| 99 | 52 | } |
| 100 | 53 | |
| 101 | 54 | var sign = false; |
| 102 | if (x < 0) { | |
| 103 | x = -x; | |
| 104 | } | |
| 55 | x = math.fabs(x); | |
| 105 | 56 | |
| 106 | 57 | var y = math.floor(x * m4pi); |
| 107 | var j = @floatToInt(i64, y); | |
| 58 | var j = @floatToInt(I, y); | |
| 108 | 59 | |
| 109 | 60 | if (j & 1 == 1) { |
| 110 | 61 | j += 1; |
| ... | ... | @@ -123,56 +74,51 @@ fn cos64(x_: f64) f64 { |
| 123 | 74 | const z = ((x - y * pi4a) - y * pi4b) - y * pi4c; |
| 124 | 75 | const w = z * z; |
| 125 | 76 | |
| 126 | const r = r: { | |
| 127 | if (j == 1 or j == 2) { | |
| 128 | break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0))))); | |
| 129 | } else { | |
| 130 | break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0))))); | |
| 131 | } | |
| 132 | }; | |
| 77 | const r = if (j == 1 or j == 2) | |
| 78 | z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0))))) | |
| 79 | else | |
| 80 | 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0))))); | |
| 133 | 81 | |
| 134 | if (sign) { | |
| 135 | return -r; | |
| 136 | } else { | |
| 137 | return r; | |
| 138 | } | |
| 82 | return if (sign) -r else r; | |
| 139 | 83 | } |
| 140 | 84 | |
| 141 | 85 | test "math.cos" { |
| 142 | expect(cos(f32(0.0)) == cos32(0.0)); | |
| 143 | expect(cos(f64(0.0)) == cos64(0.0)); | |
| 86 | expect(cos(f32(0.0)) == cos_(f32, 0.0)); | |
| 87 | expect(cos(f64(0.0)) == cos_(f64, 0.0)); | |
| 144 | 88 | } |
| 145 | 89 | |
| 146 | 90 | test "math.cos32" { |
| 147 | 91 | const epsilon = 0.000001; |
| 148 | 92 | |
| 149 | expect(math.approxEq(f32, cos32(0.0), 1.0, epsilon)); | |
| 150 | expect(math.approxEq(f32, cos32(0.2), 0.980067, epsilon)); | |
| 151 | expect(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon)); | |
| 152 | expect(math.approxEq(f32, cos32(1.5), 0.070737, epsilon)); | |
| 153 | expect(math.approxEq(f32, cos32(37.45), 0.969132, epsilon)); | |
| 154 | expect(math.approxEq(f32, cos32(89.123), 0.400798, epsilon)); | |
| 93 | expect(math.approxEq(f32, cos_(f32, 0.0), 1.0, epsilon)); | |
| 94 | expect(math.approxEq(f32, cos_(f32, 0.2), 0.980067, epsilon)); | |
| 95 | expect(math.approxEq(f32, cos_(f32, 0.8923), 0.627623, epsilon)); | |
| 96 | expect(math.approxEq(f32, cos_(f32, 1.5), 0.070737, epsilon)); | |
| 97 | expect(math.approxEq(f32, cos_(f32, -1.5), 0.070737, 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 | } |
| 156 | 101 | |
| 157 | 102 | test "math.cos64" { |
| 158 | 103 | const epsilon = 0.000001; |
| 159 | 104 | |
| 160 | expect(math.approxEq(f64, cos64(0.0), 1.0, epsilon)); | |
| 161 | expect(math.approxEq(f64, cos64(0.2), 0.980067, epsilon)); | |
| 162 | expect(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon)); | |
| 163 | expect(math.approxEq(f64, cos64(1.5), 0.070737, epsilon)); | |
| 164 | expect(math.approxEq(f64, cos64(37.45), 0.969132, epsilon)); | |
| 165 | expect(math.approxEq(f64, cos64(89.123), 0.40080, epsilon)); | |
| 105 | expect(math.approxEq(f64, cos_(f64, 0.0), 1.0, epsilon)); | |
| 106 | expect(math.approxEq(f64, cos_(f64, 0.2), 0.980067, epsilon)); | |
| 107 | expect(math.approxEq(f64, cos_(f64, 0.8923), 0.627623, epsilon)); | |
| 108 | expect(math.approxEq(f64, cos_(f64, 1.5), 0.070737, epsilon)); | |
| 109 | expect(math.approxEq(f64, cos_(f64, -1.5), 0.070737, 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 | } |
| 167 | 113 | |
| 168 | 114 | test "math.cos32.special" { |
| 169 | expect(math.isNan(cos32(math.inf(f32)))); | |
| 170 | expect(math.isNan(cos32(-math.inf(f32)))); | |
| 171 | expect(math.isNan(cos32(math.nan(f32)))); | |
| 115 | expect(math.isNan(cos_(f32, math.inf(f32)))); | |
| 116 | expect(math.isNan(cos_(f32, -math.inf(f32)))); | |
| 117 | expect(math.isNan(cos_(f32, math.nan(f32)))); | |
| 172 | 118 | } |
| 173 | 119 | |
| 174 | 120 | test "math.cos64.special" { |
| 175 | expect(math.isNan(cos64(math.inf(f64)))); | |
| 176 | expect(math.isNan(cos64(-math.inf(f64)))); | |
| 177 | expect(math.isNan(cos64(math.nan(f64)))); | |
| 121 | expect(math.isNan(cos_(f64, math.inf(f64)))); | |
| 122 | expect(math.isNan(cos_(f64, -math.inf(f64)))); | |
| 123 | expect(math.isNan(cos_(f64, math.nan(f64)))); | |
| 178 | 124 | } |
std/math/cosh.zig+10-4| ... | ... | @@ -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) = 1 | |
| 4 | // - cosh(+-inf) = +inf | |
| 5 | // - cosh(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/coshf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/cosh.c | |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | 8 | const std = @import("../std.zig"); |
| ... | ... | @@ -11,6 +11,12 @@ const expo2 = @import("expo2.zig").expo2; |
| 11 | 11 | const expect = std.testing.expect; |
| 12 | 12 | const maxInt = std.math.maxInt; |
| 13 | 13 | |
| 14 | /// Returns the hyperbolic cosine of x. | |
| 15 | /// | |
| 16 | /// Special Cases: | |
| 17 | /// - cosh(+-0) = 1 | |
| 18 | /// - cosh(+-inf) = +inf | |
| 19 | /// - cosh(nan) = nan | |
| 14 | 20 | pub fn cosh(x: var) @typeOf(x) { |
| 15 | 21 | const T = @typeOf(x); |
| 16 | 22 | return switch (T) { |
std/math/exp.zig+9-3| ... | ... | @@ -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) = +inf | |
| 4 | // - exp(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/expf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/exp.c | |
| 5 | 6 | |
| 6 | 7 | const std = @import("../std.zig"); |
| 7 | 8 | const math = std.math; |
| 8 | 9 | const assert = std.debug.assert; |
| 9 | 10 | const builtin = @import("builtin"); |
| 10 | 11 | |
| 12 | /// Returns e raised to the power of x (e^x). | |
| 13 | /// | |
| 14 | /// Special Cases: | |
| 15 | /// - exp(+inf) = +inf | |
| 16 | /// - exp(nan) = nan | |
| 11 | 17 | pub fn exp(x: var) @typeOf(x) { |
| 12 | 18 | const T = @typeOf(x); |
| 13 | 19 | return switch (T) { |
std/math/exp2.zig+9-3| ... | ... | @@ -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) = +inf | |
| 4 | // - exp2(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/exp2f.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/exp2.c | |
| 5 | 6 | |
| 6 | 7 | const std = @import("../std.zig"); |
| 7 | 8 | const math = std.math; |
| 8 | 9 | const expect = std.testing.expect; |
| 9 | 10 | |
| 11 | /// Returns 2 raised to the power of x (2^x). | |
| 12 | /// | |
| 13 | /// Special Cases: | |
| 14 | /// - exp2(+inf) = +inf | |
| 15 | /// - exp2(nan) = nan | |
| 10 | 16 | pub fn exp2(x: var) @typeOf(x) { |
| 11 | 17 | const T = @typeOf(x); |
| 12 | 18 | return switch (T) { |
std/math/expm1.zig+13-4| ... | ... | @@ -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) = +inf | |
| 4 | // - expm1(-inf) = -1 | |
| 5 | // - expm1(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/expmf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/expm.c | |
| 6 | ||
| 7 | // TODO: Updated recently. | |
| 6 | 8 | |
| 7 | 9 | const builtin = @import("builtin"); |
| 8 | 10 | const std = @import("../std.zig"); |
| 9 | 11 | const math = std.math; |
| 10 | 12 | const expect = std.testing.expect; |
| 11 | 13 | |
| 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 | |
| 12 | 21 | pub fn expm1(x: var) @typeOf(x) { |
| 13 | 22 | const T = @typeOf(x); |
| 14 | 23 | return switch (T) { |
std/math/expo2.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const math = @import("../math.zig"); |
| 2 | 8 | |
| 9 | /// Returns exp(x) / 2 for x >= log(maxFloat(T)). | |
| 3 | 10 | pub fn expo2(x: var) @typeOf(x) { |
| 4 | 11 | const T = @typeOf(x); |
| 5 | 12 | return switch (T) { |
std/math/fabs.zig+9-3| ... | ... | @@ -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) = +inf | |
| 4 | // - fabs(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/fabsf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/fabs.c | |
| 5 | 6 | |
| 6 | 7 | const std = @import("../std.zig"); |
| 7 | 8 | const math = std.math; |
| 8 | 9 | const expect = std.testing.expect; |
| 9 | 10 | const maxInt = std.math.maxInt; |
| 10 | 11 | |
| 12 | /// Returns the absolute value of x. | |
| 13 | /// | |
| 14 | /// Special Cases: | |
| 15 | /// - fabs(+-inf) = +inf | |
| 16 | /// - fabs(nan) = nan | |
| 11 | 17 | pub fn fabs(x: var) @typeOf(x) { |
| 12 | 18 | const T = @typeOf(x); |
| 13 | 19 | return switch (T) { |
std/math/floor.zig+10-4| ... | ... | @@ -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) = +-0 | |
| 4 | // - floor(+-inf) = +-inf | |
| 5 | // - floor(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c | |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | 8 | const expect = std.testing.expect; |
| 9 | 9 | const std = @import("../std.zig"); |
| 10 | 10 | const math = std.math; |
| 11 | 11 | |
| 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 | |
| 12 | 18 | pub fn floor(x: var) @typeOf(x) { |
| 13 | 19 | const T = @typeOf(x); |
| 14 | 20 | return switch (T) { |
std/math/fma.zig+9-1| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../std.zig"); |
| 2 | 8 | const math = std.math; |
| 3 | 9 | const expect = std.testing.expect; |
| 4 | 10 | |
| 11 | /// Returns x * y + z with a single rounding error. | |
| 5 | 12 | pub fn fma(comptime T: type, x: T, y: T, z: T) T { |
| 6 | 13 | return switch (T) { |
| 7 | 14 | f32 => fma32(x, y, z), |
| ... | ... | @@ -16,7 +23,7 @@ fn fma32(x: f32, y: f32, z: f32) f32 { |
| 16 | 23 | const u = @bitCast(u64, xy_z); |
| 17 | 24 | const e = (u >> 52) & 0x7FF; |
| 18 | 25 | |
| 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 | 27 | return @floatCast(f32, xy_z); |
| 21 | 28 | } else { |
| 22 | 29 | // TODO: Handle inexact case with double-rounding |
| ... | ... | @@ -24,6 +31,7 @@ fn fma32(x: f32, y: f32, z: f32) f32 { |
| 24 | 31 | } |
| 25 | 32 | } |
| 26 | 33 | |
| 34 | // NOTE: Upstream fma.c has been rewritten completely to raise fp exceptions more accurately. | |
| 27 | 35 | fn fma64(x: f64, y: f64, z: f64) f64 { |
| 28 | 36 | if (!math.isFinite(x) or !math.isFinite(y)) { |
| 29 | 37 | return x * y + z; |
std/math/frexp.zig+11-4| ... | ... | @@ -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, 0 | |
| 4 | // - frexp(+-inf) = +-inf, 0 | |
| 5 | // - frexp(nan) = nan, undefined | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/frexpf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/frexp.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("../std.zig"); |
| 8 | 8 | const math = std.math; |
| ... | ... | @@ -17,6 +17,13 @@ fn frexp_result(comptime T: type) type { |
| 17 | 17 | pub const frexp32_result = frexp_result(f32); |
| 18 | 18 | pub const frexp64_result = frexp_result(f64); |
| 19 | 19 | |
| 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 | |
| 20 | 27 | pub fn frexp(x: var) frexp_result(@typeOf(x)) { |
| 21 | 28 | const T = @typeOf(x); |
| 22 | 29 | return switch (T) { |
std/math/hypot.zig+11-5| ... | ... | @@ -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) = +inf | |
| 4 | // - hypot(x, +-inf) = +inf | |
| 5 | // - hypot(nan, y) = nan | |
| 6 | // - hypot(x, nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/hypotf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/hypot.c | |
| 7 | 6 | |
| 8 | 7 | const std = @import("../std.zig"); |
| 9 | 8 | const math = std.math; |
| 10 | 9 | const expect = std.testing.expect; |
| 11 | 10 | const maxInt = std.math.maxInt; |
| 12 | 11 | |
| 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 | |
| 13 | 19 | pub fn hypot(comptime T: type, x: T, y: T) T { |
| 14 | 20 | return switch (T) { |
| 15 | 21 | f32 => hypot32(x, y), |
std/math/ilogb.zig+10-4| ... | ... | @@ -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 | // - ilogb(0) = maxInt(i32) | |
| 5 | // - ilogb(nan) = maxInt(i32) | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/ilogbf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/ilogb.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("../std.zig"); |
| 8 | 8 | const math = std.math; |
| ... | ... | @@ -10,6 +10,12 @@ const expect = std.testing.expect; |
| 10 | 10 | const maxInt = std.math.maxInt; |
| 11 | 11 | const minInt = std.math.minInt; |
| 12 | 12 | |
| 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) | |
| 13 | 19 | pub fn ilogb(x: var) i32 { |
| 14 | 20 | const T = @typeOf(x); |
| 15 | 21 | return switch (T) { |
std/math/inf.zig+1| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("../std.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | |
| 4 | /// Returns value inf for the type T. | |
| 4 | 5 | pub fn inf(comptime T: type) T { |
| 5 | 6 | return switch (T) { |
| 6 | 7 | f16 => math.inf_f16, |
std/math/isfinite.zig+1| ... | ... | @@ -3,6 +3,7 @@ const math = std.math; |
| 3 | 3 | const expect = std.testing.expect; |
| 4 | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | |
| 6 | /// Returns whether x is a finite value. | |
| 6 | 7 | pub fn isFinite(x: var) bool { |
| 7 | 8 | const T = @typeOf(x); |
| 8 | 9 | switch (T) { |
std/math/isinf.zig+3| ... | ... | @@ -3,6 +3,7 @@ const math = std.math; |
| 3 | 3 | const expect = std.testing.expect; |
| 4 | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | |
| 6 | /// Returns whether x is an infinity, ignoring sign. | |
| 6 | 7 | pub fn isInf(x: var) bool { |
| 7 | 8 | const T = @typeOf(x); |
| 8 | 9 | switch (T) { |
| ... | ... | @@ -28,6 +29,7 @@ pub fn isInf(x: var) bool { |
| 28 | 29 | } |
| 29 | 30 | } |
| 30 | 31 | |
| 32 | /// Returns whether x is an infinity with a positive sign. | |
| 31 | 33 | pub fn isPositiveInf(x: var) bool { |
| 32 | 34 | const T = @typeOf(x); |
| 33 | 35 | switch (T) { |
| ... | ... | @@ -49,6 +51,7 @@ pub fn isPositiveInf(x: var) bool { |
| 49 | 51 | } |
| 50 | 52 | } |
| 51 | 53 | |
| 54 | /// Returns whether x is an infinity with a negative sign. | |
| 52 | 55 | pub fn isNegativeInf(x: var) bool { |
| 53 | 56 | const T = @typeOf(x); |
| 54 | 57 | switch (T) { |
std/math/isnan.zig+4-2| ... | ... | @@ -3,13 +3,15 @@ const math = std.math; |
| 3 | 3 | const expect = std.testing.expect; |
| 4 | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | |
| 6 | /// Returns whether x is a nan. | |
| 6 | 7 | pub fn isNan(x: var) bool { |
| 7 | 8 | return x != x; |
| 8 | 9 | } |
| 9 | 10 | |
| 10 | /// Note: A signalling nan is identical to a standard nan right now but may have a different bit | |
| 11 | /// representation in the future when required. | |
| 11 | /// Returns whether x is a signalling nan. | |
| 12 | 12 | pub 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 | 15 | return isNan(x); |
| 14 | 16 | } |
| 15 | 17 |
std/math/isnormal.zig+1| ... | ... | @@ -3,6 +3,7 @@ const math = std.math; |
| 3 | 3 | const expect = std.testing.expect; |
| 4 | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | |
| 6 | // Returns whether x has a normalized representation (i.e. integer part of mantissa is 1). | |
| 6 | 7 | pub fn isNormal(x: var) bool { |
| 7 | 8 | const T = @typeOf(x); |
| 8 | 9 | switch (T) { |
std/math/ln.zig+11-5| ... | ... | @@ -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) = +inf | |
| 4 | // - ln(0) = -inf | |
| 5 | // - ln(x) = nan if x < 0 | |
| 6 | // - ln(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/lnf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/ln.c | |
| 7 | 6 | |
| 8 | 7 | const std = @import("../std.zig"); |
| 9 | 8 | const math = std.math; |
| ... | ... | @@ -11,6 +10,13 @@ const expect = std.testing.expect; |
| 11 | 10 | const builtin = @import("builtin"); |
| 12 | 11 | const TypeId = builtin.TypeId; |
| 13 | 12 | |
| 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 | |
| 14 | 20 | pub fn ln(x: var) @typeOf(x) { |
| 15 | 21 | const T = @typeOf(x); |
| 16 | 22 | switch (@typeId(T)) { |
std/math/log.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../std.zig"); |
| 2 | 8 | const math = std.math; |
| 3 | 9 | const builtin = @import("builtin"); |
| 4 | 10 | const TypeId = builtin.TypeId; |
| 5 | 11 | const expect = std.testing.expect; |
| 6 | 12 | |
| 13 | /// Returns the logarithm of x for the provided base. | |
| 7 | 14 | pub fn log(comptime T: type, base: T, x: T) T { |
| 8 | 15 | if (base == 2) { |
| 9 | 16 | return math.log2(x); |
std/math/log10.zig+11-5| ... | ... | @@ -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) = +inf | |
| 4 | // - log10(0) = -inf | |
| 5 | // - log10(x) = nan if x < 0 | |
| 6 | // - log10(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log10f.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log10.c | |
| 7 | 6 | |
| 8 | 7 | const std = @import("../std.zig"); |
| 9 | 8 | const math = std.math; |
| ... | ... | @@ -12,6 +11,13 @@ const builtin = @import("builtin"); |
| 12 | 11 | const TypeId = builtin.TypeId; |
| 13 | 12 | const maxInt = std.math.maxInt; |
| 14 | 13 | |
| 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 | |
| 15 | 21 | pub fn log10(x: var) @typeOf(x) { |
| 16 | 22 | const T = @typeOf(x); |
| 17 | 23 | switch (@typeId(T)) { |
std/math/log1p.zig+12-6| ... | ... | @@ -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) = +inf | |
| 4 | // - log1p(+-0) = +-0 | |
| 5 | // - log1p(-1) = -inf | |
| 6 | // - log1p(x) = nan if x < -1 | |
| 7 | // - log1p(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log1pf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log1p.c | |
| 8 | 6 | |
| 9 | 7 | const builtin = @import("builtin"); |
| 10 | 8 | const std = @import("../std.zig"); |
| 11 | 9 | const math = std.math; |
| 12 | 10 | const expect = std.testing.expect; |
| 13 | 11 | |
| 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 | |
| 14 | 20 | pub fn log1p(x: var) @typeOf(x) { |
| 15 | 21 | const T = @typeOf(x); |
| 16 | 22 | return switch (T) { |
std/math/log2.zig+11-5| ... | ... | @@ -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) = +inf | |
| 4 | // - log2(0) = -inf | |
| 5 | // - log2(x) = nan if x < 0 | |
| 6 | // - log2(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log2f.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log2.c | |
| 7 | 6 | |
| 8 | 7 | const std = @import("../std.zig"); |
| 9 | 8 | const math = std.math; |
| ... | ... | @@ -12,6 +11,13 @@ const builtin = @import("builtin"); |
| 12 | 11 | const TypeId = builtin.TypeId; |
| 13 | 12 | const maxInt = std.math.maxInt; |
| 14 | 13 | |
| 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 | |
| 15 | 21 | pub fn log2(x: var) @typeOf(x) { |
| 16 | 22 | const T = @typeOf(x); |
| 17 | 23 | switch (@typeId(T)) { |
std/math/modf.zig+10-3| ... | ... | @@ -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, nan | |
| 4 | // - modf(nan) = nan, nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/modff.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/modf.c | |
| 5 | 6 | |
| 6 | 7 | const std = @import("../std.zig"); |
| 7 | 8 | const math = std.math; |
| ... | ... | @@ -17,6 +18,12 @@ fn modf_result(comptime T: type) type { |
| 17 | 18 | pub const modf32_result = modf_result(f32); |
| 18 | 19 | pub const modf64_result = modf_result(f64); |
| 19 | 20 | |
| 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 | |
| 20 | 27 | pub fn modf(x: var) modf_result(@typeOf(x)) { |
| 21 | 28 | const T = @typeOf(x); |
| 22 | 29 | return switch (T) { |
std/math/nan.zig+4-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | const math = @import("../math.zig"); |
| 2 | 2 | |
| 3 | /// Returns the nan representation for type T. | |
| 3 | 4 | pub fn nan(comptime T: type) T { |
| 4 | 5 | return switch (T) { |
| 5 | 6 | f16 => math.nan_f16, |
| ... | ... | @@ -10,9 +11,10 @@ pub fn nan(comptime T: type) T { |
| 10 | 11 | }; |
| 11 | 12 | } |
| 12 | 13 | |
| 13 | // Note: A signalling nan is identical to a standard right now by may have a different bit | |
| 14 | // representation in the future when required. | |
| 14 | /// Returns the signalling nan representation for type T. | |
| 15 | 15 | pub 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 | 18 | return switch (T) { |
| 17 | 19 | f16 => @bitCast(f16, math.nan_u16), |
| 18 | 20 | f32 => @bitCast(f32, math.nan_u32), |
std/math/pow.zig+57-39| ... | ... | @@ -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 x | |
| 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 | |
| 4 | // https://golang.org/src/math/pow.go | |
| 23 | 5 | |
| 24 | 6 | const builtin = @import("builtin"); |
| 25 | 7 | const std = @import("../std.zig"); |
| 26 | 8 | const math = std.math; |
| 27 | 9 | const expect = std.testing.expect; |
| 28 | 10 | |
| 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 | |
| 30 | 34 | pub fn pow(comptime T: type, x: T, y: T) T { |
| 31 | 35 | if (@typeInfo(T) == builtin.TypeId.Int) { |
| 32 | 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 | 57 | return x; |
| 54 | 58 | } |
| 55 | 59 | |
| 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 | 60 | if (x == 0) { |
| 66 | 61 | if (y < 0) { |
| 67 | 62 | // 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 | 107 | } |
| 113 | 108 | } |
| 114 | 109 | |
| 115 | var ay = y; | |
| 116 | var flip = false; | |
| 117 | if (ay < 0) { | |
| 118 | ay = -ay; | |
| 119 | flip = true; | |
| 110 | // special case sqrt | |
| 111 | if (y == 0.5) { | |
| 112 | return math.sqrt(x); | |
| 113 | } | |
| 114 | ||
| 115 | if (y == -0.5) { | |
| 116 | return 1 / math.sqrt(x); | |
| 120 | 117 | } |
| 121 | 118 | |
| 122 | const r1 = math.modf(ay); | |
| 119 | const r1 = math.modf(math.fabs(y)); | |
| 123 | 120 | var yi = r1.ipart; |
| 124 | 121 | var yf = r1.fpart; |
| 125 | 122 | |
| ... | ... | @@ -148,8 +145,18 @@ pub fn pow(comptime T: type, x: T, y: T) T { |
| 148 | 145 | var xe = r2.exponent; |
| 149 | 146 | var x1 = r2.significand; |
| 150 | 147 | |
| 151 | var i = @floatToInt(i32, yi); | |
| 148 | var i = @floatToInt(@IntType(true, T.bit_count), yi); | |
| 152 | 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 | 160 | if (i & 1 == 1) { |
| 154 | 161 | a1 *= x1; |
| 155 | 162 | ae += xe; |
| ... | ... | @@ -163,7 +170,7 @@ pub fn pow(comptime T: type, x: T, y: T) T { |
| 163 | 170 | } |
| 164 | 171 | |
| 165 | 172 | // a *= a1 * 2^ae |
| 166 | if (flip) { | |
| 173 | if (y < 0) { | |
| 167 | 174 | a1 = 1 / a1; |
| 168 | 175 | ae = -ae; |
| 169 | 176 | } |
| ... | ... | @@ -202,6 +209,9 @@ test "math.pow.special" { |
| 202 | 209 | expect(pow(f32, 45, 1.0) == 45); |
| 203 | 210 | expect(pow(f32, -45, 1.0) == -45); |
| 204 | 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 | 215 | expect(math.isNan(pow(f32, 5.0, math.nan(f32)))); |
| 206 | 216 | expect(math.isPositiveInf(pow(f32, 0.0, -1.0))); |
| 207 | 217 | //expect(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required? |
| ... | ... | @@ -232,3 +242,11 @@ test "math.pow.special" { |
| 232 | 242 | expect(math.isNan(pow(f32, -1.0, 1.2))); |
| 233 | 243 | expect(math.isNan(pow(f32, -12.4, 78.5))); |
| 234 | 244 | } |
| 245 | ||
| 246 | test "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 | // 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 x | |
| 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 | |
| 4 | // https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/src/libcore/num/mod.rs#L3423 | |
| 10 | 5 | |
| 11 | 6 | const builtin = @import("builtin"); |
| 12 | 7 | const std = @import("../std.zig"); |
| ... | ... | @@ -14,7 +9,16 @@ const math = std.math; |
| 14 | 9 | const assert = std.debug.assert; |
| 15 | 10 | const testing = std.testing; |
| 16 | 11 | |
| 17 | // This implementation is based on that from the rust stlib | |
| 12 | /// 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 | |
| 18 | 22 | pub fn powi(comptime T: type, x: T, y: T) (error{ |
| 19 | 23 | Overflow, |
| 20 | 24 | Underflow, |
std/math/round.zig+10-4| ... | ... | @@ -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) = +-0 | |
| 4 | // - round(+-inf) = +-inf | |
| 5 | // - round(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/roundf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/round.c | |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | 8 | const expect = std.testing.expect; |
| 9 | 9 | const std = @import("../std.zig"); |
| 10 | 10 | const math = std.math; |
| 11 | 11 | |
| 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 | |
| 12 | 18 | pub fn round(x: var) @typeOf(x) { |
| 13 | 19 | const T = @typeOf(x); |
| 14 | 20 | return switch (T) { |
std/math/scalbn.zig+7| ... | ... | @@ -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 | ||
| 1 | 7 | const std = @import("../std.zig"); |
| 2 | 8 | const math = std.math; |
| 3 | 9 | const expect = std.testing.expect; |
| 4 | 10 | |
| 11 | /// Returns x * 2^n. | |
| 5 | 12 | pub fn scalbn(x: var, n: i32) @typeOf(x) { |
| 6 | 13 | const T = @typeOf(x); |
| 7 | 14 | return switch (T) { |
std/math/signbit.zig+1| ... | ... | @@ -2,6 +2,7 @@ const std = @import("../std.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const expect = std.testing.expect; |
| 4 | 4 | |
| 5 | /// Returns whether x is negative or negative 0. | |
| 5 | 6 | pub fn signbit(x: var) bool { |
| 6 | 7 | const T = @typeOf(x); |
| 7 | 8 | return switch (T) { |
std/math/sin.zig+52-108| ... | ... | @@ -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) = +-0 | |
| 4 | // - sin(+-inf) = nan | |
| 5 | // - sin(nan) = nan | |
| 4 | // https://golang.org/src/math/sin.go | |
| 6 | 5 | |
| 7 | 6 | const builtin = @import("builtin"); |
| 8 | 7 | const std = @import("../std.zig"); |
| 9 | 8 | const math = std.math; |
| 10 | 9 | const expect = std.testing.expect; |
| 11 | 10 | |
| 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 | |
| 12 | 17 | pub fn sin(x: var) @typeOf(x) { |
| 13 | 18 | const T = @typeOf(x); |
| 14 | 19 | return switch (T) { |
| 15 | f32 => sin32(x), | |
| 16 | f64 => sin64(x), | |
| 20 | f32 => sin_(T, x), | |
| 21 | f64 => sin_(T, x), | |
| 17 | 22 | else => @compileError("sin not implemented for " ++ @typeName(T)), |
| 18 | 23 | }; |
| 19 | 24 | } |
| ... | ... | @@ -34,83 +39,27 @@ const C3 = 2.48015872888517045348E-5; |
| 34 | 39 | const C4 = -1.38888888888730564116E-3; |
| 35 | 40 | const C5 = 4.16666666666665929218E-2; |
| 36 | 41 | |
| 37 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. | |
| 38 | // | |
| 39 | // This may have slight differences on some edge cases and may need to replaced if so. | |
| 40 | fn sin32(x_: f32) f32 { | |
| 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 | } | |
| 42 | const pi4a = 7.85398125648498535156e-1; | |
| 43 | const pi4b = 3.77489470793079817668E-8; | |
| 44 | const pi4c = 2.69515142907905952645E-15; | |
| 45 | const m4pi = 1.273239544735162542821171882678754627704620361328125; | |
| 67 | 46 | |
| 68 | j &= 7; | |
| 69 | if (j > 3) { | |
| 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 | ||
| 92 | fn 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; | |
| 47 | fn sin_(comptime T: type, x_: T) T { | |
| 48 | const I = @IntType(true, T.bit_count); | |
| 97 | 49 | |
| 98 | 50 | var x = x_; |
| 99 | 51 | if (x == 0 or math.isNan(x)) { |
| 100 | 52 | return x; |
| 101 | 53 | } |
| 102 | 54 | if (math.isInf(x)) { |
| 103 | return math.nan(f64); | |
| 55 | return math.nan(T); | |
| 104 | 56 | } |
| 105 | 57 | |
| 106 | var sign = false; | |
| 107 | if (x < 0) { | |
| 108 | x = -x; | |
| 109 | sign = true; | |
| 110 | } | |
| 58 | var sign = x < 0; | |
| 59 | x = math.fabs(x); | |
| 111 | 60 | |
| 112 | 61 | var y = math.floor(x * m4pi); |
| 113 | var j = @floatToInt(i64, y); | |
| 62 | var j = @floatToInt(I, y); | |
| 114 | 63 | |
| 115 | 64 | if (j & 1 == 1) { |
| 116 | 65 | j += 1; |
| ... | ... | @@ -126,61 +75,56 @@ fn sin64(x_: f64) f64 { |
| 126 | 75 | const z = ((x - y * pi4a) - y * pi4b) - y * pi4c; |
| 127 | 76 | const w = z * z; |
| 128 | 77 | |
| 129 | const r = r: { | |
| 130 | if (j == 1 or j == 2) { | |
| 131 | break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0))))); | |
| 132 | } else { | |
| 133 | break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0))))); | |
| 134 | } | |
| 135 | }; | |
| 78 | const r = 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))))) | |
| 80 | else | |
| 81 | z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0))))); | |
| 136 | 82 | |
| 137 | if (sign) { | |
| 138 | return -r; | |
| 139 | } else { | |
| 140 | return r; | |
| 141 | } | |
| 83 | return if (sign) -r else r; | |
| 142 | 84 | } |
| 143 | 85 | |
| 144 | 86 | test "math.sin" { |
| 145 | expect(sin(f32(0.0)) == sin32(0.0)); | |
| 146 | expect(sin(f64(0.0)) == sin64(0.0)); | |
| 87 | expect(sin(f32(0.0)) == sin_(f32, 0.0)); | |
| 88 | expect(sin(f64(0.0)) == sin_(f64, 0.0)); | |
| 147 | 89 | expect(comptime (math.sin(f64(2))) == math.sin(f64(2))); |
| 148 | 90 | } |
| 149 | 91 | |
| 150 | 92 | test "math.sin32" { |
| 151 | 93 | const epsilon = 0.000001; |
| 152 | 94 | |
| 153 | expect(math.approxEq(f32, sin32(0.0), 0.0, epsilon)); | |
| 154 | expect(math.approxEq(f32, sin32(0.2), 0.198669, epsilon)); | |
| 155 | expect(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon)); | |
| 156 | expect(math.approxEq(f32, sin32(1.5), 0.997495, epsilon)); | |
| 157 | expect(math.approxEq(f32, sin32(37.45), -0.246544, epsilon)); | |
| 158 | expect(math.approxEq(f32, sin32(89.123), 0.916166, epsilon)); | |
| 95 | expect(math.approxEq(f32, sin_(f32, 0.0), 0.0, epsilon)); | |
| 96 | expect(math.approxEq(f32, sin_(f32, 0.2), 0.198669, epsilon)); | |
| 97 | expect(math.approxEq(f32, sin_(f32, 0.8923), 0.778517, epsilon)); | |
| 98 | expect(math.approxEq(f32, sin_(f32, 1.5), 0.997495, epsilon)); | |
| 99 | expect(math.approxEq(f32, sin_(f32, -1.5), -0.997495, 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 | } |
| 160 | 103 | |
| 161 | 104 | test "math.sin64" { |
| 162 | 105 | const epsilon = 0.000001; |
| 163 | 106 | |
| 164 | expect(math.approxEq(f64, sin64(0.0), 0.0, epsilon)); | |
| 165 | expect(math.approxEq(f64, sin64(0.2), 0.198669, epsilon)); | |
| 166 | expect(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon)); | |
| 167 | expect(math.approxEq(f64, sin64(1.5), 0.997495, epsilon)); | |
| 168 | expect(math.approxEq(f64, sin64(37.45), -0.246543, epsilon)); | |
| 169 | expect(math.approxEq(f64, sin64(89.123), 0.916166, epsilon)); | |
| 107 | expect(math.approxEq(f64, sin_(f64, 0.0), 0.0, epsilon)); | |
| 108 | expect(math.approxEq(f64, sin_(f64, 0.2), 0.198669, epsilon)); | |
| 109 | expect(math.approxEq(f64, sin_(f64, 0.8923), 0.778517, epsilon)); | |
| 110 | expect(math.approxEq(f64, sin_(f64, 1.5), 0.997495, epsilon)); | |
| 111 | expect(math.approxEq(f64, sin_(f64, -1.5), -0.997495, 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 | } |
| 171 | 115 | |
| 172 | 116 | test "math.sin32.special" { |
| 173 | expect(sin32(0.0) == 0.0); | |
| 174 | expect(sin32(-0.0) == -0.0); | |
| 175 | expect(math.isNan(sin32(math.inf(f32)))); | |
| 176 | expect(math.isNan(sin32(-math.inf(f32)))); | |
| 177 | expect(math.isNan(sin32(math.nan(f32)))); | |
| 117 | expect(sin_(f32, 0.0) == 0.0); | |
| 118 | expect(sin_(f32, -0.0) == -0.0); | |
| 119 | expect(math.isNan(sin_(f32, math.inf(f32)))); | |
| 120 | expect(math.isNan(sin_(f32, -math.inf(f32)))); | |
| 121 | expect(math.isNan(sin_(f32, math.nan(f32)))); | |
| 178 | 122 | } |
| 179 | 123 | |
| 180 | 124 | test "math.sin64.special" { |
| 181 | expect(sin64(0.0) == 0.0); | |
| 182 | expect(sin64(-0.0) == -0.0); | |
| 183 | expect(math.isNan(sin64(math.inf(f64)))); | |
| 184 | expect(math.isNan(sin64(-math.inf(f64)))); | |
| 185 | expect(math.isNan(sin64(math.nan(f64)))); | |
| 125 | expect(sin_(f64, 0.0) == 0.0); | |
| 126 | expect(sin_(f64, -0.0) == -0.0); | |
| 127 | expect(math.isNan(sin_(f64, math.inf(f64)))); | |
| 128 | expect(math.isNan(sin_(f64, -math.inf(f64)))); | |
| 129 | expect(math.isNan(sin_(f64, math.nan(f64)))); | |
| 186 | 130 | } |
std/math/sinh.zig+10-4| ... | ... | @@ -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) = +-0 | |
| 4 | // - sinh(+-inf) = +-inf | |
| 5 | // - sinh(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/sinhf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/sinh.c | |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | 8 | const std = @import("../std.zig"); |
| ... | ... | @@ -11,6 +11,12 @@ const expect = std.testing.expect; |
| 11 | 11 | const expo2 = @import("expo2.zig").expo2; |
| 12 | 12 | const maxInt = std.math.maxInt; |
| 13 | 13 | |
| 14 | /// Returns the hyperbolic sine of x. | |
| 15 | /// | |
| 16 | /// Special Cases: | |
| 17 | /// - sinh(+-0) = +-0 | |
| 18 | /// - sinh(+-inf) = +-inf | |
| 19 | /// - sinh(nan) = nan | |
| 14 | 20 | pub fn sinh(x: var) @typeOf(x) { |
| 15 | 21 | const T = @typeOf(x); |
| 16 | 22 | return switch (T) { |
std/math/sqrt.zig+7-7| ... | ... | @@ -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 | ||
| 8 | 1 | const std = @import("../std.zig"); |
| 9 | 2 | const math = std.math; |
| 10 | 3 | const expect = std.testing.expect; |
| ... | ... | @@ -12,6 +5,13 @@ const builtin = @import("builtin"); |
| 12 | 5 | const TypeId = builtin.TypeId; |
| 13 | 6 | const maxInt = std.math.maxInt; |
| 14 | 7 | |
| 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 | |
| 15 | 15 | pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) { |
| 16 | 16 | const T = @typeOf(x); |
| 17 | 17 | switch (@typeId(T)) { |
std/math/tan.zig+50-104| ... | ... | @@ -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) = +-0 | |
| 4 | // - tan(+-inf) = nan | |
| 5 | // - tan(nan) = nan | |
| 4 | // https://golang.org/src/math/tan.go | |
| 6 | 5 | |
| 7 | 6 | const builtin = @import("builtin"); |
| 8 | 7 | const std = @import("../std.zig"); |
| 9 | 8 | const math = std.math; |
| 10 | 9 | const expect = std.testing.expect; |
| 11 | 10 | |
| 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 | |
| 12 | 17 | pub fn tan(x: var) @typeOf(x) { |
| 13 | 18 | const T = @typeOf(x); |
| 14 | 19 | return switch (T) { |
| 15 | f32 => tan32(x), | |
| 16 | f64 => tan64(x), | |
| 20 | f32 => tan_(f32, x), | |
| 21 | f64 => tan_(f64, x), | |
| 17 | 22 | else => @compileError("tan not implemented for " ++ @typeName(T)), |
| 18 | 23 | }; |
| 19 | 24 | } |
| ... | ... | @@ -27,80 +32,27 @@ const Tq2 = -1.32089234440210967447E6; |
| 27 | 32 | const Tq3 = 2.50083801823357915839E7; |
| 28 | 33 | const Tq4 = -5.38695755929454629881E7; |
| 29 | 34 | |
| 30 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. | |
| 31 | // | |
| 32 | // This may have slight differences on some edge cases and may need to replaced if so. | |
| 33 | fn tan32(x_: f32) f32 { | |
| 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 | } | |
| 35 | const pi4a = 7.85398125648498535156e-1; | |
| 36 | const pi4b = 3.77489470793079817668E-8; | |
| 37 | const pi4c = 2.69515142907905952645E-15; | |
| 38 | const m4pi = 1.273239544735162542821171882678754627704620361328125; | |
| 81 | 39 | |
| 82 | fn tan64(x_: f64) f64 { | |
| 83 | const pi4a = 7.85398125648498535156e-1; | |
| 84 | const pi4b = 3.77489470793079817668E-8; | |
| 85 | const pi4c = 2.69515142907905952645E-15; | |
| 86 | const m4pi = 1.273239544735162542821171882678754627704620361328125; | |
| 40 | fn tan_(comptime T: type, x_: T) T { | |
| 41 | const I = @IntType(true, T.bit_count); | |
| 87 | 42 | |
| 88 | 43 | var x = x_; |
| 89 | 44 | if (x == 0 or math.isNan(x)) { |
| 90 | 45 | return x; |
| 91 | 46 | } |
| 92 | 47 | if (math.isInf(x)) { |
| 93 | return math.nan(f64); | |
| 48 | return math.nan(T); | |
| 94 | 49 | } |
| 95 | 50 | |
| 96 | var sign = false; | |
| 97 | if (x < 0) { | |
| 98 | x = -x; | |
| 99 | sign = true; | |
| 100 | } | |
| 51 | var sign = x < 0; | |
| 52 | x = math.fabs(x); | |
| 101 | 53 | |
| 102 | 54 | var y = math.floor(x * m4pi); |
| 103 | var j = @floatToInt(i64, y); | |
| 55 | var j = @floatToInt(I, y); | |
| 104 | 56 | |
| 105 | 57 | if (j & 1 == 1) { |
| 106 | 58 | j += 1; |
| ... | ... | @@ -110,63 +62,57 @@ fn tan64(x_: f64) f64 { |
| 110 | 62 | const z = ((x - y * pi4a) - y * pi4b) - y * pi4c; |
| 111 | 63 | const w = z * z; |
| 112 | 64 | |
| 113 | var r = r: { | |
| 114 | if (w > 1e-14) { | |
| 115 | break :r z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4)); | |
| 116 | } else { | |
| 117 | break :r z; | |
| 118 | } | |
| 119 | }; | |
| 65 | var r = if (w > 1e-14) | |
| 66 | z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4)) | |
| 67 | else | |
| 68 | z; | |
| 120 | 69 | |
| 121 | 70 | if (j & 2 == 2) { |
| 122 | 71 | r = -1 / r; |
| 123 | 72 | } |
| 124 | if (sign) { | |
| 125 | r = -r; | |
| 126 | } | |
| 127 | 73 | |
| 128 | return r; | |
| 74 | return if (sign) -r else r; | |
| 129 | 75 | } |
| 130 | 76 | |
| 131 | 77 | test "math.tan" { |
| 132 | expect(tan(f32(0.0)) == tan32(0.0)); | |
| 133 | expect(tan(f64(0.0)) == tan64(0.0)); | |
| 78 | expect(tan(f32(0.0)) == tan_(f32, 0.0)); | |
| 79 | expect(tan(f64(0.0)) == tan_(f64, 0.0)); | |
| 134 | 80 | } |
| 135 | 81 | |
| 136 | 82 | test "math.tan32" { |
| 137 | 83 | const epsilon = 0.000001; |
| 138 | 84 | |
| 139 | expect(math.approxEq(f32, tan32(0.0), 0.0, epsilon)); | |
| 140 | expect(math.approxEq(f32, tan32(0.2), 0.202710, epsilon)); | |
| 141 | expect(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon)); | |
| 142 | expect(math.approxEq(f32, tan32(1.5), 14.101420, epsilon)); | |
| 143 | expect(math.approxEq(f32, tan32(37.45), -0.254397, epsilon)); | |
| 144 | expect(math.approxEq(f32, tan32(89.123), 2.285852, epsilon)); | |
| 85 | expect(math.approxEq(f32, tan_(f32, 0.0), 0.0, epsilon)); | |
| 86 | expect(math.approxEq(f32, tan_(f32, 0.2), 0.202710, epsilon)); | |
| 87 | expect(math.approxEq(f32, tan_(f32, 0.8923), 1.240422, epsilon)); | |
| 88 | expect(math.approxEq(f32, tan_(f32, 1.5), 14.101420, epsilon)); | |
| 89 | expect(math.approxEq(f32, tan_(f32, 37.45), -0.254397, epsilon)); | |
| 90 | expect(math.approxEq(f32, tan_(f32, 89.123), 2.285852, epsilon)); | |
| 145 | 91 | } |
| 146 | 92 | |
| 147 | 93 | test "math.tan64" { |
| 148 | 94 | const epsilon = 0.000001; |
| 149 | 95 | |
| 150 | expect(math.approxEq(f64, tan64(0.0), 0.0, epsilon)); | |
| 151 | expect(math.approxEq(f64, tan64(0.2), 0.202710, epsilon)); | |
| 152 | expect(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon)); | |
| 153 | expect(math.approxEq(f64, tan64(1.5), 14.101420, epsilon)); | |
| 154 | expect(math.approxEq(f64, tan64(37.45), -0.254397, epsilon)); | |
| 155 | expect(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon)); | |
| 96 | expect(math.approxEq(f64, tan_(f64, 0.0), 0.0, epsilon)); | |
| 97 | expect(math.approxEq(f64, tan_(f64, 0.2), 0.202710, epsilon)); | |
| 98 | expect(math.approxEq(f64, tan_(f64, 0.8923), 1.240422, epsilon)); | |
| 99 | expect(math.approxEq(f64, tan_(f64, 1.5), 14.101420, epsilon)); | |
| 100 | expect(math.approxEq(f64, tan_(f64, 37.45), -0.254397, epsilon)); | |
| 101 | expect(math.approxEq(f64, tan_(f64, 89.123), 2.2858376, epsilon)); | |
| 156 | 102 | } |
| 157 | 103 | |
| 158 | 104 | test "math.tan32.special" { |
| 159 | expect(tan32(0.0) == 0.0); | |
| 160 | expect(tan32(-0.0) == -0.0); | |
| 161 | expect(math.isNan(tan32(math.inf(f32)))); | |
| 162 | expect(math.isNan(tan32(-math.inf(f32)))); | |
| 163 | expect(math.isNan(tan32(math.nan(f32)))); | |
| 105 | expect(tan_(f32, 0.0) == 0.0); | |
| 106 | expect(tan_(f32, -0.0) == -0.0); | |
| 107 | expect(math.isNan(tan_(f32, math.inf(f32)))); | |
| 108 | expect(math.isNan(tan_(f32, -math.inf(f32)))); | |
| 109 | expect(math.isNan(tan_(f32, math.nan(f32)))); | |
| 164 | 110 | } |
| 165 | 111 | |
| 166 | 112 | test "math.tan64.special" { |
| 167 | expect(tan64(0.0) == 0.0); | |
| 168 | expect(tan64(-0.0) == -0.0); | |
| 169 | expect(math.isNan(tan64(math.inf(f64)))); | |
| 170 | expect(math.isNan(tan64(-math.inf(f64)))); | |
| 171 | expect(math.isNan(tan64(math.nan(f64)))); | |
| 113 | expect(tan_(f64, 0.0) == 0.0); | |
| 114 | expect(tan_(f64, -0.0) == -0.0); | |
| 115 | expect(math.isNan(tan_(f64, math.inf(f64)))); | |
| 116 | expect(math.isNan(tan_(f64, -math.inf(f64)))); | |
| 117 | expect(math.isNan(tan_(f64, math.nan(f64)))); | |
| 172 | 118 | } |
std/math/tanh.zig+10-4| ... | ... | @@ -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) = +-0 | |
| 4 | // - sinh(+-inf) = +-1 | |
| 5 | // - sinh(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/tanhf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/tanh.c | |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | 8 | const std = @import("../std.zig"); |
| ... | ... | @@ -11,6 +11,12 @@ const expect = std.testing.expect; |
| 11 | 11 | const expo2 = @import("expo2.zig").expo2; |
| 12 | 12 | const maxInt = std.math.maxInt; |
| 13 | 13 | |
| 14 | /// Returns the hyperbolic tangent of x. | |
| 15 | /// | |
| 16 | /// Special Cases: | |
| 17 | /// - sinh(+-0) = +-0 | |
| 18 | /// - sinh(+-inf) = +-1 | |
| 19 | /// - sinh(nan) = nan | |
| 14 | 20 | pub fn tanh(x: var) @typeOf(x) { |
| 15 | 21 | const T = @typeOf(x); |
| 16 | 22 | return switch (T) { |
std/math/trunc.zig+10-4| ... | ... | @@ -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) = +-0 | |
| 4 | // - trunc(+-inf) = +-inf | |
| 5 | // - trunc(nan) = nan | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/truncf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/trunc.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("../std.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const expect = std.testing.expect; |
| 10 | 10 | const maxInt = std.math.maxInt; |
| 11 | 11 | |
| 12 | /// Returns the integer value of x. | |
| 13 | /// | |
| 14 | /// Special Cases: | |
| 15 | /// - trunc(+-0) = +-0 | |
| 16 | /// - trunc(+-inf) = +-inf | |
| 17 | /// - trunc(nan) = nan | |
| 12 | 18 | pub fn trunc(x: var) @typeOf(x) { |
| 13 | 19 | const T = @typeOf(x); |
| 14 | 20 | return switch (T) { |
std/mem.zig+23-29| ... | ... | @@ -34,39 +34,39 @@ pub const Allocator = struct { |
| 34 | 34 | /// The returned slice must have its pointer aligned at least to `new_alignment` bytes. |
| 35 | 35 | reallocFn: fn ( |
| 36 | 36 | self: *Allocator, |
| 37 | // Guaranteed to be the same as what was returned from most recent call to | |
| 38 | // `reallocFn` or `shrinkFn`. | |
| 39 | // If `old_mem.len == 0` then this is a new allocation and `new_byte_count` | |
| 40 | // is guaranteed to be >= 1. | |
| 37 | /// Guaranteed to be the same as what was returned from most recent call to | |
| 38 | /// `reallocFn` or `shrinkFn`. | |
| 39 | /// If `old_mem.len == 0` then this is a new allocation and `new_byte_count` | |
| 40 | /// is guaranteed to be >= 1. | |
| 41 | 41 | old_mem: []u8, |
| 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 to | |
| 44 | // `reallocFn` or `shrinkFn`. | |
| 45 | // Guaranteed to be >= 1. | |
| 46 | // Guaranteed to be a power of 2. | |
| 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 to | |
| 44 | /// `reallocFn` or `shrinkFn`. | |
| 45 | /// Guaranteed to be >= 1. | |
| 46 | /// Guaranteed to be a power of 2. | |
| 47 | 47 | old_alignment: u29, |
| 48 | // If `new_byte_count` is 0 then this is a free and it is guaranteed that | |
| 49 | // `old_mem.len != 0`. | |
| 48 | /// If `new_byte_count` is 0 then this is a free and it is guaranteed that | |
| 49 | /// `old_mem.len != 0`. | |
| 50 | 50 | new_byte_count: usize, |
| 51 | // Guaranteed to be >= 1. | |
| 52 | // Guaranteed to be a power of 2. | |
| 53 | // Returned slice's pointer must have this alignment. | |
| 51 | /// Guaranteed to be >= 1. | |
| 52 | /// Guaranteed to be a power of 2. | |
| 53 | /// Returned slice's pointer must have this alignment. | |
| 54 | 54 | new_alignment: u29, |
| 55 | 55 | ) Error![]u8, |
| 56 | 56 | |
| 57 | 57 | /// This function deallocates memory. It must succeed. |
| 58 | 58 | shrinkFn: fn ( |
| 59 | 59 | self: *Allocator, |
| 60 | // Guaranteed to be the same as what was returned from most recent call to | |
| 61 | // `reallocFn` or `shrinkFn`. | |
| 60 | /// Guaranteed to be the same as what was returned from most recent call to | |
| 61 | /// `reallocFn` or `shrinkFn`. | |
| 62 | 62 | old_mem: []u8, |
| 63 | // Guaranteed to be the same as what was returned from most recent call to | |
| 64 | // `reallocFn` or `shrinkFn`. | |
| 63 | /// Guaranteed to be the same as what was returned from most recent call to | |
| 64 | /// `reallocFn` or `shrinkFn`. | |
| 65 | 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 | 67 | new_byte_count: usize, |
| 68 | // If `new_byte_count == 0` then this is `undefined`, otherwise: | |
| 69 | // Guaranteed to be less than or equal to `old_alignment`. | |
| 68 | /// If `new_byte_count == 0` then this is `undefined`, otherwise: | |
| 69 | /// Guaranteed to be less than or equal to `old_alignment`. | |
| 70 | 70 | new_alignment: u29, |
| 71 | 71 | ) []u8, |
| 72 | 72 | |
| ... | ... | @@ -104,10 +104,7 @@ pub const Allocator = struct { |
| 104 | 104 | const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory; |
| 105 | 105 | const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, alignment); |
| 106 | 106 | assert(byte_slice.len == byte_count); |
| 107 | // This loop gets optimized out in ReleaseFast mode | |
| 108 | for (byte_slice) |*byte| { | |
| 109 | byte.* = undefined; | |
| 110 | } | |
| 107 | @memset(byte_slice.ptr, undefined, byte_slice.len); | |
| 111 | 108 | return @bytesToSlice(T, @alignCast(alignment, byte_slice)); |
| 112 | 109 | } |
| 113 | 110 | |
| ... | ... | @@ -153,10 +150,7 @@ pub const Allocator = struct { |
| 153 | 150 | const byte_slice = try self.reallocFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment); |
| 154 | 151 | assert(byte_slice.len == byte_count); |
| 155 | 152 | if (new_n > old_mem.len) { |
| 156 | // This loop gets optimized out in ReleaseFast mode | |
| 157 | for (byte_slice[old_byte_slice.len..]) |*byte| { | |
| 158 | byte.* = undefined; | |
| 159 | } | |
| 153 | @memset(byte_slice.ptr + old_byte_slice.len, undefined, byte_slice.len - old_byte_slice.len); | |
| 160 | 154 | } |
| 161 | 155 | return @bytesToSlice(T, @alignCast(new_alignment, byte_slice)); |
| 162 | 156 | } |
std/os.zig+104-14| ... | ... | @@ -23,6 +23,7 @@ test "std.os" { |
| 23 | 23 | _ = @import("os/time.zig"); |
| 24 | 24 | _ = @import("os/windows.zig"); |
| 25 | 25 | _ = @import("os/uefi.zig"); |
| 26 | _ = @import("os/wasi.zig"); | |
| 26 | 27 | _ = @import("os/get_app_data_dir.zig"); |
| 27 | 28 | } |
| 28 | 29 | |
| ... | ... | @@ -33,6 +34,7 @@ pub const freebsd = @import("os/freebsd.zig"); |
| 33 | 34 | pub const netbsd = @import("os/netbsd.zig"); |
| 34 | 35 | pub const zen = @import("os/zen.zig"); |
| 35 | 36 | pub const uefi = @import("os/uefi.zig"); |
| 37 | pub const wasi = @import("os/wasi.zig"); | |
| 36 | 38 | |
| 37 | 39 | pub const posix = switch (builtin.os) { |
| 38 | 40 | Os.linux => linux, |
| ... | ... | @@ -40,6 +42,7 @@ pub const posix = switch (builtin.os) { |
| 40 | 42 | Os.freebsd => freebsd, |
| 41 | 43 | Os.netbsd => netbsd, |
| 42 | 44 | Os.zen => zen, |
| 45 | Os.wasi => wasi, | |
| 43 | 46 | else => @compileError("Unsupported OS"), |
| 44 | 47 | }; |
| 45 | 48 | |
| ... | ... | @@ -50,7 +53,11 @@ pub const path = @import("os/path.zig"); |
| 50 | 53 | pub const File = @import("os/file.zig").File; |
| 51 | 54 | pub const time = @import("os/time.zig"); |
| 52 | 55 | |
| 53 | pub const page_size = 4 * 1024; | |
| 56 | pub const page_size = switch (builtin.arch) { | |
| 57 | .wasm32, .wasm64 => 64 * 1024, | |
| 58 | else => 4 * 1024, | |
| 59 | }; | |
| 60 | ||
| 54 | 61 | pub const MAX_PATH_BYTES = switch (builtin.os) { |
| 55 | 62 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => posix.PATH_MAX, |
| 56 | 63 | // Each UTF-16LE character may be expanded to 3 UTF-8 bytes. |
| ... | ... | @@ -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 | 155 | Os.zen => { |
| 143 | 156 | const randomness = []u8{ 42, 1, 7, 12, 22, 17, 99, 16, 26, 87, 41, 45 }; |
| 144 | 157 | var i: usize = 0; |
| ... | ... | @@ -198,6 +211,12 @@ pub fn abort() noreturn { |
| 198 | 211 | } |
| 199 | 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 | 220 | Os.uefi => { |
| 202 | 221 | // TODO there's gotta be a better thing to do here than loop forever |
| 203 | 222 | while (true) {} |
| ... | ... | @@ -226,6 +245,9 @@ pub fn exit(status: u8) noreturn { |
| 226 | 245 | Os.windows => { |
| 227 | 246 | windows.ExitProcess(status); |
| 228 | 247 | }, |
| 248 | Os.wasi => { | |
| 249 | wasi.proc_exit(status); | |
| 250 | }, | |
| 229 | 251 | else => @compileError("Unsupported OS"), |
| 230 | 252 | } |
| 231 | 253 | } |
| ... | ... | @@ -749,6 +771,37 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 749 | 771 | |
| 750 | 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 | 805 | } else { |
| 753 | 806 | for (posix_environ_raw) |ptr| { |
| 754 | 807 | var line_i: usize = 0; |
| ... | ... | @@ -1083,13 +1136,14 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void { |
| 1083 | 1136 | defer in_file.close(); |
| 1084 | 1137 | |
| 1085 | 1138 | const mode = try in_file.mode(); |
| 1139 | const in_stream = &in_file.inStream().stream; | |
| 1086 | 1140 | |
| 1087 | 1141 | var atomic_file = try AtomicFile.init(dest_path, mode); |
| 1088 | 1142 | defer atomic_file.deinit(); |
| 1089 | 1143 | |
| 1090 | 1144 | var buf: [page_size]u8 = undefined; |
| 1091 | 1145 | while (true) { |
| 1092 | const amt = try in_file.readFull(buf[0..]); | |
| 1146 | const amt = try in_stream.readFull(buf[0..]); | |
| 1093 | 1147 | try atomic_file.file.write(buf[0..amt]); |
| 1094 | 1148 | if (amt != buf.len) { |
| 1095 | 1149 | return atomic_file.finish(); |
| ... | ... | @@ -2127,6 +2181,11 @@ pub const ArgIterator = struct { |
| 2127 | 2181 | inner: InnerType, |
| 2128 | 2182 | |
| 2129 | 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 | 2189 | return ArgIterator{ .inner = InnerType.init() }; |
| 2131 | 2190 | } |
| 2132 | 2191 | |
| ... | ... | @@ -2159,6 +2218,34 @@ pub fn args() ArgIterator { |
| 2159 | 2218 | |
| 2160 | 2219 | /// Caller must call argsFree on result. |
| 2161 | 2220 | pub 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 | 2249 | // TODO refactor to only make 1 allocation. |
| 2163 | 2250 | var it = args(); |
| 2164 | 2251 | var contents = try Buffer.initSize(allocator, 0); |
| ... | ... | @@ -2196,6 +2283,16 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { |
| 2196 | 2283 | } |
| 2197 | 2284 | |
| 2198 | 2285 | pub 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 | 2296 | var total_bytes: usize = 0; |
| 2200 | 2297 | for (args_alloc) |arg| { |
| 2201 | 2298 | total_bytes += @sizeOf([]u8) + arg.len; |
| ... | ... | @@ -3030,9 +3127,6 @@ pub const SpawnThreadError = error{ |
| 3030 | 3127 | Unexpected, |
| 3031 | 3128 | }; |
| 3032 | 3129 | |
| 3033 | pub var linux_tls_phdr: ?*std.elf.Phdr = null; | |
| 3034 | pub var linux_tls_img_src: [*]const u8 = undefined; // defined if linux_tls_phdr is | |
| 3035 | ||
| 3036 | 3130 | /// caller must call wait on the returned thread |
| 3037 | 3131 | /// fn startFn(@typeOf(context)) T |
| 3038 | 3132 | /// where T is u8, noreturn, void, or !void |
| ... | ... | @@ -3142,12 +3236,10 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread |
| 3142 | 3236 | } |
| 3143 | 3237 | // Finally, the Thread Local Storage, if any. |
| 3144 | 3238 | if (!Thread.use_pthreads) { |
| 3145 | if (linux_tls_phdr) |tls_phdr| { | |
| 3146 | l = mem.alignForward(l, tls_phdr.p_align); | |
| 3239 | if (linux.tls.tls_image) |tls_img| { | |
| 3240 | l = mem.alignForward(l, @alignOf(usize)); | |
| 3147 | 3241 | tls_start_offset = l; |
| 3148 | l += tls_phdr.p_memsz; | |
| 3149 | // the fs register address | |
| 3150 | l += @sizeOf(usize); | |
| 3242 | l += tls_img.alloc_size; | |
| 3151 | 3243 | } |
| 3152 | 3244 | } |
| 3153 | 3245 | break :blk l; |
| ... | ... | @@ -3188,10 +3280,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread |
| 3188 | 3280 | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | |
| 3189 | 3281 | posix.CLONE_DETACHED; |
| 3190 | 3282 | var newtls: usize = undefined; |
| 3191 | if (linux_tls_phdr) |tls_phdr| { | |
| 3192 | @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz); | |
| 3193 | newtls = mmap_addr + mmap_len - @sizeOf(usize); | |
| 3194 | @intToPtr(*usize, newtls).* = newtls; | |
| 3283 | if (linux.tls.tls_image) |tls_img| { | |
| 3284 | newtls = linux.tls.copyTLS(mmap_addr + tls_start_offset); | |
| 3195 | 3285 | flags |= posix.CLONE_SETTLS; |
| 3196 | 3286 | } |
| 3197 | 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 | 812 | .sa_mask = act.mask, |
| 813 | 813 | }; |
| 814 | 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 | 816 | if (result != 0) { |
| 817 | 817 | return result; |
| 818 | 818 | } |
std/os/file.zig+12-16| ... | ... | @@ -235,7 +235,7 @@ pub const File = struct { |
| 235 | 235 | Unexpected, |
| 236 | 236 | }; |
| 237 | 237 | |
| 238 | pub fn seekForward(self: File, amount: isize) SeekError!void { | |
| 238 | pub fn seekForward(self: File, amount: i64) SeekError!void { | |
| 239 | 239 | switch (builtin.os) { |
| 240 | 240 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { |
| 241 | 241 | const result = posix.lseek(self.handle, amount, posix.SEEK_CUR); |
| ... | ... | @@ -266,7 +266,7 @@ pub const File = struct { |
| 266 | 266 | } |
| 267 | 267 | } |
| 268 | 268 | |
| 269 | pub fn seekTo(self: File, pos: usize) SeekError!void { | |
| 269 | pub fn seekTo(self: File, pos: u64) SeekError!void { | |
| 270 | 270 | switch (builtin.os) { |
| 271 | 271 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { |
| 272 | 272 | const ipos = try math.cast(isize, pos); |
| ... | ... | @@ -301,13 +301,12 @@ pub const File = struct { |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | 303 | pub const GetSeekPosError = error{ |
| 304 | Overflow, | |
| 305 | 304 | SystemResources, |
| 306 | 305 | Unseekable, |
| 307 | 306 | Unexpected, |
| 308 | 307 | }; |
| 309 | 308 | |
| 310 | pub fn getPos(self: File) GetSeekPosError!usize { | |
| 309 | pub fn getPos(self: File) GetSeekPosError!u64 { | |
| 311 | 310 | switch (builtin.os) { |
| 312 | 311 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { |
| 313 | 312 | const result = posix.lseek(self.handle, 0, posix.SEEK_CUR); |
| ... | ... | @@ -324,7 +323,7 @@ pub const File = struct { |
| 324 | 323 | else => os.unexpectedErrorPosix(err), |
| 325 | 324 | }; |
| 326 | 325 | } |
| 327 | return result; | |
| 326 | return u64(result); | |
| 328 | 327 | }, |
| 329 | 328 | Os.windows => { |
| 330 | 329 | var pos: windows.LARGE_INTEGER = undefined; |
| ... | ... | @@ -336,17 +335,16 @@ pub const File = struct { |
| 336 | 335 | }; |
| 337 | 336 | } |
| 338 | 337 | |
| 339 | assert(pos >= 0); | |
| 340 | return math.cast(usize, pos); | |
| 338 | return @intCast(u64, pos); | |
| 341 | 339 | }, |
| 342 | 340 | else => @compileError("unsupported OS"), |
| 343 | 341 | } |
| 344 | 342 | } |
| 345 | 343 | |
| 346 | pub fn getEndPos(self: File) GetSeekPosError!usize { | |
| 344 | pub fn getEndPos(self: File) GetSeekPosError!u64 { | |
| 347 | 345 | if (is_posix) { |
| 348 | 346 | const stat = try os.posixFStat(self.handle); |
| 349 | return @intCast(usize, stat.size); | |
| 347 | return @intCast(u64, stat.size); | |
| 350 | 348 | } else if (is_windows) { |
| 351 | 349 | var file_size: windows.LARGE_INTEGER = undefined; |
| 352 | 350 | if (windows.GetFileSizeEx(self.handle, &file_size) == 0) { |
| ... | ... | @@ -355,9 +353,7 @@ pub const File = struct { |
| 355 | 353 | else => os.unexpectedErrorWindows(err), |
| 356 | 354 | }; |
| 357 | 355 | } |
| 358 | if (file_size < 0) | |
| 359 | return error.Overflow; | |
| 360 | return math.cast(usize, @intCast(u64, file_size)); | |
| 356 | return @intCast(u64, file_size); | |
| 361 | 357 | } else { |
| 362 | 358 | @compileError("TODO support getEndPos on this OS"); |
| 363 | 359 | } |
| ... | ... | @@ -492,22 +488,22 @@ pub const File = struct { |
| 492 | 488 | |
| 493 | 489 | pub const Stream = io.SeekableStream(SeekError, GetSeekPosError); |
| 494 | 490 | |
| 495 | pub fn seekToFn(seekable_stream: *Stream, pos: usize) SeekError!void { | |
| 491 | pub fn seekToFn(seekable_stream: *Stream, pos: u64) SeekError!void { | |
| 496 | 492 | const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream); |
| 497 | 493 | return self.file.seekTo(pos); |
| 498 | 494 | } |
| 499 | 495 | |
| 500 | pub fn seekForwardFn(seekable_stream: *Stream, amt: isize) SeekError!void { | |
| 496 | pub fn seekForwardFn(seekable_stream: *Stream, amt: i64) SeekError!void { | |
| 501 | 497 | const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream); |
| 502 | 498 | return self.file.seekForward(amt); |
| 503 | 499 | } |
| 504 | 500 | |
| 505 | pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!usize { | |
| 501 | pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!u64 { | |
| 506 | 502 | const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream); |
| 507 | 503 | return self.file.getEndPos(); |
| 508 | 504 | } |
| 509 | 505 | |
| 510 | pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!usize { | |
| 506 | pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!u64 { | |
| 511 | 507 | const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream); |
| 512 | 508 | return self.file.getPos(); |
| 513 | 509 | } |
std/os/linux.zig+150-16| ... | ... | @@ -2,7 +2,10 @@ const std = @import("../std.zig"); |
| 2 | 2 | const assert = std.debug.assert; |
| 3 | 3 | const builtin = @import("builtin"); |
| 4 | 4 | const maxInt = std.math.maxInt; |
| 5 | const elf = std.elf; | |
| 6 | pub const tls = @import("linux/tls.zig"); | |
| 5 | 7 | const vdso = @import("linux/vdso.zig"); |
| 8 | const dl = @import("../dynamic_library.zig"); | |
| 6 | 9 | pub use switch (builtin.arch) { |
| 7 | 10 | builtin.Arch.x86_64 => @import("linux/x86_64.zig"), |
| 8 | 11 | builtin.Arch.i386 => @import("linux/i386.zig"), |
| ... | ... | @@ -12,6 +15,7 @@ pub use switch (builtin.arch) { |
| 12 | 15 | pub use @import("linux/errno.zig"); |
| 13 | 16 | |
| 14 | 17 | pub const PATH_MAX = 4096; |
| 18 | pub const IOV_MAX = 1024; | |
| 15 | 19 | |
| 16 | 20 | pub const STDIN_FILENO = 0; |
| 17 | 21 | pub const STDOUT_FILENO = 1; |
| ... | ... | @@ -955,10 +959,13 @@ pub fn waitpid(pid: i32, status: *i32, options: i32) usize { |
| 955 | 959 | return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0); |
| 956 | 960 | } |
| 957 | 961 | |
| 962 | var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime); | |
| 963 | ||
| 958 | 964 | pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { |
| 959 | 965 | if (VDSO_CGT_SYM.len != 0) { |
| 960 | const f = @atomicLoad(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, builtin.AtomicOrder.Unordered); | |
| 961 | if (@ptrToInt(f) != 0) { | |
| 966 | const ptr = @atomicLoad(?*const c_void, &vdso_clock_gettime, .Unordered); | |
| 967 | if (ptr) |fn_ptr| { | |
| 968 | const f = @ptrCast(@typeOf(clock_gettime), fn_ptr); | |
| 962 | 969 | const rc = f(clk_id, tp); |
| 963 | 970 | switch (rc) { |
| 964 | 971 | 0, @bitCast(usize, isize(-EINVAL)) => return rc, |
| ... | ... | @@ -968,13 +975,18 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { |
| 968 | 975 | } |
| 969 | 976 | return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp)); |
| 970 | 977 | } |
| 971 | var vdso_clock_gettime = init_vdso_clock_gettime; | |
| 978 | ||
| 972 | 979 | extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize { |
| 973 | const addr = vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM); | |
| 974 | var f = @intToPtr(@typeOf(init_vdso_clock_gettime), addr); | |
| 975 | _ = @cmpxchgStrong(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, init_vdso_clock_gettime, f, builtin.AtomicOrder.Monotonic, builtin.AtomicOrder.Monotonic); | |
| 976 | if (@ptrToInt(f) == 0) return @bitCast(usize, isize(-ENOSYS)); | |
| 977 | return f(clk, ts); | |
| 980 | const ptr = @intToPtr(?*const c_void, vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM)); | |
| 981 | // Note that we may not have a VDSO at all, update the stub address anyway | |
| 982 | // so that clock_gettime will fall back on the good old (and slow) syscall | |
| 983 | _ = @cmpxchgStrong(?*const c_void, &vdso_clock_gettime, &init_vdso_clock_gettime, ptr, .Monotonic, .Monotonic); | |
| 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 | } |
| 979 | 991 | |
| 980 | 992 | pub fn clock_getres(clk_id: i32, tp: *timespec) usize { |
| ... | ... | @@ -1100,8 +1112,8 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti |
| 1100 | 1112 | |
| 1101 | 1113 | const NSIG = 65; |
| 1102 | 1114 | const sigset_t = [128 / @sizeOf(usize)]usize; |
| 1103 | const all_mask = []usize{maxInt(usize)}; | |
| 1104 | const app_mask = []usize{0xfffffffc7fffffff}; | |
| 1115 | const all_mask = []u32{ 0xffffffff, 0xffffffff }; | |
| 1116 | const app_mask = []u32{ 0xfffffffc, 0x7fffffff }; | |
| 1105 | 1117 | |
| 1106 | 1118 | const k_sigaction = extern struct { |
| 1107 | 1119 | handler: extern fn (i32) void, |
| ... | ... | @@ -1193,6 +1205,16 @@ pub const iovec_const = extern struct { |
| 1193 | 1205 | iov_len: usize, |
| 1194 | 1206 | }; |
| 1195 | 1207 | |
| 1208 | pub const mmsghdr = extern struct { | |
| 1209 | msg_hdr: msghdr, | |
| 1210 | msg_len: u32, | |
| 1211 | }; | |
| 1212 | ||
| 1213 | pub const mmsghdr_const = extern struct { | |
| 1214 | msg_hdr: msghdr_const, | |
| 1215 | msg_len: u32, | |
| 1216 | }; | |
| 1217 | ||
| 1196 | 1218 | pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { |
| 1197 | 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 | 1235 | return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); |
| 1214 | 1236 | } |
| 1215 | 1237 | |
| 1216 | pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize { | |
| 1238 | pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize { | |
| 1217 | 1239 | return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); |
| 1218 | 1240 | } |
| 1219 | 1241 | |
| 1242 | pub 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 | ||
| 1220 | 1282 | pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize { |
| 1221 | 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 | 1401 | return syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), set.len * @sizeOf(usize), @ptrToInt(set.ptr)); |
| 1340 | 1402 | } |
| 1341 | 1403 | |
| 1342 | pub const epoll_data = packed union { | |
| 1404 | pub const epoll_data = extern union { | |
| 1343 | 1405 | ptr: usize, |
| 1344 | 1406 | fd: i32, |
| 1345 | 1407 | @"u32": u32, |
| 1346 | 1408 | @"u64": u64, |
| 1347 | 1409 | }; |
| 1348 | 1410 | |
| 1349 | pub const epoll_event = packed struct { | |
| 1350 | events: u32, | |
| 1351 | data: epoll_data, | |
| 1352 | }; | |
| 1411 | // On x86_64 the structure is packed so that it matches the definition of its | |
| 1412 | // 32bit counterpart | |
| 1413 | pub const epoll_event = if (builtin.arch != .x86_64) | |
| 1414 | extern struct { | |
| 1415 | events: u32, | |
| 1416 | data: epoll_data, | |
| 1417 | } | |
| 1418 | else | |
| 1419 | packed struct { | |
| 1420 | events: u32, | |
| 1421 | data: epoll_data, | |
| 1422 | }; | |
| 1353 | 1423 | |
| 1354 | 1424 | pub fn epoll_create() usize { |
| 1355 | 1425 | return epoll_create1(0); |
| ... | ... | @@ -1534,6 +1604,70 @@ pub const dirent64 = extern struct { |
| 1534 | 1604 | d_name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173 |
| 1535 | 1605 | }; |
| 1536 | 1606 | |
| 1607 | pub 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 | |
| 1615 | extern const __ehdr_start: elf.Ehdr = undefined; | |
| 1616 | ||
| 1617 | pub 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 | ||
| 1537 | 1671 | test "import" { |
| 1538 | 1672 | if (builtin.os == builtin.Os.linux) { |
| 1539 | 1673 | _ = @import("linux/test.zig"); |
std/os/linux/arm64.zig+16-3| ... | ... | @@ -2,6 +2,7 @@ const std = @import("../../std.zig"); |
| 2 | 2 | const linux = std.os.linux; |
| 3 | 3 | const socklen_t = linux.socklen_t; |
| 4 | 4 | const iovec = linux.iovec; |
| 5 | const iovec_const = linux.iovec_const; | |
| 5 | 6 | |
| 6 | 7 | pub const SYS_io_setup = 0; |
| 7 | 8 | pub const SYS_io_destroy = 1; |
| ... | ... | @@ -415,12 +416,24 @@ pub fn syscall6( |
| 415 | 416 | pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; |
| 416 | 417 | |
| 417 | 418 | pub const msghdr = extern struct { |
| 418 | msg_name: *u8, | |
| 419 | msg_name: ?*sockaddr, | |
| 419 | 420 | msg_namelen: socklen_t, |
| 420 | msg_iov: *iovec, | |
| 421 | msg_iov: [*]iovec, | |
| 421 | 422 | msg_iovlen: i32, |
| 422 | 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 | ||
| 430 | pub 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 | 437 | msg_controllen: socklen_t, |
| 425 | 438 | __pad2: socklen_t, |
| 426 | 439 | msg_flags: i32, |
std/os/linux/test.zig+41| ... | ... | @@ -1,6 +1,8 @@ |
| 1 | 1 | const std = @import("../../std.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const linux = std.os.linux; |
| 4 | const mem = std.mem; | |
| 5 | const elf = std.elf; | |
| 4 | 6 | const expect = std.testing.expect; |
| 5 | 7 | |
| 6 | 8 | test "getpid" { |
| ... | ... | @@ -42,3 +44,42 @@ test "timer" { |
| 42 | 44 | // TODO implicit cast from *[N]T to [*]T |
| 43 | 45 | err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1); |
| 44 | 46 | } |
| 47 | ||
| 48 | export 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 | ||
| 81 | test "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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const mem = std.mem; | |
| 3 | const posix = std.os.posix; | |
| 4 | const elf = std.elf; | |
| 5 | const builtin = @import("builtin"); | |
| 6 | const 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 | ||
| 44 | const TLSVariant = enum { | |
| 45 | VariantI, | |
| 46 | VariantII, | |
| 47 | }; | |
| 48 | ||
| 49 | const 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 | |
| 56 | const 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 | |
| 65 | const 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 | |
| 71 | comptime { | |
| 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 | ||
| 80 | const tls_tp_offset = switch (builtin.arch) { | |
| 81 | else => 0, | |
| 82 | }; | |
| 83 | ||
| 84 | const tls_dtv_offset = switch (builtin.arch) { | |
| 85 | else => 0, | |
| 86 | }; | |
| 87 | ||
| 88 | // Per-thread storage for Zig's use | |
| 89 | const CustomData = packed struct { | |
| 90 | }; | |
| 91 | ||
| 92 | // Dynamic Thread Vector | |
| 93 | const DTV = packed struct { | |
| 94 | entries: usize, | |
| 95 | tls_block: [1]usize, | |
| 96 | }; | |
| 97 | ||
| 98 | // Holds all the information about the process TLS image | |
| 99 | const TLSImage = struct { | |
| 100 | data_src: []u8, | |
| 101 | alloc_size: usize, | |
| 102 | tcb_offset: usize, | |
| 103 | dtv_offset: usize, | |
| 104 | data_offset: usize, | |
| 105 | }; | |
| 106 | ||
| 107 | pub var tls_image: ?TLSImage = null; | |
| 108 | ||
| 109 | pub 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 | ||
| 126 | pub 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 | ||
| 210 | pub 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 | ||
| 233 | var main_thread_tls_buffer: [256]u8 align(32) = undefined; | |
| 234 | ||
| 235 | pub 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 | 1 | const std = @import("../../std.zig"); |
| 2 | 2 | const linux = std.os.linux; |
| 3 | const sockaddr = linux.sockaddr; | |
| 3 | 4 | const socklen_t = linux.socklen_t; |
| 4 | 5 | const iovec = linux.iovec; |
| 6 | const iovec_const = linux.iovec_const; | |
| 5 | 7 | |
| 6 | 8 | pub const SYS_read = 0; |
| 7 | 9 | pub const SYS_write = 1; |
| ... | ... | @@ -386,6 +388,11 @@ pub const VDSO_CGT_VER = "LINUX_2.6"; |
| 386 | 388 | pub const VDSO_GETCPU_SYM = "__vdso_getcpu"; |
| 387 | 389 | pub const VDSO_GETCPU_VER = "LINUX_2.6"; |
| 388 | 390 | |
| 391 | pub const ARCH_SET_GS = 0x1001; | |
| 392 | pub const ARCH_SET_FS = 0x1002; | |
| 393 | pub const ARCH_GET_FS = 0x1003; | |
| 394 | pub const ARCH_GET_GS = 0x1004; | |
| 395 | ||
| 389 | 396 | pub fn syscall0(number: usize) usize { |
| 390 | 397 | return asm volatile ("syscall" |
| 391 | 398 | : [ret] "={rax}" (-> usize) |
| ... | ... | @@ -483,12 +490,24 @@ pub nakedcc fn restore_rt() void { |
| 483 | 490 | } |
| 484 | 491 | |
| 485 | 492 | pub 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 | ||
| 504 | pub const msghdr_const = extern struct { | |
| 505 | msg_name: ?*const sockaddr, | |
| 487 | 506 | msg_namelen: socklen_t, |
| 488 | msg_iov: *iovec, | |
| 507 | msg_iov: [*]iovec_const, | |
| 489 | 508 | msg_iovlen: i32, |
| 490 | 509 | __pad1: i32, |
| 491 | msg_control: *u8, | |
| 510 | msg_control: ?*c_void, | |
| 492 | 511 | msg_controllen: socklen_t, |
| 493 | 512 | __pad2: socklen_t, |
| 494 | 513 | msg_flags: i32, |
std/os/time.zig+23-7| ... | ... | @@ -3,41 +3,44 @@ const builtin = @import("builtin"); |
| 3 | 3 | const Os = builtin.Os; |
| 4 | 4 | const debug = std.debug; |
| 5 | 5 | const testing = std.testing; |
| 6 | const math = std.math; | |
| 6 | 7 | |
| 7 | 8 | const windows = std.os.windows; |
| 8 | 9 | const linux = std.os.linux; |
| 9 | 10 | const darwin = std.os.darwin; |
| 11 | const wasi = std.os.wasi; | |
| 10 | 12 | const posix = std.os.posix; |
| 11 | 13 | |
| 12 | 14 | pub const epoch = @import("epoch.zig"); |
| 13 | 15 | |
| 14 | /// Sleep for the specified duration | |
| 16 | /// Spurious wakeups are possible and no precision of timing is guaranteed. | |
| 15 | 17 | pub fn sleep(nanoseconds: u64) void { |
| 16 | 18 | switch (builtin.os) { |
| 17 | 19 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { |
| 18 | 20 | const s = nanoseconds / ns_per_s; |
| 19 | 21 | const ns = nanoseconds % ns_per_s; |
| 20 | posixSleep(@intCast(u63, s), @intCast(u63, ns)); | |
| 22 | posixSleep(s, ns); | |
| 21 | 23 | }, |
| 22 | 24 | Os.windows => { |
| 23 | 25 | const ns_per_ms = ns_per_s / ms_per_s; |
| 24 | 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 | 30 | else => @compileError("Unsupported OS"), |
| 28 | 31 | } |
| 29 | 32 | } |
| 30 | 33 | |
| 31 | pub fn posixSleep(seconds: u63, nanoseconds: u63) void { | |
| 34 | /// Spurious wakeups are possible and no precision of timing is guaranteed. | |
| 35 | pub fn posixSleep(seconds: u64, nanoseconds: u64) void { | |
| 32 | 36 | var req = posix.timespec{ |
| 33 | .tv_sec = seconds, | |
| 34 | .tv_nsec = nanoseconds, | |
| 37 | .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize), | |
| 38 | .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize), | |
| 35 | 39 | }; |
| 36 | 40 | var rem: posix.timespec = undefined; |
| 37 | 41 | while (true) { |
| 38 | 42 | const ret_val = posix.nanosleep(&req, &rem); |
| 39 | 43 | const err = posix.getErrno(ret_val); |
| 40 | if (err == 0) return; | |
| 41 | 44 | switch (err) { |
| 42 | 45 | posix.EFAULT => unreachable, |
| 43 | 46 | posix.EINVAL => { |
| ... | ... | @@ -49,6 +52,7 @@ pub fn posixSleep(seconds: u63, nanoseconds: u63) void { |
| 49 | 52 | req = rem; |
| 50 | 53 | continue; |
| 51 | 54 | }, |
| 55 | // This prong handles success as well as unexpected errors. | |
| 52 | 56 | else => return, |
| 53 | 57 | } |
| 54 | 58 | } |
| ... | ... | @@ -64,9 +68,21 @@ pub const milliTimestamp = switch (builtin.os) { |
| 64 | 68 | Os.windows => milliTimestampWindows, |
| 65 | 69 | Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix, |
| 66 | 70 | Os.macosx, Os.ios => milliTimestampDarwin, |
| 71 | Os.wasi => milliTimestampWasi, | |
| 67 | 72 | else => @compileError("Unsupported OS"), |
| 68 | 73 | }; |
| 69 | 74 | |
| 75 | fn 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 | ||
| 70 | 86 | fn milliTimestampWindows() u64 { |
| 71 | 87 | //FileTime has a granularity of 100 nanoseconds |
| 72 | 88 | // and uses the NTFS/Windows epoch |
std/os/wasi.zig created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | pub use @import("wasi/core.zig"); | |
| 2 | ||
| 3 | pub const STDIN_FILENO = 0; | |
| 4 | pub const STDOUT_FILENO = 1; | |
| 5 | pub const STDERR_FILENO = 2; | |
| 6 | ||
| 7 | pub 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 | ||
| 12 | pub 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 | ||
| 28 | pub 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 | ||
| 4 | pub const advice_t = u8; | |
| 5 | pub const ADVICE_NORMAL: advice_t = 0; | |
| 6 | pub const ADVICE_SEQUENTIAL: advice_t = 1; | |
| 7 | pub const ADVICE_RANDOM: advice_t = 2; | |
| 8 | pub const ADVICE_WILLNEED: advice_t = 3; | |
| 9 | pub const ADVICE_DONTNEED: advice_t = 4; | |
| 10 | pub const ADVICE_NOREUSE: advice_t = 5; | |
| 11 | ||
| 12 | pub const ciovec_t = extern struct { | |
| 13 | buf: [*]const u8, | |
| 14 | buf_len: usize, | |
| 15 | }; | |
| 16 | ||
| 17 | pub const clockid_t = u32; | |
| 18 | pub const CLOCK_REALTIME: clockid_t = 0; | |
| 19 | pub const CLOCK_MONOTONIC: clockid_t = 1; | |
| 20 | pub const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2; | |
| 21 | pub const CLOCK_THREAD_CPUTIME_ID: clockid_t = 3; | |
| 22 | ||
| 23 | pub const device_t = u64; | |
| 24 | ||
| 25 | pub const dircookie_t = u64; | |
| 26 | pub const DIRCOOKIE_START: dircookie_t = 0; | |
| 27 | ||
| 28 | pub 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 | ||
| 35 | pub const errno_t = u16; | |
| 36 | pub const ESUCCESS: errno_t = 0; | |
| 37 | pub const E2BIG: errno_t = 1; | |
| 38 | pub const EACCES: errno_t = 2; | |
| 39 | pub const EADDRINUSE: errno_t = 3; | |
| 40 | pub const EADDRNOTAVAIL: errno_t = 4; | |
| 41 | pub const EAFNOSUPPORT: errno_t = 5; | |
| 42 | pub const EAGAIN: errno_t = 6; | |
| 43 | pub const EALREADY: errno_t = 7; | |
| 44 | pub const EBADF: errno_t = 8; | |
| 45 | pub const EBADMSG: errno_t = 9; | |
| 46 | pub const EBUSY: errno_t = 10; | |
| 47 | pub const ECANCELED: errno_t = 11; | |
| 48 | pub const ECHILD: errno_t = 12; | |
| 49 | pub const ECONNABORTED: errno_t = 13; | |
| 50 | pub const ECONNREFUSED: errno_t = 14; | |
| 51 | pub const ECONNRESET: errno_t = 15; | |
| 52 | pub const EDEADLK: errno_t = 16; | |
| 53 | pub const EDESTADDRREQ: errno_t = 17; | |
| 54 | pub const EDOM: errno_t = 18; | |
| 55 | pub const EDQUOT: errno_t = 19; | |
| 56 | pub const EEXIST: errno_t = 20; | |
| 57 | pub const EFAULT: errno_t = 21; | |
| 58 | pub const EFBIG: errno_t = 22; | |
| 59 | pub const EHOSTUNREACH: errno_t = 23; | |
| 60 | pub const EIDRM: errno_t = 24; | |
| 61 | pub const EILSEQ: errno_t = 25; | |
| 62 | pub const EINPROGRESS: errno_t = 26; | |
| 63 | pub const EINTR: errno_t = 27; | |
| 64 | pub const EINVAL: errno_t = 28; | |
| 65 | pub const EIO: errno_t = 29; | |
| 66 | pub const EISCONN: errno_t = 30; | |
| 67 | pub const EISDIR: errno_t = 31; | |
| 68 | pub const ELOOP: errno_t = 32; | |
| 69 | pub const EMFILE: errno_t = 33; | |
| 70 | pub const EMLINK: errno_t = 34; | |
| 71 | pub const EMSGSIZE: errno_t = 35; | |
| 72 | pub const EMULTIHOP: errno_t = 36; | |
| 73 | pub const ENAMETOOLONG: errno_t = 37; | |
| 74 | pub const ENETDOWN: errno_t = 38; | |
| 75 | pub const ENETRESET: errno_t = 39; | |
| 76 | pub const ENETUNREACH: errno_t = 40; | |
| 77 | pub const ENFILE: errno_t = 41; | |
| 78 | pub const ENOBUFS: errno_t = 42; | |
| 79 | pub const ENODEV: errno_t = 43; | |
| 80 | pub const ENOENT: errno_t = 44; | |
| 81 | pub const ENOEXEC: errno_t = 45; | |
| 82 | pub const ENOLCK: errno_t = 46; | |
| 83 | pub const ENOLINK: errno_t = 47; | |
| 84 | pub const ENOMEM: errno_t = 48; | |
| 85 | pub const ENOMSG: errno_t = 49; | |
| 86 | pub const ENOPROTOOPT: errno_t = 50; | |
| 87 | pub const ENOSPC: errno_t = 51; | |
| 88 | pub const ENOSYS: errno_t = 52; | |
| 89 | pub const ENOTCONN: errno_t = 53; | |
| 90 | pub const ENOTDIR: errno_t = 54; | |
| 91 | pub const ENOTEMPTY: errno_t = 55; | |
| 92 | pub const ENOTRECOVERABLE: errno_t = 56; | |
| 93 | pub const ENOTSOCK: errno_t = 57; | |
| 94 | pub const ENOTSUP: errno_t = 58; | |
| 95 | pub const ENOTTY: errno_t = 59; | |
| 96 | pub const ENXIO: errno_t = 60; | |
| 97 | pub const EOVERFLOW: errno_t = 61; | |
| 98 | pub const EOWNERDEAD: errno_t = 62; | |
| 99 | pub const EPERM: errno_t = 63; | |
| 100 | pub const EPIPE: errno_t = 64; | |
| 101 | pub const EPROTO: errno_t = 65; | |
| 102 | pub const EPROTONOSUPPORT: errno_t = 66; | |
| 103 | pub const EPROTOTYPE: errno_t = 67; | |
| 104 | pub const ERANGE: errno_t = 68; | |
| 105 | pub const EROFS: errno_t = 69; | |
| 106 | pub const ESPIPE: errno_t = 70; | |
| 107 | pub const ESRCH: errno_t = 71; | |
| 108 | pub const ESTALE: errno_t = 72; | |
| 109 | pub const ETIMEDOUT: errno_t = 73; | |
| 110 | pub const ETXTBSY: errno_t = 74; | |
| 111 | pub const EXDEV: errno_t = 75; | |
| 112 | pub const ENOTCAPABLE: errno_t = 76; | |
| 113 | ||
| 114 | pub 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 | ||
| 126 | pub const eventrwflags_t = u16; | |
| 127 | pub const EVENT_FD_READWRITE_HANGUP: eventrwflags_t = 0x0001; | |
| 128 | ||
| 129 | pub const eventtype_t = u8; | |
| 130 | pub const EVENTTYPE_CLOCK: eventtype_t = 0; | |
| 131 | pub const EVENTTYPE_FD_READ: eventtype_t = 1; | |
| 132 | pub const EVENTTYPE_FD_WRITE: eventtype_t = 2; | |
| 133 | ||
| 134 | pub const exitcode_t = u32; | |
| 135 | ||
| 136 | pub const fd_t = u32; | |
| 137 | ||
| 138 | pub const fdflags_t = u16; | |
| 139 | pub const FDFLAG_APPEND: fdflags_t = 0x0001; | |
| 140 | pub const FDFLAG_DSYNC: fdflags_t = 0x0002; | |
| 141 | pub const FDFLAG_NONBLOCK: fdflags_t = 0x0004; | |
| 142 | pub const FDFLAG_RSYNC: fdflags_t = 0x0008; | |
| 143 | pub const FDFLAG_SYNC: fdflags_t = 0x0010; | |
| 144 | ||
| 145 | const 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 | ||
| 152 | pub const filedelta_t = i64; | |
| 153 | ||
| 154 | pub const filesize_t = u64; | |
| 155 | ||
| 156 | pub 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 | ||
| 167 | pub const filetype_t = u8; | |
| 168 | pub const FILETYPE_UNKNOWN: filetype_t = 0; | |
| 169 | pub const FILETYPE_BLOCK_DEVICE: filetype_t = 1; | |
| 170 | pub const FILETYPE_CHARACTER_DEVICE: filetype_t = 2; | |
| 171 | pub const FILETYPE_DIRECTORY: filetype_t = 3; | |
| 172 | pub const FILETYPE_REGULAR_FILE: filetype_t = 4; | |
| 173 | pub const FILETYPE_SOCKET_DGRAM: filetype_t = 5; | |
| 174 | pub const FILETYPE_SOCKET_STREAM: filetype_t = 6; | |
| 175 | pub const FILETYPE_SYMBOLIC_LINK: filetype_t = 7; | |
| 176 | ||
| 177 | pub const fstflags_t = u16; | |
| 178 | pub const FILESTAT_SET_ATIM: fstflags_t = 0x0001; | |
| 179 | pub const FILESTAT_SET_ATIM_NOW: fstflags_t = 0x0002; | |
| 180 | pub const FILESTAT_SET_MTIM: fstflags_t = 0x0004; | |
| 181 | pub const FILESTAT_SET_MTIM_NOW: fstflags_t = 0x0008; | |
| 182 | ||
| 183 | pub const inode_t = u64; | |
| 184 | ||
| 185 | pub const iovec_t = extern struct { | |
| 186 | buf: [*]u8, | |
| 187 | buf_len: usize, | |
| 188 | }; | |
| 189 | ||
| 190 | pub const linkcount_t = u32; | |
| 191 | ||
| 192 | pub const lookupflags_t = u32; | |
| 193 | pub const LOOKUP_SYMLINK_FOLLOW: lookupflags_t = 0x00000001; | |
| 194 | ||
| 195 | pub const oflags_t = u16; | |
| 196 | pub const O_CREAT: oflags_t = 0x0001; | |
| 197 | pub const O_DIRECTORY: oflags_t = 0x0002; | |
| 198 | pub const O_EXCL: oflags_t = 0x0004; | |
| 199 | pub const O_TRUNC: oflags_t = 0x0008; | |
| 200 | ||
| 201 | pub const preopentype_t = u8; | |
| 202 | pub const PREOPENTYPE_DIR: preopentype_t = 0; | |
| 203 | ||
| 204 | pub 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 | ||
| 213 | pub const riflags_t = u16; | |
| 214 | pub const SOCK_RECV_PEEK: riflags_t = 0x0001; | |
| 215 | pub const SOCK_RECV_WAITALL: riflags_t = 0x0002; | |
| 216 | ||
| 217 | pub const rights_t = u64; | |
| 218 | pub const RIGHT_FD_DATASYNC: rights_t = 0x0000000000000001; | |
| 219 | pub const RIGHT_FD_READ: rights_t = 0x0000000000000002; | |
| 220 | pub const RIGHT_FD_SEEK: rights_t = 0x0000000000000004; | |
| 221 | pub const RIGHT_FD_FDSTAT_SET_FLAGS: rights_t = 0x0000000000000008; | |
| 222 | pub const RIGHT_FD_SYNC: rights_t = 0x0000000000000010; | |
| 223 | pub const RIGHT_FD_TELL: rights_t = 0x0000000000000020; | |
| 224 | pub const RIGHT_FD_WRITE: rights_t = 0x0000000000000040; | |
| 225 | pub const RIGHT_FD_ADVISE: rights_t = 0x0000000000000080; | |
| 226 | pub const RIGHT_FD_ALLOCATE: rights_t = 0x0000000000000100; | |
| 227 | pub const RIGHT_PATH_CREATE_DIRECTORY: rights_t = 0x0000000000000200; | |
| 228 | pub const RIGHT_PATH_CREATE_FILE: rights_t = 0x0000000000000400; | |
| 229 | pub const RIGHT_PATH_LINK_SOURCE: rights_t = 0x0000000000000800; | |
| 230 | pub const RIGHT_PATH_LINK_TARGET: rights_t = 0x0000000000001000; | |
| 231 | pub const RIGHT_PATH_OPEN: rights_t = 0x0000000000002000; | |
| 232 | pub const RIGHT_FD_READDIR: rights_t = 0x0000000000004000; | |
| 233 | pub const RIGHT_PATH_READLINK: rights_t = 0x0000000000008000; | |
| 234 | pub const RIGHT_PATH_RENAME_SOURCE: rights_t = 0x0000000000010000; | |
| 235 | pub const RIGHT_PATH_RENAME_TARGET: rights_t = 0x0000000000020000; | |
| 236 | pub const RIGHT_PATH_FILESTAT_GET: rights_t = 0x0000000000040000; | |
| 237 | pub const RIGHT_PATH_FILESTAT_SET_SIZE: rights_t = 0x0000000000080000; | |
| 238 | pub const RIGHT_PATH_FILESTAT_SET_TIMES: rights_t = 0x0000000000100000; | |
| 239 | pub const RIGHT_FD_FILESTAT_GET: rights_t = 0x0000000000200000; | |
| 240 | pub const RIGHT_FD_FILESTAT_SET_SIZE: rights_t = 0x0000000000400000; | |
| 241 | pub const RIGHT_FD_FILESTAT_SET_TIMES: rights_t = 0x0000000000800000; | |
| 242 | pub const RIGHT_PATH_SYMLINK: rights_t = 0x0000000001000000; | |
| 243 | pub const RIGHT_PATH_REMOVE_DIRECTORY: rights_t = 0x0000000002000000; | |
| 244 | pub const RIGHT_PATH_UNLINK_FILE: rights_t = 0x0000000004000000; | |
| 245 | pub const RIGHT_POLL_FD_READWRITE: rights_t = 0x0000000008000000; | |
| 246 | pub const RIGHT_SOCK_SHUTDOWN: rights_t = 0x0000000010000000; | |
| 247 | ||
| 248 | pub const roflags_t = u16; | |
| 249 | pub const SOCK_RECV_DATA_TRUNCATED: roflags_t = 0x0001; | |
| 250 | ||
| 251 | pub const sdflags_t = u8; | |
| 252 | pub const SHUT_RD: sdflags_t = 0x01; | |
| 253 | pub const SHUT_WR: sdflags_t = 0x02; | |
| 254 | ||
| 255 | pub const siflags_t = u16; | |
| 256 | ||
| 257 | pub const signal_t = u8; | |
| 258 | pub const SIGHUP: signal_t = 1; | |
| 259 | pub const SIGINT: signal_t = 2; | |
| 260 | pub const SIGQUIT: signal_t = 3; | |
| 261 | pub const SIGILL: signal_t = 4; | |
| 262 | pub const SIGTRAP: signal_t = 5; | |
| 263 | pub const SIGABRT: signal_t = 6; | |
| 264 | pub const SIGBUS: signal_t = 7; | |
| 265 | pub const SIGFPE: signal_t = 8; | |
| 266 | pub const SIGKILL: signal_t = 9; | |
| 267 | pub const SIGUSR1: signal_t = 10; | |
| 268 | pub const SIGSEGV: signal_t = 11; | |
| 269 | pub const SIGUSR2: signal_t = 12; | |
| 270 | pub const SIGPIPE: signal_t = 13; | |
| 271 | pub const SIGALRM: signal_t = 14; | |
| 272 | pub const SIGTERM: signal_t = 15; | |
| 273 | pub const SIGCHLD: signal_t = 16; | |
| 274 | pub const SIGCONT: signal_t = 17; | |
| 275 | pub const SIGSTOP: signal_t = 18; | |
| 276 | pub const SIGTSTP: signal_t = 19; | |
| 277 | pub const SIGTTIN: signal_t = 20; | |
| 278 | pub const SIGTTOU: signal_t = 21; | |
| 279 | pub const SIGURG: signal_t = 22; | |
| 280 | pub const SIGXCPU: signal_t = 23; | |
| 281 | pub const SIGXFSZ: signal_t = 24; | |
| 282 | pub const SIGVTALRM: signal_t = 25; | |
| 283 | pub const SIGPROF: signal_t = 26; | |
| 284 | pub const SIGWINCH: signal_t = 27; | |
| 285 | pub const SIGPOLL: signal_t = 28; | |
| 286 | pub const SIGPWR: signal_t = 29; | |
| 287 | pub const SIGSYS: signal_t = 30; | |
| 288 | ||
| 289 | pub const subclockflags_t = u16; | |
| 290 | pub const SUBSCRIPTION_CLOCK_ABSTIME: subclockflags_t = 0x0001; | |
| 291 | ||
| 292 | pub 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 | ||
| 309 | pub const timestamp_t = u64; | |
| 310 | ||
| 311 | pub const userdata_t = u64; | |
| 312 | ||
| 313 | pub const whence_t = u8; | |
| 314 | pub const WHENCE_CUR: whence_t = 0; | |
| 315 | pub const WHENCE_END: whence_t = 1; | |
| 316 | pub const WHENCE_SET: whence_t = 2; | |
| 317 | ||
| 318 | pub extern "wasi_unstable" fn args_get(argv: [*][*]u8, argv_buf: [*]u8) errno_t; | |
| 319 | pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t; | |
| 320 | ||
| 321 | pub extern "wasi_unstable" fn clock_res_get(clock_id: clockid_t, resolution: *timestamp_t) errno_t; | |
| 322 | pub extern "wasi_unstable" fn clock_time_get(clock_id: clockid_t, precision: timestamp_t, timestamp: *timestamp_t) errno_t; | |
| 323 | ||
| 324 | pub extern "wasi_unstable" fn environ_get(environ: [*]?[*]u8, environ_buf: [*]u8) errno_t; | |
| 325 | pub extern "wasi_unstable" fn environ_sizes_get(environ_count: *usize, environ_buf_size: *usize) errno_t; | |
| 326 | ||
| 327 | pub extern "wasi_unstable" fn fd_advise(fd: fd_t, offset: filesize_t, len: filesize_t, advice: advice_t) errno_t; | |
| 328 | pub extern "wasi_unstable" fn fd_allocate(fd: fd_t, offset: filesize_t, len: filesize_t) errno_t; | |
| 329 | pub extern "wasi_unstable" fn fd_close(fd: fd_t) errno_t; | |
| 330 | pub extern "wasi_unstable" fn fd_datasync(fd: fd_t) errno_t; | |
| 331 | pub extern "wasi_unstable" fn fd_pread(fd: fd_t, iovs: *const iovec_t, iovs_len: usize, offset: filesize_t, nread: *usize) errno_t; | |
| 332 | pub extern "wasi_unstable" fn fd_pwrite(fd: fd_t, iovs: *const ciovec_t, iovs_len: usize, offset: filesize_t, nwritten: *usize) errno_t; | |
| 333 | pub extern "wasi_unstable" fn fd_read(fd: fd_t, iovs: *const iovec_t, iovs_len: usize, nread: *usize) errno_t; | |
| 334 | pub extern "wasi_unstable" fn fd_readdir(fd: fd_t, buf: [*]u8, buf_len: usize, cookie: dircookie_t, bufused: *usize) errno_t; | |
| 335 | pub extern "wasi_unstable" fn fd_renumber(from: fd_t, to: fd_t) errno_t; | |
| 336 | pub extern "wasi_unstable" fn fd_seek(fd: fd_t, offset: filedelta_t, whence: whence_t, newoffset: *filesize_t) errno_t; | |
| 337 | pub extern "wasi_unstable" fn fd_sync(fd: fd_t) errno_t; | |
| 338 | pub extern "wasi_unstable" fn fd_tell(fd: fd_t, newoffset: *filesize_t) errno_t; | |
| 339 | pub extern "wasi_unstable" fn fd_write(fd: fd_t, iovs: *const ciovec_t, iovs_len: usize, nwritten: *usize) errno_t; | |
| 340 | ||
| 341 | pub extern "wasi_unstable" fn fd_fdstat_get(fd: fd_t, buf: *fdstat_t) errno_t; | |
| 342 | pub extern "wasi_unstable" fn fd_fdstat_set_flags(fd: fd_t, flags: fdflags_t) errno_t; | |
| 343 | pub extern "wasi_unstable" fn fd_fdstat_set_rights(fd: fd_t, fs_rights_base: rights_t, fs_rights_inheriting: rights_t) errno_t; | |
| 344 | ||
| 345 | pub extern "wasi_unstable" fn fd_filestat_get(fd: fd_t, buf: *filestat_t) errno_t; | |
| 346 | pub extern "wasi_unstable" fn fd_filestat_set_size(fd: fd_t, st_size: filesize_t) errno_t; | |
| 347 | pub extern "wasi_unstable" fn fd_filestat_set_times(fd: fd_t, st_atim: timestamp_t, st_mtim: timestamp_t, fstflags: fstflags_t) errno_t; | |
| 348 | ||
| 349 | pub extern "wasi_unstable" fn fd_prestat_get(fd: fd_t, buf: *prestat_t) errno_t; | |
| 350 | pub extern "wasi_unstable" fn fd_prestat_dir_name(fd: fd_t, path: [*]u8, path_len: usize) errno_t; | |
| 351 | ||
| 352 | pub extern "wasi_unstable" fn path_create_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t; | |
| 353 | pub extern "wasi_unstable" fn path_filestat_get(fd: fd_t, flags: lookupflags_t, path: [*]const u8, path_len: usize, buf: *filestat_t) errno_t; | |
| 354 | pub extern "wasi_unstable" fn path_filestat_set_times(fd: fd_t, flags: lookupflags_t, path: [*]const u8, path_len: usize, st_atim: timestamp_t, st_mtim: timestamp_t, fstflags: fstflags_t) errno_t; | |
| 355 | pub extern "wasi_unstable" fn path_link(old_fd: fd_t, old_flags: lookupflags_t, old_path: [*]const u8, old_path_len: usize, new_fd: fd_t, new_path: [*]const u8, new_path_len: usize) errno_t; | |
| 356 | pub extern "wasi_unstable" fn path_open(dirfd: fd_t, dirflags: lookupflags_t, path: [*]const u8, path_len: usize, oflags: oflags_t, fs_rights_base: rights_t, fs_rights_inheriting: rights_t, fs_flags: fdflags_t, fd: *fd_t) errno_t; | |
| 357 | pub extern "wasi_unstable" fn path_readlink(fd: fd_t, path: [*]const u8, path_len: usize, buf: [*]u8, buf_len: usize, bufused: *usize) errno_t; | |
| 358 | pub extern "wasi_unstable" fn path_remove_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t; | |
| 359 | pub extern "wasi_unstable" fn path_rename(old_fd: fd_t, old_path: [*]const u8, old_path_len: usize, new_fd: fd_t, new_path: [*]const u8, new_path_len: usize) errno_t; | |
| 360 | pub extern "wasi_unstable" fn path_symlink(old_path: [*]const u8, old_path_len: usize, fd: fd_t, new_path: [*]const u8, new_path_len: usize) errno_t; | |
| 361 | pub extern "wasi_unstable" fn path_unlink_file(fd: fd_t, path: [*]const u8, path_len: usize) errno_t; | |
| 362 | ||
| 363 | pub extern "wasi_unstable" fn poll_oneoff(in: *const subscription_t, out: *event_t, nsubscriptions: usize, nevents: *usize) errno_t; | |
| 364 | ||
| 365 | pub extern "wasi_unstable" fn proc_exit(rval: exitcode_t) noreturn; | |
| 366 | pub extern "wasi_unstable" fn proc_raise(sig: signal_t) errno_t; | |
| 367 | ||
| 368 | pub extern "wasi_unstable" fn random_get(buf: [*]u8, buf_len: usize) errno_t; | |
| 369 | ||
| 370 | pub extern "wasi_unstable" fn sched_yield() errno_t; | |
| 371 | ||
| 372 | pub extern "wasi_unstable" fn sock_recv(sock: fd_t, ri_data: *const iovec_t, ri_data_len: usize, ri_flags: riflags_t, ro_datalen: *usize, ro_flags: *roflags_t) errno_t; | |
| 373 | pub extern "wasi_unstable" fn sock_send(sock: fd_t, si_data: *const ciovec_t, si_data_len: usize, si_flags: siflags_t, so_datalen: *usize) errno_t; | |
| 374 | pub 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 | 239 | pub const HEAP_GENERATE_EXCEPTIONS = 0x00000004; |
| 240 | 240 | pub const HEAP_NO_SERIALIZE = 0x00000001; |
| 241 | 241 | |
| 242 | // AllocationType values | |
| 243 | pub const MEM_COMMIT = 0x1000; | |
| 244 | pub const MEM_RESERVE = 0x2000; | |
| 245 | pub const MEM_RESET = 0x80000; | |
| 246 | pub const MEM_RESET_UNDO = 0x1000000; | |
| 247 | pub const MEM_LARGE_PAGES = 0x20000000; | |
| 248 | pub const MEM_PHYSICAL = 0x400000; | |
| 249 | pub const MEM_TOP_DOWN = 0x100000; | |
| 250 | pub const MEM_WRITE_WATCH = 0x200000; | |
| 251 | ||
| 252 | // Protect values | |
| 253 | pub const PAGE_EXECUTE = 0x10; | |
| 254 | pub const PAGE_EXECUTE_READ = 0x20; | |
| 255 | pub const PAGE_EXECUTE_READWRITE = 0x40; | |
| 256 | pub const PAGE_EXECUTE_WRITECOPY = 0x80; | |
| 257 | pub const PAGE_NOACCESS = 0x01; | |
| 258 | pub const PAGE_READONLY = 0x02; | |
| 259 | pub const PAGE_READWRITE = 0x04; | |
| 260 | pub const PAGE_WRITECOPY = 0x08; | |
| 261 | pub const PAGE_TARGETS_INVALID = 0x40000000; | |
| 262 | pub const PAGE_TARGETS_NO_UPDATE = 0x40000000; // Same as PAGE_TARGETS_INVALID | |
| 263 | pub const PAGE_GUARD = 0x100; | |
| 264 | pub const PAGE_NOCACHE = 0x200; | |
| 265 | pub const PAGE_WRITECOMBINE = 0x400; | |
| 266 | ||
| 267 | // FreeType values | |
| 268 | pub const MEM_COALESCE_PLACEHOLDERS = 0x1; | |
| 269 | pub const MEM_RESERVE_PLACEHOLDERS = 0x2; | |
| 270 | pub const MEM_DECOMMIT = 0x4000; | |
| 271 | pub const MEM_RELEASE = 0x8000; | |
| 272 | ||
| 242 | 273 | pub const PTHREAD_START_ROUTINE = extern fn (LPVOID) DWORD; |
| 243 | 274 | pub const LPTHREAD_START_ROUTINE = PTHREAD_START_ROUTINE; |
| 244 | 275 |
std/os/windows/kernel32.zig+3| ... | ... | @@ -116,6 +116,9 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem |
| 116 | 116 | |
| 117 | 117 | pub extern "kernel32" stdcallcc fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*const c_void) BOOL; |
| 118 | 118 | |
| 119 | pub extern "kernel32" stdcallcc fn VirtualAlloc(lpAddress: ?LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD) ?LPVOID; | |
| 120 | pub extern "kernel32" stdcallcc fn VirtualFree(lpAddress: ?LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) BOOL; | |
| 121 | ||
| 119 | 122 | pub extern "kernel32" stdcallcc fn MoveFileExW( |
| 120 | 123 | lpExistingFileName: [*]const u16, |
| 121 | 124 | lpNewFileName: [*]const u16, |
std/packed_int_array.zig created+649| ... | ... | @@ -0,0 +1,649 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const debug = std.debug; | |
| 4 | const testing = std.testing; | |
| 5 | ||
| 6 | pub 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. | |
| 169 | pub 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. | |
| 176 | pub 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. | |
| 238 | pub 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. | |
| 245 | pub 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 | ||
| 316 | test "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 | ||
| 352 | test "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 | ||
| 359 | test "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 | ||
| 396 | test "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 | ||
| 461 | test "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 | |
| 488 | test "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 | ||
| 528 | test "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. | |
| 614 | test "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 | ||
| 634 | test "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 | 588 | |
| 589 | 589 | const MsfStream = struct { |
| 590 | 590 | in_file: os.File, |
| 591 | pos: usize, | |
| 591 | pos: u64, | |
| 592 | 592 | blocks: []u32, |
| 593 | 593 | block_size: u32, |
| 594 | 594 | |
| ... | ... | @@ -598,7 +598,7 @@ const MsfStream = struct { |
| 598 | 598 | pub const Error = @typeOf(read).ReturnType.ErrorSet; |
| 599 | 599 | pub const Stream = io.InStream(Error); |
| 600 | 600 | |
| 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 | 602 | var stream = MsfStream{ |
| 603 | 603 | .in_file = file, |
| 604 | 604 | .pos = 0, |
| ... | ... | @@ -660,23 +660,24 @@ const MsfStream = struct { |
| 660 | 660 | return size; |
| 661 | 661 | } |
| 662 | 662 | |
| 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 | 665 | self.pos += len; |
| 665 | 666 | if (self.pos >= self.blocks.len * self.block_size) |
| 666 | 667 | return error.EOF; |
| 667 | 668 | } |
| 668 | 669 | |
| 669 | fn seekTo(self: *MsfStream, len: usize) !void { | |
| 670 | fn seekTo(self: *MsfStream, len: u64) !void { | |
| 670 | 671 | self.pos = len; |
| 671 | 672 | if (self.pos >= self.blocks.len * self.block_size) |
| 672 | 673 | return error.EOF; |
| 673 | 674 | } |
| 674 | 675 | |
| 675 | fn getSize(self: *const MsfStream) usize { | |
| 676 | fn getSize(self: *const MsfStream) u64 { | |
| 676 | 677 | return self.blocks.len * self.block_size; |
| 677 | 678 | } |
| 678 | 679 | |
| 679 | fn getFilePos(self: MsfStream) usize { | |
| 680 | fn getFilePos(self: MsfStream) u64 { | |
| 680 | 681 | const block_id = self.pos / self.block_size; |
| 681 | 682 | const block = self.blocks[block_id]; |
| 682 | 683 | const offset = self.pos % self.block_size; |
std/rand.zig+2-2| ... | ... | @@ -768,10 +768,10 @@ pub const Isaac64 = struct { |
| 768 | 768 | const x = self.m[base + m1]; |
| 769 | 769 | self.a = mix +% self.m[base + m2]; |
| 770 | 770 | |
| 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 | 772 | self.m[base + m1] = y; |
| 773 | 773 | |
| 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 | 775 | self.r[self.r.len - 1 - base - m1] = self.b; |
| 776 | 776 | } |
| 777 | 777 |
std/special/bootstrap.zig+13-61| ... | ... | @@ -20,6 +20,10 @@ comptime { |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | nakedcc fn _start() noreturn { |
| 23 | if (builtin.os == builtin.Os.wasi) { | |
| 24 | std.os.wasi.proc_exit(callMain()); | |
| 25 | } | |
| 26 | ||
| 23 | 27 | switch (builtin.arch) { |
| 24 | 28 | builtin.Arch.x86_64 => { |
| 25 | 29 | argc_ptr = asm ("lea (%%rsp), %[argc]" |
| ... | ... | @@ -63,24 +67,19 @@ fn posixCallMainAndExit() noreturn { |
| 63 | 67 | var envp_count: usize = 0; |
| 64 | 68 | while (envp_optional[envp_count]) |_| : (envp_count += 1) {} |
| 65 | 69 | const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count]; |
| 70 | ||
| 66 | 71 | if (builtin.os == builtin.Os.linux) { |
| 67 | // Scan auxiliary vector. | |
| 72 | // Find the beginning of the auxiliary vector | |
| 68 | 73 | const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1); |
| 69 | 74 | std.os.linux_elf_aux_maybe = auxv; |
| 70 | var i: usize = 0; | |
| 71 | var at_phdr: usize = 0; | |
| 72 | var at_phnum: usize = 0; | |
| 73 | var at_phent: usize = 0; | |
| 74 | while (auxv[i].a_un.a_val != 0) : (i += 1) { | |
| 75 | switch (auxv[i].a_type) { | |
| 76 | std.elf.AT_PAGESZ => assert(auxv[i].a_un.a_val == std.os.page_size), | |
| 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 | } | |
| 75 | // Initialize the TLS area | |
| 76 | std.os.linux.tls.initTLS(); | |
| 77 | ||
| 78 | if (std.os.linux.tls.tls_image) |tls_img| { | |
| 79 | const tls_addr = std.os.linux.tls.allocateTLS(tls_img.alloc_size); | |
| 80 | const tp = std.os.linux.tls.copyTLS(tls_addr); | |
| 81 | std.os.linux.tls.setThreadPointer(tp); | |
| 82 | 82 | } |
| 83 | if (!builtin.single_threaded) linuxInitializeThreadLocalStorage(at_phdr, at_phnum, at_phent); | |
| 84 | 83 | } |
| 85 | 84 | |
| 86 | 85 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); |
| ... | ... | @@ -136,50 +135,3 @@ inline fn callMain() u8 { |
| 136 | 135 | |
| 137 | 136 | const main_thread_tls_align = 32; |
| 138 | 137 | var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64; |
| 139 | ||
| 140 | fn 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 | ||
| 168 | fn 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 | 94 | return usageAndErr(&builder, false, try stderr_stream); |
| 95 | 95 | }); |
| 96 | 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 | 107 | } else if (mem.eql(u8, arg, "--verbose-tokenize")) { |
| 98 | 108 | builder.verbose_tokenize = true; |
| 99 | 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 | 197 | try out_stream.write( |
| 188 | 198 | \\ |
| 189 | 199 | \\Advanced Options: |
| 190 | \\ --build-file [file] Override path to build.zig | |
| 191 | \\ --cache-dir [path] Override path to zig cache directory | |
| 192 | \\ --verbose-tokenize Enable compiler debug output for tokenization | |
| 193 | \\ --verbose-ast Enable compiler debug output for parsing into an AST | |
| 194 | \\ --verbose-link Enable compiler debug output for linking | |
| 195 | \\ --verbose-ir Enable compiler debug output for Zig IR | |
| 196 | \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR | |
| 197 | \\ --verbose-cimport Enable compiler debug output for C imports | |
| 198 | \\ --verbose-cc Enable compiler debug output for C compilation | |
| 200 | \\ --build-file [file] Override path to build.zig | |
| 201 | \\ --cache-dir [path] Override path to zig cache directory | |
| 202 | \\ --override-std-dir [arg] Override path to Zig standard library | |
| 203 | \\ --override-lib-dir [arg] Override path to Zig lib directory | |
| 204 | \\ --verbose-tokenize Enable compiler debug output for tokenization | |
| 205 | \\ --verbose-ast Enable compiler debug output for parsing into an AST | |
| 206 | \\ --verbose-link Enable compiler debug output for linking | |
| 207 | \\ --verbose-ir Enable compiler debug output for Zig IR | |
| 208 | \\ --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 | 5 | const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak; |
| 6 | 6 | const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong; |
| 7 | 7 | |
| 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 | 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 | 19 | @export("__getf2", @import("compiler_rt/comparetf2.zig").__getf2, linkage); |
| 10 | 20 | |
| 11 | 21 | if (!is_test) { |
| 12 | 22 | // 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 | 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 | 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 | 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 | 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 | 41 | @export("__gttf2", @import("compiler_rt/comparetf2.zig").__getf2, linkage); |
| 42 | ||
| 18 | 43 | @export("__gnu_h2f_ieee", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage); |
| 19 | 44 | @export("__gnu_f2h_ieee", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage); |
| 20 | 45 | } |
| 21 | 46 | |
| 47 | @export("__unordsf2", @import("compiler_rt/comparesf2.zig").__unordsf2, linkage); | |
| 48 | @export("__unorddf2", @import("compiler_rt/comparedf2.zig").__unorddf2, linkage); | |
| 22 | 49 | @export("__unordtf2", @import("compiler_rt/comparetf2.zig").__unordtf2, linkage); |
| 23 | 50 | |
| 24 | 51 | @export("__addsf3", @import("compiler_rt/addXf3.zig").__addsf3, linkage); |
| ... | ... | @@ -35,6 +62,17 @@ comptime { |
| 35 | 62 | @export("__divsf3", @import("compiler_rt/divsf3.zig").__divsf3, linkage); |
| 36 | 63 | @export("__divdf3", @import("compiler_rt/divdf3.zig").__divdf3, linkage); |
| 37 | 64 | |
| 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 | 76 | @export("__floattitf", @import("compiler_rt/floattitf.zig").__floattitf, linkage); |
| 39 | 77 | @export("__floattidf", @import("compiler_rt/floattidf.zig").__floattidf, linkage); |
| 40 | 78 | @export("__floattisf", @import("compiler_rt/floattisf.zig").__floattisf, linkage); |
| ... | ... | @@ -55,6 +93,10 @@ comptime { |
| 55 | 93 | @export("__trunctfdf2", @import("compiler_rt/truncXfYf2.zig").__trunctfdf2, linkage); |
| 56 | 94 | @export("__trunctfsf2", @import("compiler_rt/truncXfYf2.zig").__trunctfsf2, linkage); |
| 57 | 95 | |
| 96 | @export("__truncdfsf2", @import("compiler_rt/truncXfYf2.zig").__truncdfsf2, linkage); | |
| 97 | ||
| 98 | @export("__extendsfdf2", @import("compiler_rt/extendXfYf2.zig").__extendsfdf2, linkage); | |
| 99 | ||
| 58 | 100 | @export("__fixunssfsi", @import("compiler_rt/fixunssfsi.zig").__fixunssfsi, linkage); |
| 59 | 101 | @export("__fixunssfdi", @import("compiler_rt/fixunssfdi.zig").__fixunssfdi, linkage); |
| 60 | 102 | @export("__fixunssfti", @import("compiler_rt/fixunssfti.zig").__fixunssfti, linkage); |
| ... | ... | @@ -80,18 +122,33 @@ comptime { |
| 80 | 122 | @export("__udivmoddi4", @import("compiler_rt/udivmoddi4.zig").__udivmoddi4, linkage); |
| 81 | 123 | @export("__popcountdi2", @import("compiler_rt/popcountdi2.zig").__popcountdi2, linkage); |
| 82 | 124 | |
| 125 | @export("__divmoddi4", __divmoddi4, linkage); | |
| 126 | @export("__divsi3", __divsi3, linkage); | |
| 127 | @export("__divdi3", __divdi3, linkage); | |
| 83 | 128 | @export("__udivsi3", __udivsi3, linkage); |
| 84 | 129 | @export("__udivdi3", __udivdi3, linkage); |
| 130 | @export("__modsi3", __modsi3, linkage); | |
| 131 | @export("__moddi3", __moddi3, linkage); | |
| 132 | @export("__umodsi3", __umodsi3, linkage); | |
| 85 | 133 | @export("__umoddi3", __umoddi3, linkage); |
| 134 | @export("__divmodsi4", __divmodsi4, linkage); | |
| 86 | 135 | @export("__udivmodsi4", __udivmodsi4, linkage); |
| 87 | 136 | |
| 88 | 137 | @export("__negsf2", @import("compiler_rt/negXf2.zig").__negsf2, linkage); |
| 89 | 138 | @export("__negdf2", @import("compiler_rt/negXf2.zig").__negdf2, linkage); |
| 90 | 139 | |
| 91 | 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 | 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 | 150 | @export("__aeabi_uidiv", __udivsi3, linkage); |
| 151 | @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); | |
| 95 | 152 | |
| 96 | 153 | @export("__aeabi_memcpy", __aeabi_memcpy, linkage); |
| 97 | 154 | @export("__aeabi_memcpy4", __aeabi_memcpy, linkage); |
| ... | ... | @@ -113,6 +170,12 @@ comptime { |
| 113 | 170 | @export("__aeabi_memcmp4", __aeabi_memcmp, linkage); |
| 114 | 171 | @export("__aeabi_memcmp8", __aeabi_memcmp, linkage); |
| 115 | 172 | |
| 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 | 179 | @export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage); |
| 117 | 180 | @export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage); |
| 118 | 181 | |
| ... | ... | @@ -132,6 +195,9 @@ comptime { |
| 132 | 195 | @export("__aeabi_h2f", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage); |
| 133 | 196 | @export("__aeabi_f2h", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage); |
| 134 | 197 | |
| 198 | @export("__aeabi_i2f", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage); | |
| 199 | @export("__aeabi_d2f", @import("compiler_rt/truncXfYf2.zig").__truncdfsf2, linkage); | |
| 200 | ||
| 135 | 201 | @export("__aeabi_fadd", @import("compiler_rt/addXf3.zig").__addsf3, linkage); |
| 136 | 202 | @export("__aeabi_dadd", @import("compiler_rt/addXf3.zig").__adddf3, linkage); |
| 137 | 203 | @export("__aeabi_fsub", @import("compiler_rt/addXf3.zig").__subsf3, linkage); |
| ... | ... | @@ -144,26 +210,41 @@ comptime { |
| 144 | 210 | |
| 145 | 211 | @export("__aeabi_fdiv", @import("compiler_rt/divsf3.zig").__divsf3, linkage); |
| 146 | 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 | 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 | 237 | switch (builtin.arch) { |
| 150 | 238 | builtin.Arch.i386 => { |
| 151 | if (!builtin.link_libc) { | |
| 152 | @export("_chkstk", _chkstk, strong_linkage); | |
| 153 | @export("__chkstk_ms", __chkstk_ms, linkage); | |
| 154 | } | |
| 155 | 239 | @export("_aulldiv", @import("compiler_rt/aulldiv.zig")._aulldiv, strong_linkage); |
| 156 | 240 | @export("_aullrem", @import("compiler_rt/aullrem.zig")._aullrem, strong_linkage); |
| 157 | 241 | }, |
| 158 | 242 | builtin.Arch.x86_64 => { |
| 159 | if (!builtin.link_libc) { | |
| 160 | @export("__chkstk", __chkstk, strong_linkage); | |
| 161 | @export("___chkstk_ms", ___chkstk_ms, linkage); | |
| 162 | } | |
| 243 | // The "ti" functions must use @Vector(2, u64) parameter types to adhere to the ABI | |
| 244 | // that LLVM expects compiler-rt to have. | |
| 163 | 245 | @export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage); |
| 164 | 246 | @export("__modti3", @import("compiler_rt/modti3.zig").__modti3_windows_x86_64, linkage); |
| 165 | 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 | 248 | @export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64, linkage); |
| 168 | 249 | @export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64, linkage); |
| 169 | 250 | @export("__umodti3", @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64, linkage); |
| ... | ... | @@ -174,11 +255,12 @@ comptime { |
| 174 | 255 | @export("__divti3", @import("compiler_rt/divti3.zig").__divti3, linkage); |
| 175 | 256 | @export("__modti3", @import("compiler_rt/modti3.zig").__modti3, linkage); |
| 176 | 257 | @export("__multi3", @import("compiler_rt/multi3.zig").__multi3, linkage); |
| 177 | @export("__muloti4", @import("compiler_rt/muloti4.zig").__muloti4, linkage); | |
| 178 | 258 | @export("__udivti3", @import("compiler_rt/udivti3.zig").__udivti3, linkage); |
| 179 | 259 | @export("__udivmodti4", @import("compiler_rt/udivmodti4.zig").__udivmodti4, linkage); |
| 180 | 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 | } |
| 183 | 265 | |
| 184 | 266 | const std = @import("std"); |
| ... | ... | @@ -198,15 +280,49 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn |
| 198 | 280 | } |
| 199 | 281 | } |
| 200 | 282 | |
| 201 | pub fn setXmm0(comptime T: type, value: T) void { | |
| 202 | comptime assert(builtin.arch == builtin.Arch.x86_64); | |
| 203 | const aligned_value: T align(16) = value; | |
| 204 | asm volatile ( | |
| 205 | \\movaps (%[ptr]), %%xmm0 | |
| 206 | : | |
| 207 | : [ptr] "r" (&aligned_value) | |
| 208 | : "xmm0" | |
| 209 | ); | |
| 283 | extern fn __aeabi_unwind_cpp_pr0() void { | |
| 284 | unreachable; | |
| 285 | } | |
| 286 | extern fn __aeabi_unwind_cpp_pr1() void { | |
| 287 | unreachable; | |
| 288 | } | |
| 289 | extern fn __aeabi_unwind_cpp_pr2() void { | |
| 290 | unreachable; | |
| 291 | } | |
| 292 | ||
| 293 | extern 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 | ||
| 301 | extern 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 | ||
| 315 | extern 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 | } |
| 211 | 327 | |
| 212 | 328 | extern fn __udivdi3(a: u64, b: u64) u64 { |
| ... | ... | @@ -222,14 +338,35 @@ extern fn __umoddi3(a: u64, b: u64) u64 { |
| 222 | 338 | return r; |
| 223 | 339 | } |
| 224 | 340 | |
| 225 | const AeabiUlDivModResult = extern struct { | |
| 226 | quot: u64, | |
| 227 | rem: u64, | |
| 228 | }; | |
| 229 | extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult { | |
| 341 | extern fn __aeabi_uidivmod(n: u32, d: u32) extern struct{q: u32, r: u32} { | |
| 342 | @setRuntimeSafety(is_test); | |
| 343 | ||
| 344 | var result: @typeOf(__aeabi_uidivmod).ReturnType = undefined; | |
| 345 | result.q = __udivmodsi4(n, d, &result.r); | |
| 346 | return result; | |
| 347 | } | |
| 348 | ||
| 349 | extern 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 | ||
| 357 | extern 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 | ||
| 365 | extern fn __aeabi_ldivmod(n: i64, d: i64) extern struct{q: i64, r:i64} { | |
| 230 | 366 | @setRuntimeSafety(is_test); |
| 231 | var result: AeabiUlDivModResult = undefined; | |
| 232 | result.quot = __udivmoddi4(numerator, denominator, &result.rem); | |
| 367 | ||
| 368 | var result: @typeOf(__aeabi_ldivmod).ReturnType = undefined; | |
| 369 | result.q = __divmoddi4(n, d, &result.r); | |
| 233 | 370 | return result; |
| 234 | 371 | } |
| 235 | 372 | |
| ... | ... | @@ -253,29 +390,74 @@ const is_arm_arch = switch (builtin.arch) { |
| 253 | 390 | |
| 254 | 391 | const is_arm_32 = is_arm_arch and !is_arm_64; |
| 255 | 392 | |
| 256 | const use_thumb_1 = is_arm_32 and switch (builtin.arch.arm) { | |
| 257 | builtin.Arch.Arm32.v6, | |
| 258 | builtin.Arch.Arm32.v6m, | |
| 259 | builtin.Arch.Arm32.v6k, | |
| 260 | builtin.Arch.Arm32.v6t2, | |
| 261 | => true, | |
| 262 | else => false, | |
| 263 | }; | |
| 393 | const use_thumb_1 = usesThumb1(builtin.arch); | |
| 394 | ||
| 395 | fn usesThumb1(arch: builtin.Arch) bool { | |
| 396 | return switch (arch) { | |
| 397 | .arm => switch (arch.arm) { | |
| 398 | .v6m => true, | |
| 399 | else => false, | |
| 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 | } | |
| 264 | 428 | |
| 265 | nakedcc fn __aeabi_uidivmod() void { | |
| 266 | @setRuntimeSafety(false); | |
| 267 | asm volatile ( | |
| 268 | \\ push { lr } | |
| 269 | \\ sub sp, sp, #4 | |
| 270 | \\ mov r2, sp | |
| 271 | \\ bl __udivmodsi4 | |
| 272 | \\ ldr r1, [sp] | |
| 273 | \\ add sp, sp, #4 | |
| 274 | \\ pop { pc } | |
| 275 | : | |
| 276 | : | |
| 277 | : "r2", "r1" | |
| 278 | ); | |
| 429 | test "usesThumb1" { | |
| 430 | testing.expect(usesThumb1(builtin.Arch{ .arm = .v6m })); | |
| 431 | testing.expect(!usesThumb1(builtin.Arch{ .arm = .v5 })); | |
| 432 | //etc. | |
| 433 | ||
| 434 | testing.expect(usesThumb1(builtin.Arch{ .armeb = .v6m })); | |
| 435 | testing.expect(!usesThumb1(builtin.Arch{ .armeb = .v5 })); | |
| 436 | //etc. | |
| 437 | ||
| 438 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5 })); | |
| 439 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5te })); | |
| 440 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v4t })); | |
| 441 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6 })); | |
| 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 | } |
| 280 | 462 | |
| 281 | 463 | nakedcc fn __aeabi_memcpy() noreturn { |
| ... | ... | @@ -368,107 +550,12 @@ nakedcc fn __aeabi_memcmp() noreturn { |
| 368 | 550 | unreachable; |
| 369 | 551 | } |
| 370 | 552 | |
| 371 | // _chkstk (_alloca) routine - probe stack between %esp and (%esp-%eax) in 4k increments, | |
| 372 | // then decrement %esp by %eax. Preserves all registers except %esp and flags. | |
| 373 | // This routine is windows specific | |
| 374 | // http://msdn.microsoft.com/en-us/library/ms648426.aspx | |
| 375 | nakedcc 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 | ||
| 399 | nakedcc 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 | |
| 426 | nakedcc 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 | ||
| 450 | nakedcc fn ___chkstk_ms() align(4) void { | |
| 451 | @setRuntimeSafety(false); | |
| 553 | extern fn __divmodsi4(a: i32, b: i32, rem: *i32) i32 { | |
| 554 | @setRuntimeSafety(is_test); | |
| 452 | 555 | |
| 453 | asm volatile ( | |
| 454 | \\ push %%rcx | |
| 455 | \\ push %%rax | |
| 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 | ); | |
| 556 | const d = __divsi3(a, b); | |
| 557 | rem.* = a -% (d * b); | |
| 558 | return d; | |
| 472 | 559 | } |
| 473 | 560 | |
| 474 | 561 | 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 | 566 | return d; |
| 480 | 567 | } |
| 481 | 568 | |
| 569 | extern 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 | ||
| 482 | 583 | extern fn __udivsi3(n: u32, d: u32) u32 { |
| 483 | 584 | @setRuntimeSafety(is_test); |
| 484 | 585 | |
| ... | ... | @@ -520,6 +621,18 @@ extern fn __udivsi3(n: u32, d: u32) u32 { |
| 520 | 621 | return q; |
| 521 | 622 | } |
| 522 | 623 | |
| 624 | extern fn __modsi3(n: i32, d: i32) i32 { | |
| 625 | @setRuntimeSafety(is_test); | |
| 626 | ||
| 627 | return n -% __divsi3(n, d) *% d; | |
| 628 | } | |
| 629 | ||
| 630 | extern fn __umodsi3(n: u32, d: u32) u32 { | |
| 631 | @setRuntimeSafety(is_test); | |
| 632 | ||
| 633 | return n -% __udivsi3(n, d) *% d; | |
| 634 | } | |
| 635 | ||
| 523 | 636 | test "test_umoddi3" { |
| 524 | 637 | test_one_umoddi3(0, 1, 0); |
| 525 | 638 | test_one_umoddi3(2, 1, 0); |
| ... | ... | @@ -1206,3 +1319,279 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { |
| 1206 | 1319 | const q: u32 = __udivsi3(a, b); |
| 1207 | 1320 | testing.expect(q == expected_q); |
| 1208 | 1321 | } |
| 1322 | ||
| 1323 | test "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 | ||
| 1343 | fn 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 | ||
| 1348 | test "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 | ||
| 1370 | fn 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 | ||
| 1376 | test "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 | ||
| 1396 | fn 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 | ||
| 1401 | test "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 | ||
| 1423 | fn 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 | ||
| 1428 | test "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 | ||
| 1448 | fn 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 | ||
| 1453 | test "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 | ||
| 1594 | fn 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 | 78 | const infRep = @bitCast(Z, std.math.inf(T)); |
| 79 | 79 | |
| 80 | 80 | // Detect if a or b is zero, infinity, or NaN. |
| 81 | if (aAbs - Z(1) >= infRep - Z(1) or | |
| 82 | bAbs - Z(1) >= infRep - Z(1)) | |
| 81 | if (aAbs -% Z(1) >= infRep - Z(1) or | |
| 82 | bAbs -% Z(1) >= infRep - Z(1)) | |
| 83 | 83 | { |
| 84 | 84 | // NaN + anything = qNaN |
| 85 | 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 | ||
| 5 | const compiler_rt_armhf_target = false; // TODO | |
| 6 | ||
| 7 | const ConditionalOperator = enum { | |
| 8 | Eq, | |
| 9 | Lt, | |
| 10 | Le, | |
| 11 | Ge, | |
| 12 | Gt, | |
| 13 | }; | |
| 14 | ||
| 15 | pub nakedcc fn __aeabi_dcmpeq() noreturn { | |
| 16 | @setRuntimeSafety(false); | |
| 17 | aeabi_dcmp(.Eq); | |
| 18 | unreachable; | |
| 19 | } | |
| 20 | ||
| 21 | pub nakedcc fn __aeabi_dcmplt() noreturn { | |
| 22 | @setRuntimeSafety(false); | |
| 23 | aeabi_dcmp(.Lt); | |
| 24 | unreachable; | |
| 25 | } | |
| 26 | ||
| 27 | pub nakedcc fn __aeabi_dcmple() noreturn { | |
| 28 | @setRuntimeSafety(false); | |
| 29 | aeabi_dcmp(.Le); | |
| 30 | unreachable; | |
| 31 | } | |
| 32 | ||
| 33 | pub nakedcc fn __aeabi_dcmpge() noreturn { | |
| 34 | @setRuntimeSafety(false); | |
| 35 | aeabi_dcmp(.Ge); | |
| 36 | unreachable; | |
| 37 | } | |
| 38 | ||
| 39 | pub nakedcc fn __aeabi_dcmpgt() noreturn { | |
| 40 | @setRuntimeSafety(false); | |
| 41 | aeabi_dcmp(.Gt); | |
| 42 | unreachable; | |
| 43 | } | |
| 44 | ||
| 45 | inline fn convert_dcmp_args_to_df2_args() void { | |
| 46 | asm volatile ( | |
| 47 | \\ vmov d0, r0, r1 | |
| 48 | \\ vmov d1, r2, r3 | |
| 49 | ); | |
| 50 | } | |
| 51 | ||
| 52 | inline 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 | ||
| 5 | const compiler_rt_armhf_target = false; // TODO | |
| 6 | ||
| 7 | const ConditionalOperator = enum { | |
| 8 | Eq, | |
| 9 | Lt, | |
| 10 | Le, | |
| 11 | Ge, | |
| 12 | Gt, | |
| 13 | }; | |
| 14 | ||
| 15 | pub nakedcc fn __aeabi_fcmpeq() noreturn { | |
| 16 | @setRuntimeSafety(false); | |
| 17 | aeabi_fcmp(.Eq); | |
| 18 | unreachable; | |
| 19 | } | |
| 20 | ||
| 21 | pub nakedcc fn __aeabi_fcmplt() noreturn { | |
| 22 | @setRuntimeSafety(false); | |
| 23 | aeabi_fcmp(.Lt); | |
| 24 | unreachable; | |
| 25 | } | |
| 26 | ||
| 27 | pub nakedcc fn __aeabi_fcmple() noreturn { | |
| 28 | @setRuntimeSafety(false); | |
| 29 | aeabi_fcmp(.Le); | |
| 30 | unreachable; | |
| 31 | } | |
| 32 | ||
| 33 | pub nakedcc fn __aeabi_fcmpge() noreturn { | |
| 34 | @setRuntimeSafety(false); | |
| 35 | aeabi_fcmp(.Ge); | |
| 36 | unreachable; | |
| 37 | } | |
| 38 | ||
| 39 | pub nakedcc fn __aeabi_fcmpgt() noreturn { | |
| 40 | @setRuntimeSafety(false); | |
| 41 | aeabi_fcmp(.Gt); | |
| 42 | unreachable; | |
| 43 | } | |
| 44 | ||
| 45 | inline fn convert_fcmp_args_to_sf2_args() void { | |
| 46 | asm volatile ( | |
| 47 | \\ vmov s0, r0 | |
| 48 | \\ vmov s1, r1 | |
| 49 | ); | |
| 50 | } | |
| 51 | ||
| 52 | inline 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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | ||
| 4 | pub 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 | ||
| 23 | const 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 | ||
| 39 | test "import ashlti3" { | |
| 40 | _ = @import("ashlti3_test.zig"); | |
| 41 | } |
std/special/compiler_rt/ashlti3_test.zig created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | const __ashlti3 = @import("ashlti3.zig").__ashlti3; | |
| 2 | const testing = @import("std").testing; | |
| 3 | ||
| 4 | fn test__ashlti3(a: i128, b: i32, expected: i128) void { | |
| 5 | const x = __ashlti3(a, b); | |
| 6 | testing.expect(x == expected); | |
| 7 | } | |
| 8 | ||
| 9 | test "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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | ||
| 4 | pub 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 | ||
| 24 | const 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 | ||
| 40 | test "import ashrti3" { | |
| 41 | _ = @import("ashrti3_test.zig"); | |
| 42 | } |
std/special/compiler_rt/ashrti3_test.zig created+58| ... | ... | @@ -0,0 +1,58 @@ |
| 1 | const __ashrti3 = @import("ashrti3.zig").__ashrti3; | |
| 2 | const testing = @import("std").testing; | |
| 3 | ||
| 4 | fn 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 | ||
| 11 | test "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 | ||
| 5 | const std = @import("std"); | |
| 6 | const builtin = @import("builtin"); | |
| 7 | const is_test = builtin.is_test; | |
| 8 | ||
| 9 | const fp_t = f64; | |
| 10 | const rep_t = u64; | |
| 11 | const srep_t = i64; | |
| 12 | ||
| 13 | const typeWidth = rep_t.bit_count; | |
| 14 | const significandBits = std.math.floatMantissaBits(fp_t); | |
| 15 | const exponentBits = std.math.floatExponentBits(fp_t); | |
| 16 | const signBit = (rep_t(1) << (significandBits + exponentBits)); | |
| 17 | const absMask = signBit - 1; | |
| 18 | const implicitBit = rep_t(1) << significandBits; | |
| 19 | const significandMask = implicitBit - 1; | |
| 20 | const exponentMask = absMask ^ significandMask; | |
| 21 | const 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 | |
| 25 | const LE_LESS = c_int(-1); | |
| 26 | const LE_EQUAL = c_int(0); | |
| 27 | const LE_GREATER = c_int(1); | |
| 28 | const LE_UNORDERED = c_int(1); | |
| 29 | ||
| 30 | pub 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 | |
| 68 | const GE_LESS = c_int(-1); | |
| 69 | const GE_EQUAL = c_int(0); | |
| 70 | const GE_GREATER = c_int(1); | |
| 71 | const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED | |
| 72 | ||
| 73 | pub 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 | ||
| 97 | pub 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 | ||
| 104 | pub extern fn __eqdf2(a: fp_t, b: fp_t) c_int { | |
| 105 | return __ledf2(a, b); | |
| 106 | } | |
| 107 | ||
| 108 | pub extern fn __ltdf2(a: fp_t, b: fp_t) c_int { | |
| 109 | return __ledf2(a, b); | |
| 110 | } | |
| 111 | ||
| 112 | pub extern fn __nedf2(a: fp_t, b: fp_t) c_int { | |
| 113 | return __ledf2(a, b); | |
| 114 | } | |
| 115 | ||
| 116 | pub extern fn __gtdf2(a: fp_t, b: fp_t) c_int { | |
| 117 | return __gedf2(a, b); | |
| 118 | } | |
| 119 | ||
| 120 | test "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 | ||
| 5 | const std = @import("std"); | |
| 6 | const builtin = @import("builtin"); | |
| 7 | const is_test = builtin.is_test; | |
| 8 | ||
| 9 | const comparedf2 = @import("comparedf2.zig"); | |
| 10 | ||
| 11 | const 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 | ||
| 23 | fn 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 | ||
| 48 | const 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 | ||
| 69 | fn 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 | ||
| 86 | const 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 | ||
| 97 | test "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 | ||
| 5 | const std = @import("std"); | |
| 6 | const builtin = @import("builtin"); | |
| 7 | const is_test = builtin.is_test; | |
| 8 | ||
| 9 | const fp_t = f32; | |
| 10 | const rep_t = u32; | |
| 11 | const srep_t = i32; | |
| 12 | ||
| 13 | const typeWidth = rep_t.bit_count; | |
| 14 | const significandBits = std.math.floatMantissaBits(fp_t); | |
| 15 | const exponentBits = std.math.floatExponentBits(fp_t); | |
| 16 | const signBit = (rep_t(1) << (significandBits + exponentBits)); | |
| 17 | const absMask = signBit - 1; | |
| 18 | const implicitBit = rep_t(1) << significandBits; | |
| 19 | const significandMask = implicitBit - 1; | |
| 20 | const exponentMask = absMask ^ significandMask; | |
| 21 | const 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 | |
| 25 | const LE_LESS = c_int(-1); | |
| 26 | const LE_EQUAL = c_int(0); | |
| 27 | const LE_GREATER = c_int(1); | |
| 28 | const LE_UNORDERED = c_int(1); | |
| 29 | ||
| 30 | pub 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 | |
| 68 | const GE_LESS = c_int(-1); | |
| 69 | const GE_EQUAL = c_int(0); | |
| 70 | const GE_GREATER = c_int(1); | |
| 71 | const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED | |
| 72 | ||
| 73 | pub 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 | ||
| 97 | pub 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 | ||
| 104 | pub extern fn __eqsf2(a: fp_t, b: fp_t) c_int { | |
| 105 | return __lesf2(a, b); | |
| 106 | } | |
| 107 | ||
| 108 | pub extern fn __ltsf2(a: fp_t, b: fp_t) c_int { | |
| 109 | return __lesf2(a, b); | |
| 110 | } | |
| 111 | ||
| 112 | pub extern fn __nesf2(a: fp_t, b: fp_t) c_int { | |
| 113 | return __lesf2(a, b); | |
| 114 | } | |
| 115 | ||
| 116 | pub extern fn __gtsf2(a: fp_t, b: fp_t) c_int { | |
| 117 | return __gesf2(a, b); | |
| 118 | } | |
| 119 | ||
| 120 | test "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 | ||
| 5 | const std = @import("std"); | |
| 6 | const builtin = @import("builtin"); | |
| 7 | const is_test = builtin.is_test; | |
| 8 | ||
| 9 | const comparesf2 = @import("comparesf2.zig"); | |
| 10 | ||
| 11 | const 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 | ||
| 23 | fn 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 | ||
| 48 | const 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 | ||
| 69 | fn 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 | ||
| 86 | const 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 | ||
| 97 | test "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 | 16 | return (@bitCast(i128, r) ^ s) -% s; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | pub extern fn __divti3_windows_x86_64(a: *const i128, b: *const i128) void { | |
| 20 | @setRuntimeSafety(builtin.is_test); | |
| 21 | compiler_rt.setXmm0(i128, __divti3(a.*, b.*)); | |
| 19 | const v128 = @Vector(2, u64); | |
| 20 | pub extern fn __divti3_windows_x86_64(a: v128, b: v128) v128 { | |
| 21 | return @bitCast(v128, @inlineCall(__divti3, @bitCast(i128, a), @bitCast(i128, b))); | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | test "import divti3" { |
std/special/compiler_rt/extendXfYf2.zig+10-4| ... | ... | @@ -2,21 +2,27 @@ const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const is_test = builtin.is_test; |
| 4 | 4 | |
| 5 | pub extern fn __extendsfdf2(a: f32) f64 { | |
| 6 | return @inlineCall(extendXfYf2, f64, f32, @bitCast(u32, a)); | |
| 7 | } | |
| 8 | ||
| 5 | 9 | pub extern fn __extenddftf2(a: f64) f128 { |
| 6 | return extendXfYf2(f128, f64, a); | |
| 10 | return @inlineCall(extendXfYf2, f128, f64, @bitCast(u64, a)); | |
| 7 | 11 | } |
| 8 | 12 | |
| 9 | 13 | pub extern fn __extendsftf2(a: f32) f128 { |
| 10 | return extendXfYf2(f128, f32, a); | |
| 14 | return @inlineCall(extendXfYf2, f128, f32, @bitCast(u32, a)); | |
| 11 | 15 | } |
| 12 | 16 | |
| 13 | 17 | pub extern fn __extendhfsf2(a: u16) f32 { |
| 14 | return extendXfYf2(f32, f16, @bitCast(f16, a)); | |
| 18 | return @inlineCall(extendXfYf2, f32, f16, a); | |
| 15 | 19 | } |
| 16 | 20 | |
| 17 | 21 | const CHAR_BIT = 8; |
| 18 | 22 | |
| 19 | inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { | |
| 23 | fn 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 | 26 | const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits); |
| 21 | 27 | const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits); |
| 22 | 28 | const srcSigBits = std.math.floatMantissaBits(src_t); |
std/special/compiler_rt/floatdidf.zig created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | ||
| 4 | const twop52: f64 = 0x1.0p52; | |
| 5 | const twop32: f64 = 0x1.0p32; | |
| 6 | ||
| 7 | pub 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 | ||
| 20 | test "import floatdidf" { | |
| 21 | _ = @import("floatdidf_test.zig"); | |
| 22 | } |
std/special/compiler_rt/floatdidf_test.zig created+53| ... | ... | @@ -0,0 +1,53 @@ |
| 1 | const __floatdidf = @import("floatdidf.zig").__floatdidf; | |
| 2 | const testing = @import("std").testing; | |
| 3 | ||
| 4 | fn test__floatdidf(a: i64, expected: f64) void { | |
| 5 | const r = __floatdidf(a); | |
| 6 | testing.expect(r == expected); | |
| 7 | } | |
| 8 | ||
| 9 | test "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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | const maxInt = std.math.maxInt; | |
| 4 | ||
| 5 | fn 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 | ||
| 56 | pub extern fn __floatsisf(arg: i32) f32 { | |
| 57 | @setRuntimeSafety(builtin.is_test); | |
| 58 | return @inlineCall(floatsiXf, f32, arg); | |
| 59 | } | |
| 60 | ||
| 61 | pub extern fn __floatsidf(arg: i32) f64 { | |
| 62 | @setRuntimeSafety(builtin.is_test); | |
| 63 | return @inlineCall(floatsiXf, f64, arg); | |
| 64 | } | |
| 65 | ||
| 66 | pub extern fn __floatsitf(arg: i32) f128 { | |
| 67 | @setRuntimeSafety(builtin.is_test); | |
| 68 | return @inlineCall(floatsiXf, f128, arg); | |
| 69 | } | |
| 70 | ||
| 71 | fn test_one_floatsitf(a: i32, expected: u128) void { | |
| 72 | const r = __floatsitf(a); | |
| 73 | std.testing.expect(@bitCast(u128, r) == expected); | |
| 74 | } | |
| 75 | ||
| 76 | fn test_one_floatsidf(a: i32, expected: u64) void { | |
| 77 | const r = __floatsidf(a); | |
| 78 | std.testing.expect(@bitCast(u64, r) == expected); | |
| 79 | } | |
| 80 | ||
| 81 | fn test_one_floatsisf(a: i32, expected: u32) void { | |
| 82 | const r = __floatsisf(a); | |
| 83 | std.testing.expect(@bitCast(u32, r) == expected); | |
| 84 | } | |
| 85 | ||
| 86 | test "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 | ||
| 94 | test "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 | ||
| 102 | test "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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | ||
| 4 | const twop52: f64 = 0x1.0p52; | |
| 5 | const twop84: f64 = 0x1.0p84; | |
| 6 | const twop84_plus_twop52: f64 = 0x1.00000001p84; | |
| 7 | ||
| 8 | pub 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 | ||
| 22 | test "import floatundidf" { | |
| 23 | _ = @import("floatundidf_test.zig"); | |
| 24 | } |
std/special/compiler_rt/floatundidf_test.zig created+50| ... | ... | @@ -0,0 +1,50 @@ |
| 1 | const __floatundidf = @import("floatundidf.zig").__floatundidf; | |
| 2 | const testing = @import("std").testing; | |
| 3 | ||
| 4 | fn test__floatundidf(a: u64, expected: f64) void { | |
| 5 | const r = __floatundidf(a); | |
| 6 | testing.expect(r == expected); | |
| 7 | } | |
| 8 | ||
| 9 | test "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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | const maxInt = std.math.maxInt; | |
| 4 | ||
| 5 | const implicitBit = u64(1) << 52; | |
| 6 | ||
| 7 | pub 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 | ||
| 21 | fn test_one_floatunsidf(a: u32, expected: u64) void { | |
| 22 | const r = __floatunsidf(a); | |
| 23 | std.testing.expect(@bitCast(u64, r) == expected); | |
| 24 | } | |
| 25 | ||
| 26 | test "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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | ||
| 4 | pub 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 | ||
| 23 | const 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 | ||
| 39 | test "import lshrti3" { | |
| 40 | _ = @import("lshrti3_test.zig"); | |
| 41 | } |
std/special/compiler_rt/lshrti3_test.zig created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | const __lshrti3 = @import("lshrti3.zig").__lshrti3; | |
| 2 | const testing = @import("std").testing; | |
| 3 | ||
| 4 | fn test__lshrti3(a: i128, b: i32, expected: i128) void { | |
| 5 | const x = __lshrti3(a, b); | |
| 6 | testing.expect(x == expected); | |
| 7 | } | |
| 8 | ||
| 9 | test "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 | 20 | return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -1 |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | pub extern fn __modti3_windows_x86_64(a: *const i128, b: *const i128) void { | |
| 24 | @setRuntimeSafety(builtin.is_test); | |
| 25 | compiler_rt.setXmm0(i128, __modti3(a.*, b.*)); | |
| 23 | const v128 = @Vector(2, u64); | |
| 24 | pub extern fn __modti3_windows_x86_64(a: v128, b: v128) v128 { | |
| 25 | return @bitCast(v128, @inlineCall(__modti3, @bitCast(i128, a), @bitCast(i128, b))); | |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | test "import modti3" { |
std/special/compiler_rt/mulodi4.zig created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const maxInt = std.math.maxInt; | |
| 4 | const minInt = std.math.minInt; | |
| 5 | ||
| 6 | pub 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 | ||
| 42 | test "import mulodi4" { | |
| 43 | _ = @import("mulodi4_test.zig"); | |
| 44 | } |
std/special/compiler_rt/mulodi4_test.zig created+85| ... | ... | @@ -0,0 +1,85 @@ |
| 1 | const __mulodi4 = @import("mulodi4.zig").__mulodi4; | |
| 2 | const testing = @import("std").testing; | |
| 3 | ||
| 4 | fn 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 | ||
| 10 | test "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 | const udivmod = @import("udivmod.zig").udivmod; | |
| 2 | 1 | const builtin = @import("builtin"); |
| 3 | 2 | const compiler_rt = @import("../compiler_rt.zig"); |
| 4 | 3 | |
| ... | ... | @@ -33,11 +32,11 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 { |
| 33 | 32 | } |
| 34 | 33 | |
| 35 | 34 | if (sa == sb) { |
| 36 | if (abs_a > @divFloor(max, abs_b)) { | |
| 35 | if (abs_a > @divTrunc(max, abs_b)) { | |
| 37 | 36 | overflow.* = 1; |
| 38 | 37 | } |
| 39 | 38 | } else { |
| 40 | if (abs_a > @divFloor(min, -abs_b)) { | |
| 39 | if (abs_a > @divTrunc(min, -abs_b)) { | |
| 41 | 40 | overflow.* = 1; |
| 42 | 41 | } |
| 43 | 42 | } |
| ... | ... | @@ -45,11 +44,6 @@ pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 { |
| 45 | 44 | return r; |
| 46 | 45 | } |
| 47 | 46 | |
| 48 | pub 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 | ||
| 53 | 47 | test "import muloti4" { |
| 54 | 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 | 14 | return r.all; |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | pub extern fn __multi3_windows_x86_64(a: *const i128, b: *const i128) void { | |
| 18 | @setRuntimeSafety(builtin.is_test); | |
| 19 | compiler_rt.setXmm0(i128, __multi3(a.*, b.*)); | |
| 17 | const v128 = @Vector(2, u64); | |
| 18 | pub extern fn __multi3_windows_x86_64(a: v128, b: v128) v128 { | |
| 19 | return @bitCast(v128, @inlineCall(__multi3, @bitCast(i128, a), @bitCast(i128, b))); | |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | fn __mulddi3(a: u64, b: u64) i128 { |
std/special/compiler_rt/stack_probe.zig created+206| ... | ... | @@ -0,0 +1,206 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | // Zig's own stack-probe routine (available only on x86 and x86_64) | |
| 4 | pub 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 | ||
| 60 | fn 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 | ||
| 112 | fn 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 | ||
| 183 | pub nakedcc fn _chkstk() void { | |
| 184 | @setRuntimeSafety(false); | |
| 185 | @inlineCall(win_probe_stack_adjust_sp); | |
| 186 | } | |
| 187 | pub 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 | } | |
| 195 | pub nakedcc fn ___chkstk() void { | |
| 196 | @setRuntimeSafety(false); | |
| 197 | @inlineCall(win_probe_stack_adjust_sp); | |
| 198 | } | |
| 199 | pub nakedcc fn __chkstk_ms() void { | |
| 200 | @setRuntimeSafety(false); | |
| 201 | @inlineCall(win_probe_stack_only); | |
| 202 | } | |
| 203 | pub 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 | 16 | return truncXfYf2(f64, f128, a); |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | pub extern fn __truncdfsf2(a: f64) f32 { | |
| 20 | return truncXfYf2(f32, f64, a); | |
| 21 | } | |
| 22 | ||
| 19 | 23 | inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { |
| 20 | 24 | const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits); |
| 21 | 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 | 200 | test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); |
| 201 | 201 | test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); |
| 202 | 202 | } |
| 203 | ||
| 204 | const __truncdfsf2 = @import("truncXfYf2.zig").__truncdfsf2; | |
| 205 | ||
| 206 | fn 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 | ||
| 225 | test "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 | 7 | return udivmod(u128, a, b, maybe_rem); |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | pub extern fn __udivmodti4_windows_x86_64(a: *const u128, b: *const u128, maybe_rem: ?*u128) void { | |
| 10 | const v128 = @Vector(2, u64); | |
| 11 | pub extern fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) v128 { | |
| 11 | 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 | } |
| 14 | 15 | |
| 15 | 16 | test "import udivmodti4" { |
std/special/compiler_rt/udivti3.zig+3-2| ... | ... | @@ -6,7 +6,8 @@ pub extern fn __udivti3(a: u128, b: u128) u128 { |
| 6 | 6 | return udivmodti4.__udivmodti4(a, b, null); |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | pub extern fn __udivti3_windows_x86_64(a: *const u128, b: *const u128) void { | |
| 9 | const v128 = @Vector(2, u64); | |
| 10 | pub extern fn __udivti3_windows_x86_64(a: v128, b: v128) v128 { | |
| 10 | 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 | 9 | return r; |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | pub extern fn __umodti3_windows_x86_64(a: *const u128, b: *const u128) void { | |
| 13 | @setRuntimeSafety(builtin.is_test); | |
| 14 | compiler_rt.setXmm0(u128, __umodti3(a.*, b.*)); | |
| 12 | const v128 = @Vector(2, u64); | |
| 13 | pub extern fn __umodti3_windows_x86_64(a: v128, b: v128) v128 { | |
| 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | ||
| 4 | const os = std.os; | |
| 5 | const io = std.io; | |
| 6 | const mem = std.mem; | |
| 7 | const Allocator = mem.Allocator; | |
| 8 | const ArrayList = std.ArrayList; | |
| 9 | const Buffer = std.Buffer; | |
| 10 | const ast = std.zig.ast; | |
| 11 | ||
| 12 | const arg = @import("fmt/arg.zig"); | |
| 13 | const self_hosted_main = @import("fmt/main.zig"); | |
| 14 | const Args = arg.Args; | |
| 15 | const Flag = arg.Flag; | |
| 16 | const errmsg = @import("fmt/errmsg.zig"); | |
| 17 | ||
| 18 | var stderr_file: os.File = undefined; | |
| 19 | var stderr: *io.OutStream(os.File.WriteError) = undefined; | |
| 20 | var stdout: *io.OutStream(os.File.WriteError) = undefined; | |
| 21 | ||
| 22 | // This brings `zig fmt` to stage 1. | |
| 23 | pub 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 | ||
| 119 | const 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 | ||
| 140 | fn 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 | ||
| 204 | const 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 | ||
| 213 | fn 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 | 9 | pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { |
| 10 | 10 | @setCold(true); |
| 11 | 11 | switch (builtin.os) { |
| 12 | // TODO: fix panic in zen. | |
| 12 | // TODO: fix panic in zen | |
| 13 | 13 | builtin.Os.freestanding, builtin.Os.zen => { |
| 14 | 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 | 21 | builtin.Os.uefi => { |
| 17 | 22 | // TODO look into using the debug info and logging helpful messages |
| 18 | 23 | std.os.abort(); |
std/special/test_runner.zig+1-1| ... | ... | @@ -8,7 +8,7 @@ pub fn main() !void { |
| 8 | 8 | var ok_count: usize = 0; |
| 9 | 9 | var skip_count: usize = 0; |
| 10 | 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); | |
| 12 | 12 | |
| 13 | 13 | if (test_fn.func()) |_| { |
| 14 | 14 | ok_count += 1; |
std/std.zig+7| ... | ... | @@ -9,6 +9,10 @@ pub const DynLib = @import("dynamic_library.zig").DynLib; |
| 9 | 9 | pub const HashMap = @import("hash_map.zig").HashMap; |
| 10 | 10 | pub const LinkedList = @import("linked_list.zig").LinkedList; |
| 11 | 11 | pub const Mutex = @import("mutex.zig").Mutex; |
| 12 | pub const PackedIntArrayEndian = @import("packed_int_array.zig").PackedIntArrayEndian; | |
| 13 | pub const PackedIntArray = @import("packed_int_array.zig").PackedIntArray; | |
| 14 | pub const PackedIntSliceEndian = @import("packed_int_array.zig").PackedIntSliceEndian; | |
| 15 | pub const PackedIntSlice = @import("packed_int_array.zig").PackedIntSlice; | |
| 12 | 16 | pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue; |
| 13 | 17 | pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex; |
| 14 | 18 | pub const SegmentedList = @import("segmented_list.zig").SegmentedList; |
| ... | ... | @@ -87,6 +91,7 @@ test "std" { |
| 87 | 91 | _ = @import("net.zig"); |
| 88 | 92 | _ = @import("os.zig"); |
| 89 | 93 | _ = @import("pdb.zig"); |
| 94 | _ = @import("packed_int_array.zig"); | |
| 90 | 95 | _ = @import("priority_queue.zig"); |
| 91 | 96 | _ = @import("rand.zig"); |
| 92 | 97 | _ = @import("sort.zig"); |
| ... | ... | @@ -94,4 +99,6 @@ test "std" { |
| 94 | 99 | _ = @import("unicode.zig"); |
| 95 | 100 | _ = @import("valgrind.zig"); |
| 96 | 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 | 18 | pub const ErrorList = SegmentedList(Error, 0); |
| 19 | 19 | |
| 20 | 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 | } |
| 23 | 27 | |
| 24 | 28 | pub fn renderError(self: *Tree, parse_error: *Error, stream: var) !void { |
| ... | ... | @@ -551,7 +555,6 @@ pub const Node = struct { |
| 551 | 555 | doc_comments: ?*DocComment, |
| 552 | 556 | decls: DeclList, |
| 553 | 557 | eof_token: TokenIndex, |
| 554 | shebang: ?TokenIndex, | |
| 555 | 558 | |
| 556 | 559 | pub const DeclList = SegmentedList(*Node, 4); |
| 557 | 560 | |
| ... | ... | @@ -563,7 +566,6 @@ pub const Node = struct { |
| 563 | 566 | } |
| 564 | 567 | |
| 565 | 568 | pub fn firstToken(self: *const Root) TokenIndex { |
| 566 | if (self.shebang) |shebang| return shebang; | |
| 567 | 569 | return if (self.decls.len == 0) self.eof_token else (self.decls.at(0).*).firstToken(); |
| 568 | 570 | } |
| 569 | 571 | |
| ... | ... | @@ -2307,7 +2309,6 @@ test "iterate" { |
| 2307 | 2309 | .doc_comments = null, |
| 2308 | 2310 | .decls = Node.Root.DeclList.init(std.debug.global_allocator), |
| 2309 | 2311 | .eof_token = 0, |
| 2310 | .shebang = null, | |
| 2311 | 2312 | }; |
| 2312 | 2313 | var base = &root.base; |
| 2313 | 2314 | testing.expect(base.iterate(0) == null); |
std/zig/parse.zig+179-159| ... | ... | @@ -9,7 +9,7 @@ const Error = ast.Error; |
| 9 | 9 | |
| 10 | 10 | /// Result should be freed with tree.deinit() when there are |
| 11 | 11 | /// no more references to any of the tokens or nodes. |
| 12 | pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | |
| 12 | pub fn parse(allocator: *mem.Allocator, source: []const u8) !*ast.Tree { | |
| 13 | 13 | var tree_arena = std.heap.ArenaAllocator.init(allocator); |
| 14 | 14 | errdefer tree_arena.deinit(); |
| 15 | 15 | |
| ... | ... | @@ -22,12 +22,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 22 | 22 | .base = ast.Node{ .id = ast.Node.Id.Root }, |
| 23 | 23 | .decls = ast.Node.Root.DeclList.init(arena), |
| 24 | 24 | .doc_comments = null, |
| 25 | .shebang = null, | |
| 26 | 25 | // initialized when we get the eof token |
| 27 | 26 | .eof_token = undefined, |
| 28 | 27 | }; |
| 29 | 28 | |
| 30 | var tree = ast.Tree{ | |
| 29 | const tree = try arena.create(ast.Tree); | |
| 30 | tree.* = ast.Tree{ | |
| 31 | 31 | .source = source, |
| 32 | 32 | .root_node = root_node, |
| 33 | 33 | .arena_allocator = tree_arena, |
| ... | ... | @@ -43,15 +43,6 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 43 | 43 | } |
| 44 | 44 | var tok_it = tree.tokens.iterator(0); |
| 45 | 45 | |
| 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 | 46 | // skip over line comments at the top of the file |
| 56 | 47 | while (true) { |
| 57 | 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 | 58 | |
| 68 | 59 | switch (state) { |
| 69 | 60 | State.TopLevel => { |
| 70 | const comments = try eatDocComments(arena, &tok_it, &tree); | |
| 61 | const comments = try eatDocComments(arena, &tok_it, tree); | |
| 71 | 62 | |
| 72 | const token = nextToken(&tok_it, &tree); | |
| 63 | const token = nextToken(&tok_it, tree); | |
| 73 | 64 | const token_index = token.index; |
| 74 | 65 | const token_ptr = token.ptr; |
| 75 | 66 | switch (token_ptr.id) { |
| ... | ... | @@ -150,7 +141,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 150 | 141 | continue; |
| 151 | 142 | }, |
| 152 | 143 | else => { |
| 153 | prevToken(&tok_it, &tree); | |
| 144 | prevToken(&tok_it, tree); | |
| 154 | 145 | stack.append(State.TopLevel) catch unreachable; |
| 155 | 146 | try stack.append(State{ |
| 156 | 147 | .TopLevelExtern = TopLevelDeclCtx{ |
| ... | ... | @@ -166,7 +157,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 166 | 157 | } |
| 167 | 158 | }, |
| 168 | 159 | State.TopLevelExtern => |ctx| { |
| 169 | const token = nextToken(&tok_it, &tree); | |
| 160 | const token = nextToken(&tok_it, tree); | |
| 170 | 161 | const token_index = token.index; |
| 171 | 162 | const token_ptr = token.ptr; |
| 172 | 163 | switch (token_ptr.id) { |
| ... | ... | @@ -201,7 +192,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 201 | 192 | continue; |
| 202 | 193 | }, |
| 203 | 194 | else => { |
| 204 | prevToken(&tok_it, &tree); | |
| 195 | prevToken(&tok_it, tree); | |
| 205 | 196 | stack.append(State{ .TopLevelDecl = ctx }) catch unreachable; |
| 206 | 197 | continue; |
| 207 | 198 | }, |
| ... | ... | @@ -209,11 +200,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 209 | 200 | }, |
| 210 | 201 | State.TopLevelLibname => |ctx| { |
| 211 | 202 | const lib_name = blk: { |
| 212 | const lib_name_token = nextToken(&tok_it, &tree); | |
| 203 | const lib_name_token = nextToken(&tok_it, tree); | |
| 213 | 204 | const lib_name_token_index = lib_name_token.index; |
| 214 | 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 { | |
| 216 | prevToken(&tok_it, &tree); | |
| 206 | break :blk (try parseStringLiteral(arena, &tok_it, lib_name_token_ptr, lib_name_token_index, tree)) orelse { | |
| 207 | prevToken(&tok_it, tree); | |
| 217 | 208 | break :blk null; |
| 218 | 209 | }; |
| 219 | 210 | }; |
| ... | ... | @@ -230,7 +221,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 230 | 221 | continue; |
| 231 | 222 | }, |
| 232 | 223 | State.ThreadLocal => |ctx| { |
| 233 | const token = nextToken(&tok_it, &tree); | |
| 224 | const token = nextToken(&tok_it, tree); | |
| 234 | 225 | const token_index = token.index; |
| 235 | 226 | const token_ptr = token.ptr; |
| 236 | 227 | switch (token_ptr.id) { |
| ... | ... | @@ -256,7 +247,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 256 | 247 | } |
| 257 | 248 | }, |
| 258 | 249 | State.TopLevelDecl => |ctx| { |
| 259 | const token = nextToken(&tok_it, &tree); | |
| 250 | const token = nextToken(&tok_it, tree); | |
| 260 | 251 | const token_index = token.index; |
| 261 | 252 | const token_ptr = token.ptr; |
| 262 | 253 | switch (token_ptr.id) { |
| ... | ... | @@ -397,7 +388,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 397 | 388 | } |
| 398 | 389 | }, |
| 399 | 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 | 392 | const node = try arena.create(ast.Node.StructField); |
| 402 | 393 | node.* = ast.Node.StructField{ |
| 403 | 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 | 425 | }, |
| 435 | 426 | |
| 436 | 427 | State.FieldInitValue => |ctx| { |
| 437 | const eq_tok = nextToken(&tok_it, &tree); | |
| 428 | const eq_tok = nextToken(&tok_it, tree); | |
| 438 | 429 | const eq_tok_index = eq_tok.index; |
| 439 | 430 | const eq_tok_ptr = eq_tok.ptr; |
| 440 | 431 | if (eq_tok_ptr.id != Token.Id.Equal) { |
| 441 | prevToken(&tok_it, &tree); | |
| 432 | prevToken(&tok_it, tree); | |
| 442 | 433 | continue; |
| 443 | 434 | } |
| 444 | 435 | stack.append(State{ .Expression = ctx }) catch unreachable; |
| ... | ... | @@ -446,7 +437,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 446 | 437 | }, |
| 447 | 438 | |
| 448 | 439 | State.ContainerKind => |ctx| { |
| 449 | const token = nextToken(&tok_it, &tree); | |
| 440 | const token = nextToken(&tok_it, tree); | |
| 450 | 441 | const token_index = token.index; |
| 451 | 442 | const token_ptr = token.ptr; |
| 452 | 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 | 470 | }, |
| 480 | 471 | |
| 481 | 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 | 474 | continue; |
| 484 | 475 | } |
| 485 | 476 | |
| ... | ... | @@ -489,24 +480,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 489 | 480 | }, |
| 490 | 481 | |
| 491 | 482 | State.ContainerInitArg => |container_decl| { |
| 492 | const init_arg_token = nextToken(&tok_it, &tree); | |
| 483 | const init_arg_token = nextToken(&tok_it, tree); | |
| 493 | 484 | const init_arg_token_index = init_arg_token.index; |
| 494 | 485 | const init_arg_token_ptr = init_arg_token.ptr; |
| 495 | 486 | switch (init_arg_token_ptr.id) { |
| 496 | 487 | Token.Id.Keyword_enum => { |
| 497 | 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 | 490 | const lparen_tok_index = lparen_tok.index; |
| 500 | 491 | const lparen_tok_ptr = lparen_tok.ptr; |
| 501 | 492 | if (lparen_tok_ptr.id == Token.Id.LParen) { |
| 502 | 493 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); |
| 503 | 494 | try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &container_decl.init_arg_expr.Enum } }); |
| 504 | 495 | } else { |
| 505 | prevToken(&tok_it, &tree); | |
| 496 | prevToken(&tok_it, tree); | |
| 506 | 497 | } |
| 507 | 498 | }, |
| 508 | 499 | else => { |
| 509 | prevToken(&tok_it, &tree); | |
| 500 | prevToken(&tok_it, tree); | |
| 510 | 501 | container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Type = undefined }; |
| 511 | 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 | 506 | }, |
| 516 | 507 | |
| 517 | 508 | State.ContainerDecl => |container_decl| { |
| 518 | const comments = try eatDocComments(arena, &tok_it, &tree); | |
| 519 | const token = nextToken(&tok_it, &tree); | |
| 509 | const comments = try eatDocComments(arena, &tok_it, tree); | |
| 510 | const token = nextToken(&tok_it, tree); | |
| 520 | 511 | const token_index = token.index; |
| 521 | 512 | const token_ptr = token.ptr; |
| 522 | 513 | switch (token_ptr.id) { |
| ... | ... | @@ -629,6 +620,35 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 629 | 620 | }); |
| 630 | 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 | 652 | Token.Id.RBrace => { |
| 633 | 653 | if (comments != null) { |
| 634 | 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 | 658 | continue; |
| 639 | 659 | }, |
| 640 | 660 | else => { |
| 641 | prevToken(&tok_it, &tree); | |
| 661 | prevToken(&tok_it, tree); | |
| 642 | 662 | stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; |
| 643 | 663 | try stack.append(State{ |
| 644 | 664 | .TopLevelExtern = TopLevelDeclCtx{ |
| ... | ... | @@ -690,7 +710,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 690 | 710 | State.VarDeclAlign => |var_decl| { |
| 691 | 711 | try stack.append(State{ .VarDeclSection = var_decl }); |
| 692 | 712 | |
| 693 | const next_token = nextToken(&tok_it, &tree); | |
| 713 | const next_token = nextToken(&tok_it, tree); | |
| 694 | 714 | const next_token_index = next_token.index; |
| 695 | 715 | const next_token_ptr = next_token.ptr; |
| 696 | 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 | 720 | continue; |
| 701 | 721 | } |
| 702 | 722 | |
| 703 | prevToken(&tok_it, &tree); | |
| 723 | prevToken(&tok_it, tree); | |
| 704 | 724 | continue; |
| 705 | 725 | }, |
| 706 | 726 | State.VarDeclSection => |var_decl| { |
| 707 | 727 | try stack.append(State{ .VarDeclEq = var_decl }); |
| 708 | 728 | |
| 709 | const next_token = nextToken(&tok_it, &tree); | |
| 729 | const next_token = nextToken(&tok_it, tree); | |
| 710 | 730 | const next_token_index = next_token.index; |
| 711 | 731 | const next_token_ptr = next_token.ptr; |
| 712 | 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 | 736 | continue; |
| 717 | 737 | } |
| 718 | 738 | |
| 719 | prevToken(&tok_it, &tree); | |
| 739 | prevToken(&tok_it, tree); | |
| 720 | 740 | continue; |
| 721 | 741 | }, |
| 722 | 742 | State.VarDeclEq => |var_decl| { |
| 723 | const token = nextToken(&tok_it, &tree); | |
| 743 | const token = nextToken(&tok_it, tree); | |
| 724 | 744 | const token_index = token.index; |
| 725 | 745 | const token_ptr = token.ptr; |
| 726 | 746 | switch (token_ptr.id) { |
| ... | ... | @@ -742,7 +762,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 742 | 762 | }, |
| 743 | 763 | |
| 744 | 764 | State.VarDeclSemiColon => |var_decl| { |
| 745 | const semicolon_token = nextToken(&tok_it, &tree); | |
| 765 | const semicolon_token = nextToken(&tok_it, tree); | |
| 746 | 766 | |
| 747 | 767 | if (semicolon_token.ptr.id != Token.Id.Semicolon) { |
| 748 | 768 | ((try tree.errors.addOne())).* = Error{ |
| ... | ... | @@ -756,18 +776,18 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 756 | 776 | |
| 757 | 777 | var_decl.semicolon_token = semicolon_token.index; |
| 758 | 778 | |
| 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 | 780 | const loc = tree.tokenLocation(semicolon_token.ptr.end, doc_comment_token); |
| 761 | 781 | if (loc.line == 0) { |
| 762 | 782 | try pushDocComment(arena, doc_comment_token, &var_decl.doc_comments); |
| 763 | 783 | } else { |
| 764 | prevToken(&tok_it, &tree); | |
| 784 | prevToken(&tok_it, tree); | |
| 765 | 785 | } |
| 766 | 786 | } |
| 767 | 787 | }, |
| 768 | 788 | |
| 769 | 789 | State.FnDef => |fn_proto| { |
| 770 | const token = nextToken(&tok_it, &tree); | |
| 790 | const token = nextToken(&tok_it, tree); | |
| 771 | 791 | const token_index = token.index; |
| 772 | 792 | const token_ptr = token.ptr; |
| 773 | 793 | switch (token_ptr.id) { |
| ... | ... | @@ -796,7 +816,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 796 | 816 | try stack.append(State{ .ParamDecl = fn_proto }); |
| 797 | 817 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); |
| 798 | 818 | |
| 799 | if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |name_token| { | |
| 819 | if (eatToken(&tok_it, tree, Token.Id.Identifier)) |name_token| { | |
| 800 | 820 | fn_proto.name_token = name_token; |
| 801 | 821 | } |
| 802 | 822 | continue; |
| ... | ... | @@ -804,7 +824,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 804 | 824 | State.FnProtoAlign => |fn_proto| { |
| 805 | 825 | stack.append(State{ .FnProtoSection = fn_proto }) catch unreachable; |
| 806 | 826 | |
| 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 | 828 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); |
| 809 | 829 | try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.align_expr } }); |
| 810 | 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 | 834 | State.FnProtoSection => |fn_proto| { |
| 815 | 835 | stack.append(State{ .FnProtoReturnType = fn_proto }) catch unreachable; |
| 816 | 836 | |
| 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 | 838 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); |
| 819 | 839 | try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.section_expr } }); |
| 820 | 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 | 842 | continue; |
| 823 | 843 | }, |
| 824 | 844 | State.FnProtoReturnType => |fn_proto| { |
| 825 | const token = nextToken(&tok_it, &tree); | |
| 845 | const token = nextToken(&tok_it, tree); | |
| 826 | 846 | const token_index = token.index; |
| 827 | 847 | const token_ptr = token.ptr; |
| 828 | 848 | switch (token_ptr.id) { |
| ... | ... | @@ -845,7 +865,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 845 | 865 | } |
| 846 | 866 | } |
| 847 | 867 | |
| 848 | prevToken(&tok_it, &tree); | |
| 868 | prevToken(&tok_it, tree); | |
| 849 | 869 | fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = undefined }; |
| 850 | 870 | stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.Explicit } }) catch unreachable; |
| 851 | 871 | continue; |
| ... | ... | @@ -854,8 +874,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 854 | 874 | }, |
| 855 | 875 | |
| 856 | 876 | State.ParamDecl => |fn_proto| { |
| 857 | const comments = try eatDocComments(arena, &tok_it, &tree); | |
| 858 | if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| { | |
| 877 | const comments = try eatDocComments(arena, &tok_it, tree); | |
| 878 | if (eatToken(&tok_it, tree, Token.Id.RParen)) |_| { | |
| 859 | 879 | continue; |
| 860 | 880 | } |
| 861 | 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 | 901 | continue; |
| 882 | 902 | }, |
| 883 | 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 | 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 | 907 | param_decl.noalias_token = noalias_token; |
| 888 | 908 | } |
| 889 | 909 | continue; |
| ... | ... | @@ -891,20 +911,20 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 891 | 911 | State.ParamDeclName => |param_decl| { |
| 892 | 912 | // TODO: Here, we eat two tokens in one state. This means that we can't have |
| 893 | 913 | // comments between these two tokens. |
| 894 | if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |ident_token| { | |
| 895 | if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| { | |
| 914 | if (eatToken(&tok_it, tree, Token.Id.Identifier)) |ident_token| { | |
| 915 | if (eatToken(&tok_it, tree, Token.Id.Colon)) |_| { | |
| 896 | 916 | param_decl.name_token = ident_token; |
| 897 | 917 | } else { |
| 898 | prevToken(&tok_it, &tree); | |
| 918 | prevToken(&tok_it, tree); | |
| 899 | 919 | } |
| 900 | 920 | } |
| 901 | 921 | continue; |
| 902 | 922 | }, |
| 903 | 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 | 925 | ctx.param_decl.var_args_token = ellipsis3; |
| 906 | 926 | |
| 907 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) { | |
| 927 | switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RParen)) { | |
| 908 | 928 | ExpectCommaOrEndResult.end_token => |t| { |
| 909 | 929 | if (t == null) { |
| 910 | 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 | 944 | continue; |
| 925 | 945 | }, |
| 926 | 946 | State.ParamDeclComma => |fn_proto| { |
| 927 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) { | |
| 947 | switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RParen)) { | |
| 928 | 948 | ExpectCommaOrEndResult.end_token => |t| { |
| 929 | 949 | if (t == null) { |
| 930 | 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 | 959 | }, |
| 940 | 960 | |
| 941 | 961 | State.MaybeLabeledExpression => |ctx| { |
| 942 | if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| { | |
| 962 | if (eatToken(&tok_it, tree, Token.Id.Colon)) |_| { | |
| 943 | 963 | stack.append(State{ |
| 944 | 964 | .LabeledExpression = LabelCtx{ |
| 945 | 965 | .label = ctx.label, |
| ... | ... | @@ -953,7 +973,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 953 | 973 | continue; |
| 954 | 974 | }, |
| 955 | 975 | State.LabeledExpression => |ctx| { |
| 956 | const token = nextToken(&tok_it, &tree); | |
| 976 | const token = nextToken(&tok_it, tree); | |
| 957 | 977 | const token_index = token.index; |
| 958 | 978 | const token_ptr = token.ptr; |
| 959 | 979 | switch (token_ptr.id) { |
| ... | ... | @@ -1008,13 +1028,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1008 | 1028 | return tree; |
| 1009 | 1029 | } |
| 1010 | 1030 | |
| 1011 | prevToken(&tok_it, &tree); | |
| 1031 | prevToken(&tok_it, tree); | |
| 1012 | 1032 | continue; |
| 1013 | 1033 | }, |
| 1014 | 1034 | } |
| 1015 | 1035 | }, |
| 1016 | 1036 | State.Inline => |ctx| { |
| 1017 | const token = nextToken(&tok_it, &tree); | |
| 1037 | const token = nextToken(&tok_it, tree); | |
| 1018 | 1038 | const token_index = token.index; |
| 1019 | 1039 | const token_ptr = token.ptr; |
| 1020 | 1040 | switch (token_ptr.id) { |
| ... | ... | @@ -1046,7 +1066,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1046 | 1066 | return tree; |
| 1047 | 1067 | } |
| 1048 | 1068 | |
| 1049 | prevToken(&tok_it, &tree); | |
| 1069 | prevToken(&tok_it, tree); | |
| 1050 | 1070 | continue; |
| 1051 | 1071 | }, |
| 1052 | 1072 | } |
| ... | ... | @@ -1103,7 +1123,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1103 | 1123 | continue; |
| 1104 | 1124 | }, |
| 1105 | 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 | 1127 | const node = try arena.create(ast.Node.Else); |
| 1108 | 1128 | node.* = ast.Node.Else{ |
| 1109 | 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 | 1142 | }, |
| 1123 | 1143 | |
| 1124 | 1144 | State.Block => |block| { |
| 1125 | const token = nextToken(&tok_it, &tree); | |
| 1145 | const token = nextToken(&tok_it, tree); | |
| 1126 | 1146 | const token_index = token.index; |
| 1127 | 1147 | const token_ptr = token.ptr; |
| 1128 | 1148 | switch (token_ptr.id) { |
| ... | ... | @@ -1131,7 +1151,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1131 | 1151 | continue; |
| 1132 | 1152 | }, |
| 1133 | 1153 | else => { |
| 1134 | prevToken(&tok_it, &tree); | |
| 1154 | prevToken(&tok_it, tree); | |
| 1135 | 1155 | stack.append(State{ .Block = block }) catch unreachable; |
| 1136 | 1156 | |
| 1137 | 1157 | try stack.append(State{ .Statement = block }); |
| ... | ... | @@ -1140,7 +1160,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1140 | 1160 | } |
| 1141 | 1161 | }, |
| 1142 | 1162 | State.Statement => |block| { |
| 1143 | const token = nextToken(&tok_it, &tree); | |
| 1163 | const token = nextToken(&tok_it, tree); | |
| 1144 | 1164 | const token_index = token.index; |
| 1145 | 1165 | const token_ptr = token.ptr; |
| 1146 | 1166 | switch (token_ptr.id) { |
| ... | ... | @@ -1197,7 +1217,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1197 | 1217 | continue; |
| 1198 | 1218 | }, |
| 1199 | 1219 | else => { |
| 1200 | prevToken(&tok_it, &tree); | |
| 1220 | prevToken(&tok_it, tree); | |
| 1201 | 1221 | const statement = try block.statements.addOne(); |
| 1202 | 1222 | try stack.append(State{ .Semicolon = statement }); |
| 1203 | 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 | 1226 | } |
| 1207 | 1227 | }, |
| 1208 | 1228 | State.ComptimeStatement => |ctx| { |
| 1209 | const token = nextToken(&tok_it, &tree); | |
| 1229 | const token = nextToken(&tok_it, tree); | |
| 1210 | 1230 | const token_index = token.index; |
| 1211 | 1231 | const token_ptr = token.ptr; |
| 1212 | 1232 | switch (token_ptr.id) { |
| ... | ... | @@ -1226,8 +1246,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1226 | 1246 | continue; |
| 1227 | 1247 | }, |
| 1228 | 1248 | else => { |
| 1229 | prevToken(&tok_it, &tree); | |
| 1230 | prevToken(&tok_it, &tree); | |
| 1249 | prevToken(&tok_it, tree); | |
| 1250 | prevToken(&tok_it, tree); | |
| 1231 | 1251 | const statement = try ctx.block.statements.addOne(); |
| 1232 | 1252 | try stack.append(State{ .Semicolon = statement }); |
| 1233 | 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 | 1265 | }, |
| 1246 | 1266 | |
| 1247 | 1267 | State.AsmOutputItems => |items| { |
| 1248 | const lbracket = nextToken(&tok_it, &tree); | |
| 1268 | const lbracket = nextToken(&tok_it, tree); | |
| 1249 | 1269 | const lbracket_index = lbracket.index; |
| 1250 | 1270 | const lbracket_ptr = lbracket.ptr; |
| 1251 | 1271 | if (lbracket_ptr.id != Token.Id.LBracket) { |
| 1252 | prevToken(&tok_it, &tree); | |
| 1272 | prevToken(&tok_it, tree); | |
| 1253 | 1273 | continue; |
| 1254 | 1274 | } |
| 1255 | 1275 | |
| ... | ... | @@ -1280,7 +1300,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1280 | 1300 | continue; |
| 1281 | 1301 | }, |
| 1282 | 1302 | State.AsmOutputReturnOrType => |node| { |
| 1283 | const token = nextToken(&tok_it, &tree); | |
| 1303 | const token = nextToken(&tok_it, tree); | |
| 1284 | 1304 | const token_index = token.index; |
| 1285 | 1305 | const token_ptr = token.ptr; |
| 1286 | 1306 | switch (token_ptr.id) { |
| ... | ... | @@ -1300,11 +1320,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1300 | 1320 | } |
| 1301 | 1321 | }, |
| 1302 | 1322 | State.AsmInputItems => |items| { |
| 1303 | const lbracket = nextToken(&tok_it, &tree); | |
| 1323 | const lbracket = nextToken(&tok_it, tree); | |
| 1304 | 1324 | const lbracket_index = lbracket.index; |
| 1305 | 1325 | const lbracket_ptr = lbracket.ptr; |
| 1306 | 1326 | if (lbracket_ptr.id != Token.Id.LBracket) { |
| 1307 | prevToken(&tok_it, &tree); | |
| 1327 | prevToken(&tok_it, tree); | |
| 1308 | 1328 | continue; |
| 1309 | 1329 | } |
| 1310 | 1330 | |
| ... | ... | @@ -1335,16 +1355,16 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1335 | 1355 | continue; |
| 1336 | 1356 | }, |
| 1337 | 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 | 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 | 1361 | break; |
| 1342 | 1362 | } |
| 1343 | 1363 | continue; |
| 1344 | 1364 | }, |
| 1345 | 1365 | |
| 1346 | 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 | 1368 | (list_state.ptr).* = token_index; |
| 1349 | 1369 | continue; |
| 1350 | 1370 | } |
| ... | ... | @@ -1354,7 +1374,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1354 | 1374 | continue; |
| 1355 | 1375 | }, |
| 1356 | 1376 | State.ExprListCommaOrEnd => |list_state| { |
| 1357 | switch (expectCommaOrEnd(&tok_it, &tree, list_state.end)) { | |
| 1377 | switch (expectCommaOrEnd(&tok_it, tree, list_state.end)) { | |
| 1358 | 1378 | ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { |
| 1359 | 1379 | (list_state.ptr).* = end; |
| 1360 | 1380 | continue; |
| ... | ... | @@ -1369,7 +1389,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1369 | 1389 | } |
| 1370 | 1390 | }, |
| 1371 | 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 | 1393 | (list_state.ptr).* = rbrace; |
| 1374 | 1394 | continue; |
| 1375 | 1395 | } |
| ... | ... | @@ -1401,7 +1421,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1401 | 1421 | continue; |
| 1402 | 1422 | }, |
| 1403 | 1423 | State.FieldInitListCommaOrEnd => |list_state| { |
| 1404 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) { | |
| 1424 | switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RBrace)) { | |
| 1405 | 1425 | ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { |
| 1406 | 1426 | (list_state.ptr).* = end; |
| 1407 | 1427 | continue; |
| ... | ... | @@ -1416,17 +1436,17 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1416 | 1436 | } |
| 1417 | 1437 | }, |
| 1418 | 1438 | State.FieldListCommaOrEnd => |field_ctx| { |
| 1419 | const end_token = nextToken(&tok_it, &tree); | |
| 1439 | const end_token = nextToken(&tok_it, tree); | |
| 1420 | 1440 | const end_token_index = end_token.index; |
| 1421 | 1441 | const end_token_ptr = end_token.ptr; |
| 1422 | 1442 | switch (end_token_ptr.id) { |
| 1423 | 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 | 1445 | const loc = tree.tokenLocation(end_token_ptr.end, doc_comment_token); |
| 1426 | 1446 | if (loc.line == 0) { |
| 1427 | 1447 | try pushDocComment(arena, doc_comment_token, field_ctx.doc_comments); |
| 1428 | 1448 | } else { |
| 1429 | prevToken(&tok_it, &tree); | |
| 1449 | prevToken(&tok_it, tree); | |
| 1430 | 1450 | } |
| 1431 | 1451 | } |
| 1432 | 1452 | |
| ... | ... | @@ -1449,7 +1469,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1449 | 1469 | } |
| 1450 | 1470 | }, |
| 1451 | 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 | 1473 | (list_state.ptr).* = rbrace; |
| 1454 | 1474 | continue; |
| 1455 | 1475 | } |
| ... | ... | @@ -1461,7 +1481,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1461 | 1481 | continue; |
| 1462 | 1482 | }, |
| 1463 | 1483 | State.ErrorTagListCommaOrEnd => |list_state| { |
| 1464 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) { | |
| 1484 | switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RBrace)) { | |
| 1465 | 1485 | ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { |
| 1466 | 1486 | (list_state.ptr).* = end; |
| 1467 | 1487 | continue; |
| ... | ... | @@ -1476,12 +1496,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1476 | 1496 | } |
| 1477 | 1497 | }, |
| 1478 | 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 | 1500 | (list_state.ptr).* = rbrace; |
| 1481 | 1501 | continue; |
| 1482 | 1502 | } |
| 1483 | 1503 | |
| 1484 | const comments = try eatDocComments(arena, &tok_it, &tree); | |
| 1504 | const comments = try eatDocComments(arena, &tok_it, tree); | |
| 1485 | 1505 | const node = try arena.create(ast.Node.SwitchCase); |
| 1486 | 1506 | node.* = ast.Node.SwitchCase{ |
| 1487 | 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 | 1520 | }, |
| 1501 | 1521 | |
| 1502 | 1522 | State.SwitchCaseCommaOrEnd => |list_state| { |
| 1503 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) { | |
| 1523 | switch (expectCommaOrEnd(&tok_it, tree, Token.Id.RBrace)) { | |
| 1504 | 1524 | ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { |
| 1505 | 1525 | (list_state.ptr).* = end; |
| 1506 | 1526 | continue; |
| ... | ... | @@ -1516,7 +1536,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1516 | 1536 | }, |
| 1517 | 1537 | |
| 1518 | 1538 | State.SwitchCaseFirstItem => |switch_case| { |
| 1519 | const token = nextToken(&tok_it, &tree); | |
| 1539 | const token = nextToken(&tok_it, tree); | |
| 1520 | 1540 | const token_index = token.index; |
| 1521 | 1541 | const token_ptr = token.ptr; |
| 1522 | 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 | 1555 | }); |
| 1536 | 1556 | continue; |
| 1537 | 1557 | } else { |
| 1538 | prevToken(&tok_it, &tree); | |
| 1558 | prevToken(&tok_it, tree); | |
| 1539 | 1559 | stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable; |
| 1540 | 1560 | try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } }); |
| 1541 | 1561 | continue; |
| 1542 | 1562 | } |
| 1543 | 1563 | }, |
| 1544 | 1564 | State.SwitchCaseItemOrEnd => |switch_case| { |
| 1545 | const token = nextToken(&tok_it, &tree); | |
| 1565 | const token = nextToken(&tok_it, tree); | |
| 1546 | 1566 | if (token.ptr.id == Token.Id.EqualAngleBracketRight) { |
| 1547 | 1567 | switch_case.arrow_token = token.index; |
| 1548 | 1568 | continue; |
| 1549 | 1569 | } else { |
| 1550 | prevToken(&tok_it, &tree); | |
| 1570 | prevToken(&tok_it, tree); | |
| 1551 | 1571 | stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable; |
| 1552 | 1572 | try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } }); |
| 1553 | 1573 | continue; |
| 1554 | 1574 | } |
| 1555 | 1575 | }, |
| 1556 | 1576 | State.SwitchCaseItemCommaOrEnd => |switch_case| { |
| 1557 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.EqualAngleBracketRight)) { | |
| 1577 | switch (expectCommaOrEnd(&tok_it, tree, Token.Id.EqualAngleBracketRight)) { | |
| 1558 | 1578 | ExpectCommaOrEndResult.end_token => |end_token| { |
| 1559 | 1579 | if (end_token) |t| { |
| 1560 | 1580 | switch_case.arrow_token = t; |
| ... | ... | @@ -1572,14 +1592,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1572 | 1592 | }, |
| 1573 | 1593 | |
| 1574 | 1594 | State.SuspendBody => |suspend_node| { |
| 1575 | const token = nextToken(&tok_it, &tree); | |
| 1595 | const token = nextToken(&tok_it, tree); | |
| 1576 | 1596 | switch (token.ptr.id) { |
| 1577 | 1597 | Token.Id.Semicolon => { |
| 1578 | prevToken(&tok_it, &tree); | |
| 1598 | prevToken(&tok_it, tree); | |
| 1579 | 1599 | continue; |
| 1580 | 1600 | }, |
| 1581 | 1601 | Token.Id.LBrace => { |
| 1582 | prevToken(&tok_it, &tree); | |
| 1602 | prevToken(&tok_it, tree); | |
| 1583 | 1603 | try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } }); |
| 1584 | 1604 | continue; |
| 1585 | 1605 | }, |
| ... | ... | @@ -1589,7 +1609,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1589 | 1609 | } |
| 1590 | 1610 | }, |
| 1591 | 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 | 1613 | continue; |
| 1594 | 1614 | } |
| 1595 | 1615 | |
| ... | ... | @@ -1630,7 +1650,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1630 | 1650 | }, |
| 1631 | 1651 | |
| 1632 | 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 | 1654 | const fn_proto = try arena.create(ast.Node.FnProto); |
| 1635 | 1655 | fn_proto.* = ast.Node.FnProto{ |
| 1636 | 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 | 1683 | continue; |
| 1664 | 1684 | }, |
| 1665 | 1685 | State.SliceOrArrayAccess => |node| { |
| 1666 | const token = nextToken(&tok_it, &tree); | |
| 1686 | const token = nextToken(&tok_it, tree); | |
| 1667 | 1687 | const token_index = token.index; |
| 1668 | 1688 | const token_ptr = token.ptr; |
| 1669 | 1689 | switch (token_ptr.id) { |
| ... | ... | @@ -1696,7 +1716,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1696 | 1716 | } |
| 1697 | 1717 | }, |
| 1698 | 1718 | State.SliceOrArrayType => |node| { |
| 1699 | if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| { | |
| 1719 | if (eatToken(&tok_it, tree, Token.Id.RBracket)) |_| { | |
| 1700 | 1720 | node.op = ast.Node.PrefixOp.Op{ |
| 1701 | 1721 | .SliceType = ast.Node.PrefixOp.PtrInfo{ |
| 1702 | 1722 | .align_info = null, |
| ... | ... | @@ -1718,7 +1738,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1718 | 1738 | }, |
| 1719 | 1739 | |
| 1720 | 1740 | State.PtrTypeModifiers => |addr_of_info| { |
| 1721 | const token = nextToken(&tok_it, &tree); | |
| 1741 | const token = nextToken(&tok_it, tree); | |
| 1722 | 1742 | const token_index = token.index; |
| 1723 | 1743 | const token_ptr = token.ptr; |
| 1724 | 1744 | switch (token_ptr.id) { |
| ... | ... | @@ -1768,14 +1788,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1768 | 1788 | continue; |
| 1769 | 1789 | }, |
| 1770 | 1790 | else => { |
| 1771 | prevToken(&tok_it, &tree); | |
| 1791 | prevToken(&tok_it, tree); | |
| 1772 | 1792 | continue; |
| 1773 | 1793 | }, |
| 1774 | 1794 | } |
| 1775 | 1795 | }, |
| 1776 | 1796 | |
| 1777 | 1797 | State.AlignBitRange => |align_info| { |
| 1778 | const token = nextToken(&tok_it, &tree); | |
| 1798 | const token = nextToken(&tok_it, tree); | |
| 1779 | 1799 | switch (token.ptr.id) { |
| 1780 | 1800 | Token.Id.Colon => { |
| 1781 | 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 | 1818 | }, |
| 1799 | 1819 | |
| 1800 | 1820 | State.Payload => |opt_ctx| { |
| 1801 | const token = nextToken(&tok_it, &tree); | |
| 1821 | const token = nextToken(&tok_it, tree); | |
| 1802 | 1822 | const token_index = token.index; |
| 1803 | 1823 | const token_ptr = token.ptr; |
| 1804 | 1824 | if (token_ptr.id != Token.Id.Pipe) { |
| ... | ... | @@ -1812,7 +1832,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1812 | 1832 | return tree; |
| 1813 | 1833 | } |
| 1814 | 1834 | |
| 1815 | prevToken(&tok_it, &tree); | |
| 1835 | prevToken(&tok_it, tree); | |
| 1816 | 1836 | continue; |
| 1817 | 1837 | } |
| 1818 | 1838 | |
| ... | ... | @@ -1835,7 +1855,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1835 | 1855 | continue; |
| 1836 | 1856 | }, |
| 1837 | 1857 | State.PointerPayload => |opt_ctx| { |
| 1838 | const token = nextToken(&tok_it, &tree); | |
| 1858 | const token = nextToken(&tok_it, tree); | |
| 1839 | 1859 | const token_index = token.index; |
| 1840 | 1860 | const token_ptr = token.ptr; |
| 1841 | 1861 | if (token_ptr.id != Token.Id.Pipe) { |
| ... | ... | @@ -1849,7 +1869,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1849 | 1869 | return tree; |
| 1850 | 1870 | } |
| 1851 | 1871 | |
| 1852 | prevToken(&tok_it, &tree); | |
| 1872 | prevToken(&tok_it, tree); | |
| 1853 | 1873 | continue; |
| 1854 | 1874 | } |
| 1855 | 1875 | |
| ... | ... | @@ -1879,7 +1899,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1879 | 1899 | continue; |
| 1880 | 1900 | }, |
| 1881 | 1901 | State.PointerIndexPayload => |opt_ctx| { |
| 1882 | const token = nextToken(&tok_it, &tree); | |
| 1902 | const token = nextToken(&tok_it, tree); | |
| 1883 | 1903 | const token_index = token.index; |
| 1884 | 1904 | const token_ptr = token.ptr; |
| 1885 | 1905 | if (token_ptr.id != Token.Id.Pipe) { |
| ... | ... | @@ -1893,7 +1913,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1893 | 1913 | return tree; |
| 1894 | 1914 | } |
| 1895 | 1915 | |
| 1896 | prevToken(&tok_it, &tree); | |
| 1916 | prevToken(&tok_it, tree); | |
| 1897 | 1917 | continue; |
| 1898 | 1918 | } |
| 1899 | 1919 | |
| ... | ... | @@ -1927,7 +1947,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1927 | 1947 | }, |
| 1928 | 1948 | |
| 1929 | 1949 | State.Expression => |opt_ctx| { |
| 1930 | const token = nextToken(&tok_it, &tree); | |
| 1950 | const token = nextToken(&tok_it, tree); | |
| 1931 | 1951 | const token_index = token.index; |
| 1932 | 1952 | const token_ptr = token.ptr; |
| 1933 | 1953 | switch (token_ptr.id) { |
| ... | ... | @@ -1981,7 +2001,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1981 | 2001 | }, |
| 1982 | 2002 | else => { |
| 1983 | 2003 | if (!try parseBlockExpr(&stack, arena, opt_ctx, token_ptr.*, token_index)) { |
| 1984 | prevToken(&tok_it, &tree); | |
| 2004 | prevToken(&tok_it, tree); | |
| 1985 | 2005 | stack.append(State{ .UnwrapExpressionBegin = opt_ctx }) catch unreachable; |
| 1986 | 2006 | } |
| 1987 | 2007 | continue; |
| ... | ... | @@ -1996,7 +2016,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1996 | 2016 | State.RangeExpressionEnd => |opt_ctx| { |
| 1997 | 2017 | const lhs = opt_ctx.get() orelse continue; |
| 1998 | 2018 | |
| 1999 | if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| { | |
| 2019 | if (eatToken(&tok_it, tree, Token.Id.Ellipsis3)) |ellipsis3| { | |
| 2000 | 2020 | const node = try arena.create(ast.Node.InfixOp); |
| 2001 | 2021 | node.* = ast.Node.InfixOp{ |
| 2002 | 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 | 2039 | State.AssignmentExpressionEnd => |opt_ctx| { |
| 2020 | 2040 | const lhs = opt_ctx.get() orelse continue; |
| 2021 | 2041 | |
| 2022 | const token = nextToken(&tok_it, &tree); | |
| 2042 | const token = nextToken(&tok_it, tree); | |
| 2023 | 2043 | const token_index = token.index; |
| 2024 | 2044 | const token_ptr = token.ptr; |
| 2025 | 2045 | if (tokenIdToAssignment(token_ptr.id)) |ass_id| { |
| ... | ... | @@ -2036,7 +2056,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2036 | 2056 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }); |
| 2037 | 2057 | continue; |
| 2038 | 2058 | } else { |
| 2039 | prevToken(&tok_it, &tree); | |
| 2059 | prevToken(&tok_it, tree); | |
| 2040 | 2060 | continue; |
| 2041 | 2061 | } |
| 2042 | 2062 | }, |
| ... | ... | @@ -2050,7 +2070,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2050 | 2070 | State.UnwrapExpressionEnd => |opt_ctx| { |
| 2051 | 2071 | const lhs = opt_ctx.get() orelse continue; |
| 2052 | 2072 | |
| 2053 | const token = nextToken(&tok_it, &tree); | |
| 2073 | const token = nextToken(&tok_it, tree); | |
| 2054 | 2074 | const token_index = token.index; |
| 2055 | 2075 | const token_ptr = token.ptr; |
| 2056 | 2076 | if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| { |
| ... | ... | @@ -2072,7 +2092,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2072 | 2092 | } |
| 2073 | 2093 | continue; |
| 2074 | 2094 | } else { |
| 2075 | prevToken(&tok_it, &tree); | |
| 2095 | prevToken(&tok_it, tree); | |
| 2076 | 2096 | continue; |
| 2077 | 2097 | } |
| 2078 | 2098 | }, |
| ... | ... | @@ -2086,7 +2106,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2086 | 2106 | State.BoolOrExpressionEnd => |opt_ctx| { |
| 2087 | 2107 | const lhs = opt_ctx.get() orelse continue; |
| 2088 | 2108 | |
| 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 | 2110 | const node = try arena.create(ast.Node.InfixOp); |
| 2091 | 2111 | node.* = ast.Node.InfixOp{ |
| 2092 | 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 | 2131 | State.BoolAndExpressionEnd => |opt_ctx| { |
| 2112 | 2132 | const lhs = opt_ctx.get() orelse continue; |
| 2113 | 2133 | |
| 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 | 2135 | const node = try arena.create(ast.Node.InfixOp); |
| 2116 | 2136 | node.* = ast.Node.InfixOp{ |
| 2117 | 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 | 2156 | State.ComparisonExpressionEnd => |opt_ctx| { |
| 2137 | 2157 | const lhs = opt_ctx.get() orelse continue; |
| 2138 | 2158 | |
| 2139 | const token = nextToken(&tok_it, &tree); | |
| 2159 | const token = nextToken(&tok_it, tree); | |
| 2140 | 2160 | const token_index = token.index; |
| 2141 | 2161 | const token_ptr = token.ptr; |
| 2142 | 2162 | if (tokenIdToComparison(token_ptr.id)) |comp_id| { |
| ... | ... | @@ -2153,7 +2173,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2153 | 2173 | try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| 2154 | 2174 | continue; |
| 2155 | 2175 | } else { |
| 2156 | prevToken(&tok_it, &tree); | |
| 2176 | prevToken(&tok_it, tree); | |
| 2157 | 2177 | continue; |
| 2158 | 2178 | } |
| 2159 | 2179 | }, |
| ... | ... | @@ -2167,7 +2187,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2167 | 2187 | State.BinaryOrExpressionEnd => |opt_ctx| { |
| 2168 | 2188 | const lhs = opt_ctx.get() orelse continue; |
| 2169 | 2189 | |
| 2170 | if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| { | |
| 2190 | if (eatToken(&tok_it, tree, Token.Id.Pipe)) |pipe| { | |
| 2171 | 2191 | const node = try arena.create(ast.Node.InfixOp); |
| 2172 | 2192 | node.* = ast.Node.InfixOp{ |
| 2173 | 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 | 2212 | State.BinaryXorExpressionEnd => |opt_ctx| { |
| 2193 | 2213 | const lhs = opt_ctx.get() orelse continue; |
| 2194 | 2214 | |
| 2195 | if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| { | |
| 2215 | if (eatToken(&tok_it, tree, Token.Id.Caret)) |caret| { | |
| 2196 | 2216 | const node = try arena.create(ast.Node.InfixOp); |
| 2197 | 2217 | node.* = ast.Node.InfixOp{ |
| 2198 | 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 | 2237 | State.BinaryAndExpressionEnd => |opt_ctx| { |
| 2218 | 2238 | const lhs = opt_ctx.get() orelse continue; |
| 2219 | 2239 | |
| 2220 | if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| { | |
| 2240 | if (eatToken(&tok_it, tree, Token.Id.Ampersand)) |ampersand| { | |
| 2221 | 2241 | const node = try arena.create(ast.Node.InfixOp); |
| 2222 | 2242 | node.* = ast.Node.InfixOp{ |
| 2223 | 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 | 2262 | State.BitShiftExpressionEnd => |opt_ctx| { |
| 2243 | 2263 | const lhs = opt_ctx.get() orelse continue; |
| 2244 | 2264 | |
| 2245 | const token = nextToken(&tok_it, &tree); | |
| 2265 | const token = nextToken(&tok_it, tree); | |
| 2246 | 2266 | const token_index = token.index; |
| 2247 | 2267 | const token_ptr = token.ptr; |
| 2248 | 2268 | if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| { |
| ... | ... | @@ -2259,7 +2279,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2259 | 2279 | try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| 2260 | 2280 | continue; |
| 2261 | 2281 | } else { |
| 2262 | prevToken(&tok_it, &tree); | |
| 2282 | prevToken(&tok_it, tree); | |
| 2263 | 2283 | continue; |
| 2264 | 2284 | } |
| 2265 | 2285 | }, |
| ... | ... | @@ -2273,7 +2293,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2273 | 2293 | State.AdditionExpressionEnd => |opt_ctx| { |
| 2274 | 2294 | const lhs = opt_ctx.get() orelse continue; |
| 2275 | 2295 | |
| 2276 | const token = nextToken(&tok_it, &tree); | |
| 2296 | const token = nextToken(&tok_it, tree); | |
| 2277 | 2297 | const token_index = token.index; |
| 2278 | 2298 | const token_ptr = token.ptr; |
| 2279 | 2299 | if (tokenIdToAddition(token_ptr.id)) |add_id| { |
| ... | ... | @@ -2290,7 +2310,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2290 | 2310 | try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| 2291 | 2311 | continue; |
| 2292 | 2312 | } else { |
| 2293 | prevToken(&tok_it, &tree); | |
| 2313 | prevToken(&tok_it, tree); | |
| 2294 | 2314 | continue; |
| 2295 | 2315 | } |
| 2296 | 2316 | }, |
| ... | ... | @@ -2304,7 +2324,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2304 | 2324 | State.MultiplyExpressionEnd => |opt_ctx| { |
| 2305 | 2325 | const lhs = opt_ctx.get() orelse continue; |
| 2306 | 2326 | |
| 2307 | const token = nextToken(&tok_it, &tree); | |
| 2327 | const token = nextToken(&tok_it, tree); | |
| 2308 | 2328 | const token_index = token.index; |
| 2309 | 2329 | const token_ptr = token.ptr; |
| 2310 | 2330 | if (tokenIdToMultiply(token_ptr.id)) |mult_id| { |
| ... | ... | @@ -2321,7 +2341,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2321 | 2341 | try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| 2322 | 2342 | continue; |
| 2323 | 2343 | } else { |
| 2324 | prevToken(&tok_it, &tree); | |
| 2344 | prevToken(&tok_it, tree); | |
| 2325 | 2345 | continue; |
| 2326 | 2346 | } |
| 2327 | 2347 | }, |
| ... | ... | @@ -2386,7 +2406,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2386 | 2406 | State.TypeExprEnd => |opt_ctx| { |
| 2387 | 2407 | const lhs = opt_ctx.get() orelse continue; |
| 2388 | 2408 | |
| 2389 | if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| { | |
| 2409 | if (eatToken(&tok_it, tree, Token.Id.Bang)) |bang| { | |
| 2390 | 2410 | const node = try arena.create(ast.Node.InfixOp); |
| 2391 | 2411 | node.* = ast.Node.InfixOp{ |
| 2392 | 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 | 2423 | }, |
| 2404 | 2424 | |
| 2405 | 2425 | State.PrefixOpExpression => |opt_ctx| { |
| 2406 | const token = nextToken(&tok_it, &tree); | |
| 2426 | const token = nextToken(&tok_it, tree); | |
| 2407 | 2427 | const token_index = token.index; |
| 2408 | 2428 | const token_ptr = token.ptr; |
| 2409 | 2429 | if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| { |
| ... | ... | @@ -2435,14 +2455,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2435 | 2455 | } |
| 2436 | 2456 | continue; |
| 2437 | 2457 | } else { |
| 2438 | prevToken(&tok_it, &tree); | |
| 2458 | prevToken(&tok_it, tree); | |
| 2439 | 2459 | stack.append(State{ .SuffixOpExpressionBegin = opt_ctx }) catch unreachable; |
| 2440 | 2460 | continue; |
| 2441 | 2461 | } |
| 2442 | 2462 | }, |
| 2443 | 2463 | |
| 2444 | 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 | 2466 | const async_node = try arena.create(ast.Node.AsyncAttribute); |
| 2447 | 2467 | async_node.* = ast.Node.AsyncAttribute{ |
| 2448 | 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 | 2490 | State.SuffixOpExpressionEnd => |opt_ctx| { |
| 2471 | 2491 | const lhs = opt_ctx.get() orelse continue; |
| 2472 | 2492 | |
| 2473 | const token = nextToken(&tok_it, &tree); | |
| 2493 | const token = nextToken(&tok_it, tree); | |
| 2474 | 2494 | const token_index = token.index; |
| 2475 | 2495 | const token_ptr = token.ptr; |
| 2476 | 2496 | switch (token_ptr.id) { |
| ... | ... | @@ -2515,7 +2535,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2515 | 2535 | continue; |
| 2516 | 2536 | }, |
| 2517 | 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 | 2539 | const node = try arena.create(ast.Node.SuffixOp); |
| 2520 | 2540 | node.* = ast.Node.SuffixOp{ |
| 2521 | 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 | 2547 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2528 | 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 | 2551 | const node = try arena.create(ast.Node.SuffixOp); |
| 2532 | 2552 | node.* = ast.Node.SuffixOp{ |
| 2533 | 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 | 2574 | continue; |
| 2555 | 2575 | }, |
| 2556 | 2576 | else => { |
| 2557 | prevToken(&tok_it, &tree); | |
| 2577 | prevToken(&tok_it, tree); | |
| 2558 | 2578 | continue; |
| 2559 | 2579 | }, |
| 2560 | 2580 | } |
| 2561 | 2581 | }, |
| 2562 | 2582 | |
| 2563 | 2583 | State.PrimaryExpression => |opt_ctx| { |
| 2564 | const token = nextToken(&tok_it, &tree); | |
| 2584 | const token = nextToken(&tok_it, tree); | |
| 2565 | 2585 | switch (token.ptr.id) { |
| 2566 | 2586 | Token.Id.IntegerLiteral => { |
| 2567 | 2587 | _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.IntegerLiteral, token.index); |
| 2568 | 2588 | continue; |
| 2569 | 2589 | }, |
| 2570 | 2590 | Token.Id.Period => { |
| 2571 | const name_token = nextToken(&tok_it, &tree); | |
| 2591 | const name_token = nextToken(&tok_it, tree); | |
| 2572 | 2592 | if (name_token.ptr.id != Token.Id.Identifier) { |
| 2573 | 2593 | ((try tree.errors.addOne())).* = Error{ |
| 2574 | 2594 | .ExpectedToken = Error.ExpectedToken{ |
| ... | ... | @@ -2624,11 +2644,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2624 | 2644 | .result = null, |
| 2625 | 2645 | }; |
| 2626 | 2646 | opt_ctx.store(&node.base); |
| 2627 | const next_token = nextToken(&tok_it, &tree); | |
| 2647 | const next_token = nextToken(&tok_it, tree); | |
| 2628 | 2648 | const next_token_index = next_token.index; |
| 2629 | 2649 | const next_token_ptr = next_token.ptr; |
| 2630 | 2650 | if (next_token_ptr.id != Token.Id.Arrow) { |
| 2631 | prevToken(&tok_it, &tree); | |
| 2651 | prevToken(&tok_it, tree); | |
| 2632 | 2652 | continue; |
| 2633 | 2653 | } |
| 2634 | 2654 | node.result = ast.Node.PromiseType.Result{ |
| ... | ... | @@ -2640,7 +2660,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2640 | 2660 | continue; |
| 2641 | 2661 | }, |
| 2642 | 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 | 2664 | continue; |
| 2645 | 2665 | }, |
| 2646 | 2666 | Token.Id.LParen => { |
| ... | ... | @@ -2728,7 +2748,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2728 | 2748 | continue; |
| 2729 | 2749 | }, |
| 2730 | 2750 | Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => { |
| 2731 | prevToken(&tok_it, &tree); | |
| 2751 | prevToken(&tok_it, tree); | |
| 2732 | 2752 | stack.append(State{ |
| 2733 | 2753 | .ContainerKind = ContainerKindCtx{ |
| 2734 | 2754 | .opt_ctx = opt_ctx, |
| ... | ... | @@ -2845,7 +2865,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2845 | 2865 | }, |
| 2846 | 2866 | else => { |
| 2847 | 2867 | if (!try parseBlockExpr(&stack, arena, opt_ctx, token.ptr.*, token.index)) { |
| 2848 | prevToken(&tok_it, &tree); | |
| 2868 | prevToken(&tok_it, tree); | |
| 2849 | 2869 | if (opt_ctx != OptionalCtx.Optional) { |
| 2850 | 2870 | ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token.index } }; |
| 2851 | 2871 | return tree; |
| ... | ... | @@ -2857,7 +2877,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2857 | 2877 | }, |
| 2858 | 2878 | |
| 2859 | 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 | 2881 | const node = try arena.create(ast.Node.InfixOp); |
| 2862 | 2882 | node.* = ast.Node.InfixOp{ |
| 2863 | 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 | 2915 | continue; |
| 2896 | 2916 | }, |
| 2897 | 2917 | State.StringLiteral => |opt_ctx| { |
| 2898 | const token = nextToken(&tok_it, &tree); | |
| 2918 | const token = nextToken(&tok_it, tree); | |
| 2899 | 2919 | const token_index = token.index; |
| 2900 | 2920 | const token_ptr = token.ptr; |
| 2901 | opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) orelse { | |
| 2902 | prevToken(&tok_it, &tree); | |
| 2921 | opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, tree)) orelse { | |
| 2922 | prevToken(&tok_it, tree); | |
| 2903 | 2923 | if (opt_ctx != OptionalCtx.Optional) { |
| 2904 | 2924 | ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token_index } }; |
| 2905 | 2925 | return tree; |
| ... | ... | @@ -2910,13 +2930,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2910 | 2930 | }, |
| 2911 | 2931 | |
| 2912 | 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 | 2934 | _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.Identifier, ident_token); |
| 2915 | 2935 | continue; |
| 2916 | 2936 | } |
| 2917 | 2937 | |
| 2918 | 2938 | if (opt_ctx != OptionalCtx.Optional) { |
| 2919 | const token = nextToken(&tok_it, &tree); | |
| 2939 | const token = nextToken(&tok_it, tree); | |
| 2920 | 2940 | const token_index = token.index; |
| 2921 | 2941 | const token_ptr = token.ptr; |
| 2922 | 2942 | ((try tree.errors.addOne())).* = Error{ |
| ... | ... | @@ -2930,8 +2950,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2930 | 2950 | }, |
| 2931 | 2951 | |
| 2932 | 2952 | State.ErrorTag => |node_ptr| { |
| 2933 | const comments = try eatDocComments(arena, &tok_it, &tree); | |
| 2934 | const ident_token = nextToken(&tok_it, &tree); | |
| 2953 | const comments = try eatDocComments(arena, &tok_it, tree); | |
| 2954 | const ident_token = nextToken(&tok_it, tree); | |
| 2935 | 2955 | const ident_token_index = ident_token.index; |
| 2936 | 2956 | const ident_token_ptr = ident_token.ptr; |
| 2937 | 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 | 2975 | }, |
| 2956 | 2976 | |
| 2957 | 2977 | State.ExpectToken => |token_id| { |
| 2958 | const token = nextToken(&tok_it, &tree); | |
| 2978 | const token = nextToken(&tok_it, tree); | |
| 2959 | 2979 | const token_index = token.index; |
| 2960 | 2980 | const token_ptr = token.ptr; |
| 2961 | 2981 | if (token_ptr.id != token_id) { |
| ... | ... | @@ -2970,7 +2990,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2970 | 2990 | continue; |
| 2971 | 2991 | }, |
| 2972 | 2992 | State.ExpectTokenSave => |expect_token_save| { |
| 2973 | const token = nextToken(&tok_it, &tree); | |
| 2993 | const token = nextToken(&tok_it, tree); | |
| 2974 | 2994 | const token_index = token.index; |
| 2975 | 2995 | const token_ptr = token.ptr; |
| 2976 | 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 | 3006 | continue; |
| 2987 | 3007 | }, |
| 2988 | 3008 | State.IfToken => |token_id| { |
| 2989 | if (eatToken(&tok_it, &tree, token_id)) |_| { | |
| 3009 | if (eatToken(&tok_it, tree, token_id)) |_| { | |
| 2990 | 3010 | continue; |
| 2991 | 3011 | } |
| 2992 | 3012 | |
| ... | ... | @@ -2994,7 +3014,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2994 | 3014 | continue; |
| 2995 | 3015 | }, |
| 2996 | 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 | 3018 | (if_token_save.ptr).* = token_index; |
| 2999 | 3019 | continue; |
| 3000 | 3020 | } |
| ... | ... | @@ -3003,7 +3023,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 3003 | 3023 | continue; |
| 3004 | 3024 | }, |
| 3005 | 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 | 3027 | (optional_token_save.ptr).* = token_index; |
| 3008 | 3028 | continue; |
| 3009 | 3029 | } |
std/zig/parser_test.zig+18-18| ... | ... | @@ -1,10 +1,3 @@ |
| 1 | test "temporary trivial example" { | |
| 2 | try testCanonical( | |
| 3 | \\const x = true; | |
| 4 | \\ | |
| 5 | ); | |
| 6 | } | |
| 7 | ||
| 8 | 1 | test "zig fmt: allowzero pointer" { |
| 9 | 2 | try testCanonical( |
| 10 | 3 | \\const T = [*]allowzero const u8; |
| ... | ... | @@ -57,14 +50,6 @@ test "zig fmt: linksection" { |
| 57 | 50 | ); |
| 58 | 51 | } |
| 59 | 52 | |
| 60 | test "zig fmt: shebang line" { | |
| 61 | try testCanonical( | |
| 62 | \\#!/usr/bin/env zig | |
| 63 | \\pub fn main() void {} | |
| 64 | \\ | |
| 65 | ); | |
| 66 | } | |
| 67 | ||
| 68 | 53 | test "zig fmt: correctly move doc comments on struct fields" { |
| 69 | 54 | try testTransform( |
| 70 | 55 | \\pub const section_64 = extern struct { |
| ... | ... | @@ -2125,6 +2110,21 @@ test "zig fmt: error return" { |
| 2125 | 2110 | ); |
| 2126 | 2111 | } |
| 2127 | 2112 | |
| 2113 | test "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 | ||
| 2128 | 2128 | const std = @import("std"); |
| 2129 | 2129 | const mem = std.mem; |
| 2130 | 2130 | const warn = std.debug.warn; |
| ... | ... | @@ -2137,7 +2137,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b |
| 2137 | 2137 | var stderr_file = try io.getStdErr(); |
| 2138 | 2138 | var stderr = &stderr_file.outStream().stream; |
| 2139 | 2139 | |
| 2140 | var tree = try std.zig.parse2(allocator, source); | |
| 2140 | const tree = try std.zig.parse(allocator, source); | |
| 2141 | 2141 | defer tree.deinit(); |
| 2142 | 2142 | |
| 2143 | 2143 | var error_it = tree.errors.iterator(0); |
| ... | ... | @@ -2170,7 +2170,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b |
| 2170 | 2170 | errdefer buffer.deinit(); |
| 2171 | 2171 | |
| 2172 | 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 | 2174 | return buffer.toOwnedSlice(); |
| 2175 | 2175 | } |
| 2176 | 2176 | |
| ... | ... | @@ -2215,7 +2215,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void { |
| 2215 | 2215 | needed_alloc_count, |
| 2216 | 2216 | failing_allocator.allocated_bytes, |
| 2217 | 2217 | failing_allocator.freed_bytes, |
| 2218 | failing_allocator.index, | |
| 2218 | failing_allocator.allocations, | |
| 2219 | 2219 | failing_allocator.deallocations, |
| 2220 | 2220 | ); |
| 2221 | 2221 | return error.MemoryLeakDetected; |
std/zig/render.zig+1-6| ... | ... | @@ -73,11 +73,6 @@ fn renderRoot( |
| 73 | 73 | ) (@typeOf(stream).Child.Error || Error)!void { |
| 74 | 74 | var tok_it = tree.tokens.iterator(0); |
| 75 | 75 | |
| 76 | // render the shebang line | |
| 77 | if (tree.root_node.shebang) |shebang| { | |
| 78 | try stream.write(tree.tokenSlice(shebang)); | |
| 79 | } | |
| 80 | ||
| 81 | 76 | // render all the line comments at the beginning of the file |
| 82 | 77 | while (tok_it.next()) |token| { |
| 83 | 78 | if (token.id != Token.Id.LineComment) break; |
| ... | ... | @@ -753,7 +748,7 @@ fn renderExpression( |
| 753 | 748 | counting_stream.bytes_written = 0; |
| 754 | 749 | var dummy_col: usize = 0; |
| 755 | 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 | 752 | const col = i % row_size; |
| 758 | 753 | column_widths[col] = std.math.max(column_widths[col], width); |
| 759 | 754 | expr_widths[i] = width; |
test/compile_errors.zig+80-33| ... | ... | @@ -2,6 +2,64 @@ const tests = @import("tests.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | pub 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 | 63 | cases.add( |
| 6 | 64 | "@ptrToInt 0 to non optional pointer", |
| 7 | 65 | \\export fn entry() void { |
| ... | ... | @@ -552,15 +610,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 552 | 610 | "tmp.zig:1:13: error: threadlocal variable cannot be constant", |
| 553 | 611 | ); |
| 554 | 612 | |
| 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 | 613 | cases.add( |
| 565 | 614 | "@bitCast same size but bit count mismatch", |
| 566 | 615 | \\export fn entry(byte: u8) void { |
| ... | ... | @@ -839,7 +888,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 839 | 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 | ); |
| 844 | 893 | |
| 845 | 894 | cases.add( |
| ... | ... | @@ -5347,8 +5396,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5347 | 5396 | "tmp.zig:12:20: note: referenced here", |
| 5348 | 5397 | ); |
| 5349 | 5398 | |
| 5350 | cases.add( | |
| 5351 | "specify enum tag type that is too small", | |
| 5399 | cases.add("specify enum tag type that is too small", | |
| 5352 | 5400 | \\const Small = enum (u2) { |
| 5353 | 5401 | \\ One, |
| 5354 | 5402 | \\ Two, |
| ... | ... | @@ -5360,9 +5408,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5360 | 5408 | \\export fn entry() void { |
| 5361 | 5409 | \\ var x = Small.One; |
| 5362 | 5410 | \\} |
| 5363 | , | |
| 5364 | "tmp.zig:1:21: error: 'u2' too small to hold all bits; must be at least 'u3'", | |
| 5365 | ); | |
| 5411 | , "tmp.zig:6:5: error: enumeration value 4 too large for type 'u2'"); | |
| 5366 | 5412 | |
| 5367 | 5413 | cases.add( |
| 5368 | 5414 | "specify non-integer enum tag type", |
| ... | ... | @@ -5412,22 +5458,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5412 | 5458 | "tmp.zig:10:31: error: expected type 'u2', found 'u3'", |
| 5413 | 5459 | ); |
| 5414 | 5460 | |
| 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 | 5461 | cases.add( |
| 5432 | 5462 | "struct fields with value assignments", |
| 5433 | 5463 | \\const MultipleChoice = struct { |
| ... | ... | @@ -5486,8 +5516,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5486 | 5516 | \\ var x = MultipleChoice.C; |
| 5487 | 5517 | \\} |
| 5488 | 5518 | , |
| 5489 | "tmp.zig:6:9: error: enum tag value 60 already taken", | |
| 5490 | "tmp.zig:4:9: note: other occurrence here", | |
| 5519 | "tmp.zig:6:5: error: enum tag value 60 already taken", | |
| 5520 | "tmp.zig:4:5: note: other occurrence here", | |
| 5491 | 5521 | ); |
| 5492 | 5522 | |
| 5493 | 5523 | cases.add( |
| ... | ... | @@ -5892,4 +5922,21 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5892 | 5922 | , |
| 5893 | 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 | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | |
| 3 | 3 | pub 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 | 24 | cases.addRuntimeSafety("@ptrToInt address zero to non-optional pointer", |
| 5 | 25 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 6 | 26 | \\ @import("std").os.exit(126); |
test/stage1/behavior.zig+3| ... | ... | @@ -20,9 +20,12 @@ comptime { |
| 20 | 20 | _ = @import("behavior/bugs/1442.zig"); |
| 21 | 21 | _ = @import("behavior/bugs/1486.zig"); |
| 22 | 22 | _ = @import("behavior/bugs/1500.zig"); |
| 23 | _ = @import("behavior/bugs/1607.zig"); | |
| 23 | 24 | _ = @import("behavior/bugs/1851.zig"); |
| 24 | 25 | _ = @import("behavior/bugs/1914.zig"); |
| 25 | 26 | _ = @import("behavior/bugs/2006.zig"); |
| 27 | _ = @import("behavior/bugs/2114.zig"); | |
| 28 | _ = @import("behavior/bugs/2346.zig"); | |
| 26 | 29 | _ = @import("behavior/bugs/394.zig"); |
| 27 | 30 | _ = @import("behavior/bugs/421.zig"); |
| 28 | 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 | 86 | expect(table.get(@intCast(Key, i)) == node); |
| 87 | 87 | } |
| 88 | 88 | } |
| 89 | ||
| 90 | // #2225 | |
| 91 | test "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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const testing = std.testing; | |
| 3 | ||
| 4 | const a = []u8{ 1, 2, 3 }; | |
| 5 | ||
| 6 | fn checkAddress(s: []const u8) void { | |
| 7 | for (s) |*i, j| { | |
| 8 | testing.expect(i == &a[j]); | |
| 9 | } | |
| 10 | } | |
| 11 | ||
| 12 | test "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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | const math = std.math; | |
| 4 | ||
| 5 | fn ctz(x: var) usize { | |
| 6 | return @ctz(x); | |
| 7 | } | |
| 8 | ||
| 9 | test "fixed" { | |
| 10 | testClz(); | |
| 11 | comptime testClz(); | |
| 12 | } | |
| 13 | ||
| 14 | fn 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 @@ |
| 1 | test "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 | 923 | expect(Items.two == .two); |
| 924 | 924 | expect(.two == Items.two); |
| 925 | 925 | } |
| 926 | ||
| 927 | test "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 | ||
| 942 | test "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 | ||
| 954 | test "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 | 632 | expect(!(nan1 < nan2)); |
| 633 | 633 | expect(!(nan1 <= nan2)); |
| 634 | 634 | } |
| 635 | ||
| 636 | test "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 | 150 | expect(@typeInfo(@typeOf(ptr)).Pointer.is_allowzero); |
| 151 | 151 | expect(@typeInfo(@typeOf(slice)).Pointer.is_allowzero); |
| 152 | 152 | } |
| 153 | ||
| 154 | test "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 | 67 | expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); |
| 68 | 68 | expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); |
| 69 | 69 | } |
| 70 | ||
| 71 | test "@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 | 2 | const expect = std.testing.expect; |
| 3 | 3 | const expectEqualSlices = std.testing.expectEqualSlices; |
| 4 | 4 | const builtin = @import("builtin"); |
| 5 | const maxInt = std.math.maxInt; | |
| 6 | ||
| 5 | const maxInt = std.math.maxInt; | |
| 7 | 6 | const StructWithNoFields = struct { |
| 8 | 7 | fn add(a: i32, b: i32) i32 { |
| 9 | 8 | return a + b; |
| ... | ... | @@ -505,3 +504,22 @@ test "packed struct with u0 field access" { |
| 505 | 504 | var s = S{ .f0 = 0 }; |
| 506 | 505 | comptime expect(s.f0 == 0); |
| 507 | 506 | } |
| 507 | ||
| 508 | const 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 | ||
| 520 | var g_foo: S0 = S0.init(); | |
| 521 | ||
| 522 | test "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 | 1 | // Test trailing comma syntax |
| 2 | 2 | // zig fmt: off |
| 3 | 3 | |
| 4 | extern var a: c_int; | |
| 5 | extern "c" var b: c_int; | |
| 6 | export var c: c_int = 0; | |
| 7 | threadlocal var d: c_int; | |
| 8 | extern threadlocal var e: c_int; | |
| 9 | extern "c" threadlocal var f: c_int; | |
| 10 | export threadlocal var g: c_int = 0; | |
| 11 | ||
| 4 | 12 | const struct_trailing_comma = struct { x: i32, y: i32, }; |
| 5 | 13 | const struct_no_comma = struct { x: i32, y: i32 }; |
| 6 | 14 | const 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 | 365 | expect(@enumToInt(b) == 1); |
| 366 | 366 | expect(@enumToInt(c) == 2); |
| 367 | 367 | } |
| 368 | ||
| 369 | const Attribute = union(enum) { | |
| 370 | A: bool, | |
| 371 | B: u8, | |
| 372 | }; | |
| 373 | ||
| 374 | fn setAttribute(attr: Attribute) void {} | |
| 375 | ||
| 376 | fn Setter(attr: Attribute) type { | |
| 377 | return struct{ | |
| 378 | fn set() void { | |
| 379 | setAttribute(attr); | |
| 380 | } | |
| 381 | }; | |
| 382 | } | |
| 383 | ||
| 384 | test "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 | 903 | sources: ArrayList(SourceFile), |
| 904 | 904 | expected_lines: ArrayList([]const u8), |
| 905 | 905 | allow_warnings: bool, |
| 906 | stage2: bool, | |
| 906 | 907 | |
| 907 | 908 | const SourceFile = struct { |
| 908 | 909 | filename: []const u8, |
| ... | ... | @@ -955,7 +956,8 @@ pub const TranslateCContext = struct { |
| 955 | 956 | var zig_args = ArrayList([]const u8).init(b.allocator); |
| 956 | 957 | zig_args.append(b.zig_exe) catch unreachable; |
| 957 | 958 | |
| 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 | 961 | zig_args.append(b.pathFromRoot(root_src)) catch unreachable; |
| 960 | 962 | |
| 961 | 963 | warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); |
| ... | ... | @@ -1052,6 +1054,7 @@ pub const TranslateCContext = struct { |
| 1052 | 1054 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), |
| 1053 | 1055 | .expected_lines = ArrayList([]const u8).init(self.b.allocator), |
| 1054 | 1056 | .allow_warnings = allow_warnings, |
| 1057 | .stage2 = false, | |
| 1055 | 1058 | }; |
| 1056 | 1059 | |
| 1057 | 1060 | tc.addSourceFile(filename, source); |
| ... | ... | @@ -1072,6 +1075,34 @@ pub const TranslateCContext = struct { |
| 1072 | 1075 | self.addCase(tc); |
| 1073 | 1076 | } |
| 1074 | 1077 | |
| 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 | 1106 | pub fn addAllowWarnings(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { |
| 1076 | 1107 | const tc = self.create(true, "source.h", name, source, expected_lines); |
| 1077 | 1108 | self.addCase(tc); |
| ... | ... | @@ -1080,7 +1111,8 @@ pub const TranslateCContext = struct { |
| 1080 | 1111 | pub fn addCase(self: *TranslateCContext, case: *const TestCase) void { |
| 1081 | 1112 | const b = self.b; |
| 1082 | 1113 | |
| 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 | 1116 | if (self.test_filter) |filter| { |
| 1085 | 1117 | if (mem.indexOf(u8, annotated_case_name, filter) == null) return; |
| 1086 | 1118 | } |
test/translate_c.zig+167-48| ... | ... | @@ -1,7 +1,66 @@ |
| 1 | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 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 | ||
| 4 | 11 | pub 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 | 64 | if (builtin.os != builtin.Os.windows) { |
| 6 | 65 | // Windows treats this as an enum with type c_int |
| 7 | 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 | 131 | \\ _ = c"void foo(void)"; |
| 73 | 132 | \\} |
| 74 | 133 | ); |
| 75 | ||
| 134 | ||
| 76 | 135 | cases.add("ignore result", |
| 77 | 136 | \\void foo() { |
| 78 | 137 | \\ int a; |
| ... | ... | @@ -648,11 +707,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 648 | 707 | , |
| 649 | 708 | \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { |
| 650 | 709 | \\ if ((a != 0) and (b != 0)) return 0; |
| 651 | \\ if ((b != 0) and (c != 0)) return 1; | |
| 652 | \\ if ((a != 0) and (c != 0)) return 2; | |
| 710 | \\ if ((b != 0) and (c != null)) return 1; | |
| 711 | \\ if ((a != 0) and (c != null)) return 2; | |
| 653 | 712 | \\ if ((a != 0) or (b != 0)) return 3; |
| 654 | \\ if ((b != 0) or (c != 0)) return 4; | |
| 655 | \\ if ((a != 0) or (c != 0)) return 5; | |
| 713 | \\ if ((b != 0) or (c != null)) return 4; | |
| 714 | \\ if ((a != 0) or (c != null)) return 5; | |
| 656 | 715 | \\ return 6; |
| 657 | 716 | \\} |
| 658 | 717 | ); |
| ... | ... | @@ -832,7 +891,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 832 | 891 | \\} |
| 833 | 892 | , |
| 834 | 893 | \\pub export fn foo() [*c]c_int { |
| 835 | \\ return 0; | |
| 894 | \\ return null; | |
| 836 | 895 | \\} |
| 837 | 896 | ); |
| 838 | 897 | |
| ... | ... | @@ -1334,7 +1393,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1334 | 1393 | \\} |
| 1335 | 1394 | , |
| 1336 | 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 | ); |
| 1340 | 1399 | |
| ... | ... | @@ -1360,7 +1419,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1360 | 1419 | \\ return !(a == 0); |
| 1361 | 1420 | \\ return !(a != 0); |
| 1362 | 1421 | \\ return !(b != 0); |
| 1363 | \\ return !(c != 0); | |
| 1422 | \\ return !(c != null); | |
| 1364 | 1423 | \\} |
| 1365 | 1424 | ); |
| 1366 | 1425 | |
| ... | ... | @@ -1417,7 +1476,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1417 | 1476 | \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { |
| 1418 | 1477 | \\ if (a != 0) return 0; |
| 1419 | 1478 | \\ if (b != 0) return 1; |
| 1420 | \\ if (c != 0) return 2; | |
| 1479 | \\ if (c != null) return 2; | |
| 1421 | 1480 | \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3; |
| 1422 | 1481 | \\ return 4; |
| 1423 | 1482 | \\} |
| ... | ... | @@ -1434,7 +1493,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1434 | 1493 | \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { |
| 1435 | 1494 | \\ while (a != 0) return 0; |
| 1436 | 1495 | \\ while (b != 0) return 1; |
| 1437 | \\ while (c != 0) return 2; | |
| 1496 | \\ while (c != null) return 2; | |
| 1438 | 1497 | \\ return 3; |
| 1439 | 1498 | \\} |
| 1440 | 1499 | ); |
| ... | ... | @@ -1450,7 +1509,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1450 | 1509 | \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { |
| 1451 | 1510 | \\ while (a != 0) return 0; |
| 1452 | 1511 | \\ while (b != 0) return 1; |
| 1453 | \\ while (c != 0) return 2; | |
| 1512 | \\ while (c != null) return 2; | |
| 1454 | 1513 | \\ return 3; |
| 1455 | 1514 | \\} |
| 1456 | 1515 | ); |
| ... | ... | @@ -1497,14 +1556,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1497 | 1556 | \\} |
| 1498 | 1557 | ); |
| 1499 | 1558 | |
| 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 | 1559 | cases.addC( |
| 1509 | 1560 | "u integer suffix after 0 (zero) in macro definition", |
| 1510 | 1561 | "#define ZERO 0U", |
| ... | ... | @@ -1553,33 +1604,101 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1553 | 1604 | "pub const NOT_ZERO = ~c_uint(0);", |
| 1554 | 1605 | ); |
| 1555 | 1606 | |
| 1556 | // cases.add("empty array with initializer", | |
| 1557 | // "int a[4] = {};" | |
| 1558 | // , | |
| 1559 | // "pub var a: [4]c_int = [1]c_int{0} ** 4;" | |
| 1560 | // ); | |
| 1561 | ||
| 1562 | // cases.add("array with initialization", | |
| 1563 | // "int a[4] = {1, 2, 3, 4};" | |
| 1564 | // , | |
| 1565 | // "pub var a: [4]c_int = [4]c_int{1, 2, 3, 4};" | |
| 1566 | // ); | |
| 1567 | ||
| 1568 | // cases.add("array with incomplete initialization", | |
| 1569 | // "int a[4] = {3, 4};" | |
| 1570 | // , | |
| 1571 | // "pub var a: [4]c_int = [2]c_int{3, 4} ++ ([1]c_int{0} ** 2);" | |
| 1572 | // ); | |
| 1573 | ||
| 1574 | // cases.add("2D array with initialization", | |
| 1575 | // "int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };" | |
| 1576 | // , | |
| 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}};" | |
| 1578 | // ); | |
| 1579 | ||
| 1580 | // cases.add("2D array with incomplete initialization", | |
| 1581 | // "int a[3][3] = { {1, 2}, {4, 5, 6} };" | |
| 1582 | // , | |
| 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};" | |
| 1584 | // ); | |
| 1607 | cases.addC("implicit casts", | |
| 1608 | \\#include <stdbool.h> | |
| 1609 | \\ | |
| 1610 | \\void fn_int(int x); | |
| 1611 | \\void fn_f32(float x); | |
| 1612 | \\void fn_f64(double x); | |
| 1613 | \\void fn_char(char x); | |
| 1614 | \\void fn_bool(bool x); | |
| 1615 | \\void fn_ptr(void *x); | |
| 1616 | \\ | |
| 1617 | \\void call(int q) { | |
| 1618 | \\ fn_int(3.0f); | |
| 1619 | \\ fn_int(3.0); | |
| 1620 | \\ fn_int(3.0L); | |
| 1621 | \\ fn_int('ABCD'); | |
| 1622 | \\ fn_f32(3); | |
| 1623 | \\ fn_f64(3); | |
| 1624 | \\ fn_char('3'); | |
| 1625 | \\ fn_char('\x1'); | |
| 1626 | \\ fn_char(0); | |
| 1627 | \\ fn_f32(3.0f); | |
| 1628 | \\ fn_f64(3.0); | |
| 1629 | \\ fn_bool(123); | |
| 1630 | \\ fn_bool(0); | |
| 1631 | \\ fn_bool(&fn_int); | |
| 1632 | \\ fn_int(&fn_int); | |
| 1633 | \\ fn_ptr(42); | |
| 1634 | \\} | |
| 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 | } |